@polycode-projects/the-mechanical-code-talker 5.0.5 → 5.0.7

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 (46) hide show
  1. package/README.md +78 -19
  2. package/bin/tmct.mjs +63 -2
  3. package/package.json +1 -1
  4. package/src/adapters/memory/core.mjs +23 -0
  5. package/src/domain/ask-vocab.mjs +19 -0
  6. package/src/domain/ask.mjs +10 -5
  7. package/src/domain/codegraph.mjs +23 -9
  8. package/src/domain/game-config.mjs +12 -0
  9. package/src/domain/interpret/strategies/keywords.mjs +30 -1
  10. package/src/domain/memory/capability.mjs +15 -11
  11. package/src/domain/router/drive.mjs +36 -17
  12. package/src/domain/router/resolver.mjs +63 -17
  13. package/src/domain/spider-fly-world.mjs +2 -2
  14. package/src/domain/sprite-templates.mjs +19 -7
  15. package/src/domain/syllogise.mjs +16 -6
  16. package/src/domain/town-square-world.mjs +1 -1
  17. package/src/services/adventure-viz.mjs +5 -2
  18. package/src/services/adventure.mjs +8 -1
  19. package/src/services/chat-page-viz.mjs +123 -25
  20. package/src/services/chat-session.mjs +60 -10
  21. package/src/services/chat.mjs +328 -36
  22. package/src/services/code-explorer-viz.mjs +3 -2
  23. package/src/services/extract-facts.mjs +47 -7
  24. package/src/services/ingest-viz.mjs +113 -29
  25. package/src/services/ledger-viz.mjs +9 -4
  26. package/src/services/memory-panel-viz.mjs +44 -0
  27. package/src/services/mud-viz.mjs +21 -3
  28. package/src/services/mudiii-scene.mjs +407 -36
  29. package/src/services/mudiii-turn.mjs +65 -9
  30. package/src/services/mudiii-viz.mjs +810 -157
  31. package/src/services/p2p-room.mjs +1 -1
  32. package/src/services/plan-viz.mjs +26 -4
  33. package/src/services/predator-prey.mjs +141 -37
  34. package/src/services/research-viz.mjs +17 -23
  35. package/src/services/spider-fly-turn.mjs +7 -1
  36. package/src/services/spider-fly-viz.mjs +13 -5
  37. package/src/services/sprite-catalog-viz.mjs +3 -2
  38. package/src/services/viz-theme.mjs +20 -0
  39. package/src/services/viz-ticker.mjs +15 -2
  40. package/src/surfaces/http/server-http.mjs +90 -13
  41. package/src/surfaces/web/memory-ask-browser.bundle.js +125 -125
  42. package/src/surfaces/web/mud-browser-entry.mjs +33 -1
  43. package/src/surfaces/web/mudiii-browser-entry.mjs +70 -34
  44. package/src/surfaces/web/tmct-surface.mjs +18 -6
  45. package/src/tools/handlers/tmct-ask.mjs +15 -2
  46. package/src/tools/server.mjs +31 -2
@@ -3,9 +3,9 @@
3
3
  // command, the addressed teach-frame (extended to the food channel spider-fly
4
4
  // has no equivalent of), the bare "tick" command, the player's own food-
5
5
  // placement verb, and the belief and orientation asides. The fifth lane on
6
- // the shared plan slot, shaped exactly like spider-fly-turn.mjs (PLAN_MUD_
7
- // MUDIII.md, "The chat lane") with vocabulary from predator-prey.mjs's own
8
- // MUDIII_ROLES: fox hunts goblin, goblins forage crumbs and morsels.
6
+ // the shared plan slot, shaped exactly like spider-fly-turn.mjs, with
7
+ // vocabulary from predator-prey.mjs's own MUDIII_ROLES: fox hunts goblin,
8
+ // goblins forage crumbs and morsels.
9
9
  //
10
10
  // This module never plans a move or runs the ecology pass itself — every bit
11
11
  // of game logic (fold, pathfinding, belief, ecology, food placement) lives in
@@ -21,7 +21,7 @@ import {
21
21
  MUDIII_ROLES, foldTownSquareState, startTownSquareGame, runTownSquareTick,
22
22
  placeFood, roleOfId, beliefSnapshotFor,
23
23
  } from "./predator-prey.mjs";
24
- import { snapshotSubject } from "./adventure.mjs";
24
+ import { snapshotSubject, parseSnapshotSubject } from "./adventure.mjs";
25
25
  import { correctMisspellings, QUESTION_LEAD_RE } from "../domain/interpret/normalize.mjs";
26
26
  import { worldProvenanceTag } from "../domain/worlds-pack.mjs";
27
27
  import { getWorldsPackProvider } from "../adapters/corpus/worlds-pack.mjs";
@@ -424,6 +424,63 @@ export function believedFactSentence(id, believedCell) {
424
424
  return believedCell ? `${id} is at ${believedCell}.` : `${id} has not been observed.`;
425
425
  }
426
426
 
427
+ // The mark both visitor-driven write paths stamp on a placement row: the teach
428
+ // lane's `world:<name>:taught:turnK`, and placeFood's own, which builds the
429
+ // same tag. The board's own ticks write the bare world tag with no such mark.
430
+ const TAUGHT_PROVENANCE_MARK = ":taught:";
431
+
432
+ /** Every subject standing where a VISITOR put it — taught into place by a
433
+ * sentence, or dropped there by the food verb. Both write the same
434
+ * `:taught:turnK` provenance, and the board's own ticks write none of it.
435
+ *
436
+ * Reads the row that WON, ranked the way foldTownSquareState ranks a
437
+ * placement, so a crumb a visitor moved and the board has since moved on from
438
+ * no longer counts. `epoch` is the fold's own, which unstamped rows (a
439
+ * hand-built fixture, a seed row) are ranked at. Pure. */
440
+ export function taughtPlacementSubjects(factRows, epoch = 0) {
441
+ const winner = new Map(); // subject -> { epoch, turn, taught }
442
+ for (const row of factRows || []) {
443
+ if (row.predicate !== PLACEMENT_PREDICATE) continue;
444
+ const snap = parseSnapshotSubject(row.subject);
445
+ const base = snap ? snap.base : row.subject;
446
+ const rowEpoch = snap ? snap.epoch : epoch;
447
+ const turn = snap ? snap.turn : 0;
448
+ const prior = winner.get(base);
449
+ if (prior && !(rowEpoch > prior.epoch || (rowEpoch === prior.epoch && turn >= prior.turn))) continue;
450
+ winner.set(base, { epoch: rowEpoch, turn, taught: String(row.provenance || "").includes(TAUGHT_PROVENANCE_MARK) });
451
+ }
452
+ const taught = new Set();
453
+ for (const [subject, entry] of winner) if (entry.taught) taught.add(subject);
454
+ return taught;
455
+ }
456
+
457
+ /** One observer's whole belief snapshot as a sentence.
458
+ *
459
+ * Anything the observer can place is named: seen, or told. So is anything the
460
+ * visitor put where it stands, seen or not, because the teach lane exists so
461
+ * a claim about ONE individual lands where a visitor can watch it, and an
462
+ * individual that dissolved into a count would take that with it.
463
+ *
464
+ * Everything else unobserved is counted rather than listed. A square at its
465
+ * food cap otherwise answers a question about what a goblin can see with a
466
+ * row of crumbs it cannot, and the list grows with the cap.
467
+ *
468
+ * `beliefEntries` is `Object.entries(beliefSnapshotFor(...))` and
469
+ * `taughtSubjects` a Set from taughtPlacementSubjects. Pure. */
470
+ export function beliefLineFor(observerId, beliefEntries, taughtSubjects) {
471
+ const taught = taughtSubjects || new Set();
472
+ const named = [];
473
+ let unobserved = 0;
474
+ for (const [id, cell] of beliefEntries || []) {
475
+ if (cell || taught.has(id)) named.push(believedFactSentence(id, cell));
476
+ else unobserved += 1;
477
+ }
478
+ if (!named.length && !unobserved) return `${observerId} is alone on the board — nothing else to see.`;
479
+ const rest = unobserved === 1 ? "1 other has not been observed." : `${unobserved} others have not been observed.`;
480
+ if (!named.length) return `${observerId} sees nothing yet. ${rest}`;
481
+ return `${observerId} sees: ${named.join(" ")}${unobserved ? ` ${rest}` : ""}`;
482
+ }
483
+
427
484
  /** "what does the goblin see?" / "what does the fox see?" rendered as plain
428
485
  * text: the same beliefSnapshotFor read predator-prey.mjs's own tick loop
429
486
  * uses, over the CURRENT board state — read-only, no tick runs. Candidates
@@ -431,7 +488,9 @@ export function believedFactSentence(id, believedCell) {
431
488
  * goblin's own forage target), exactly the beliefCandidates set
432
489
  * runTownSquareTick itself builds. toldFacts is empty — a told position only
433
490
  * ever arrives fresh alongside a tick, so there is none standing between
434
- * ticks to read back here. */
491
+ * ticks to read back here. beliefLineFor turns the snapshot into the
492
+ * sentence, naming what the observer can place and what a visitor put where
493
+ * it stands, and counting the rest. */
435
494
  async function mudiiiBeliefAnswer(match, { memoryDir, gameConfig = DEFAULT_GAME_CONFIG }) {
436
495
  const kind = match[1].toLowerCase();
437
496
  const num = match[2];
@@ -451,10 +510,7 @@ async function mudiiiBeliefAnswer(match, { memoryDir, gameConfig = DEFAULT_GAME_
451
510
  ? gameConfig?.mudiii?.predatorVisionRadius
452
511
  : gameConfig?.mudiii?.preyVisionRadius;
453
512
  const belief = beliefSnapshotFor(observerId, observerCell, candidateIds, state, { visionRadius });
454
- const entries = Object.entries(belief);
455
- const text = entries.length
456
- ? `${observerId} sees: ${entries.map(([id, cell]) => believedFactSentence(id, cell)).join(" ")}`
457
- : `${observerId} is alone on the board — nothing else to see.`;
513
+ const text = beliefLineFor(observerId, Object.entries(belief), taughtPlacementSubjects(rows, state.epoch));
458
514
  return {
459
515
  text,
460
516
  lane: "game-inform",