@polycode-projects/the-mechanical-code-talker 4.1.1 → 4.1.3

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 (55) hide show
  1. package/README.md +31 -18
  2. package/bin/tmct.mjs +3 -0
  3. package/data/templates/responses.jsonl +3 -0
  4. package/package.json +2 -1
  5. package/src/adapters/memory/core.mjs +1358 -196
  6. package/src/adapters/memory/inspect.mjs +11 -0
  7. package/src/adapters/memory/shacl.mjs +38 -0
  8. package/src/adapters/p2p/webrtc-transport.mjs +28 -5
  9. package/src/domain/ask-vocab.mjs +39 -0
  10. package/src/domain/ask.mjs +183 -34
  11. package/src/domain/grammar/assert.mjs +8 -2
  12. package/src/domain/hanoi-board.mjs +232 -0
  13. package/src/domain/ingest-facts.mjs +120 -0
  14. package/src/domain/interpret/normalize.mjs +49 -0
  15. package/src/domain/memory/compaction.mjs +284 -0
  16. package/src/domain/memory/resolution.mjs +171 -0
  17. package/src/domain/memory/trust.mjs +175 -5
  18. package/src/domain/memory-facts.mjs +139 -0
  19. package/src/domain/p2p/facts.mjs +21 -0
  20. package/src/domain/p2p/peer-id.mjs +15 -0
  21. package/src/domain/p2p/provenance-relabel.mjs +13 -2
  22. package/src/domain/p2p/sync-filter.mjs +5 -1
  23. package/src/domain/p2p/wire.mjs +7 -4
  24. package/src/domain/scene-compose.mjs +2 -2
  25. package/src/domain/sprite-facts.mjs +0 -0
  26. package/src/services/adventure-viz.mjs +5 -1
  27. package/src/services/adventure.mjs +70 -44
  28. package/src/services/chat-page-viz.mjs +381 -310
  29. package/src/services/chat.mjs +273 -155
  30. package/src/services/code-explorer-viz.mjs +141 -54
  31. package/src/services/index.mjs +1 -1
  32. package/src/services/ingest-viz.mjs +134 -9
  33. package/src/services/ledger-viz.mjs +7 -4
  34. package/src/services/memory-panel-viz.mjs +8 -3
  35. package/src/services/mud-turn.mjs +11 -8
  36. package/src/services/mud-viz.mjs +441 -206
  37. package/src/services/p2p-room.mjs +110 -23
  38. package/src/services/plan-viz.mjs +63 -4
  39. package/src/services/research-viz.mjs +18 -7
  40. package/src/services/share-overlay-viz.mjs +623 -0
  41. package/src/services/spider-fly-viz.mjs +2 -2
  42. package/src/services/sprite-catalog-viz.mjs +303 -78
  43. package/src/surfaces/web/adventure-browser-entry.mjs +27 -5
  44. package/src/surfaces/web/chat-browser-entry.mjs +37 -10
  45. package/src/surfaces/web/code-explorer-browser-entry.mjs +4 -3
  46. package/src/surfaces/web/ingest-browser-entry.mjs +73 -12
  47. package/src/surfaces/web/ledger-browser-entry.mjs +32 -7
  48. package/src/surfaces/web/memory-ask-browser.bundle.js +149 -116
  49. package/src/surfaces/web/mud-browser-entry.mjs +38 -7
  50. package/src/surfaces/web/p2p-browser-entry.mjs +1 -1
  51. package/src/surfaces/web/plan-browser-entry.mjs +33 -2
  52. package/src/surfaces/web/research-browser-entry.mjs +11 -19
  53. package/src/surfaces/web/sprites-browser-entry.mjs +39 -8
  54. package/src/surfaces/web/tmct-surface.mjs +12 -0
  55. package/src/surfaces/web/turn-session.mjs +10 -3
@@ -652,76 +652,101 @@ async function writeWorldTurn(memoryDir, world, k, facts, cache) {
652
652
 
653
653
  const VOIDED_TESTIMONY_SUFFIX = ":gone";
654
654
 
655
- const characterTestimonyTag = (character, k, voided = false) =>
656
- `mud:${character}:turn${k}${voided ? VOIDED_TESTIMONY_SUFFIX : ""}`;
657
-
658
- async function appendTestimony(memoryDir, { knower, source, thing, k, voided = false, cache }) {
655
+ /** The provenance tag one character's claim carries: who said it, which run of
656
+ * the world it was said in, the turn it was said on, and whether it says the
657
+ * thing has gone. The epoch segment follows snapshotSubject's convention —
658
+ * written only once a recast has moved the world past epoch 0, so an unrecast
659
+ * store and every tag written before epochs existed keep the bare form and
660
+ * read back as epoch 0. */
661
+ export function characterTestimonyTag(character, k, { epoch = 0, voided = false } = {}) {
662
+ const when = epoch > 0 ? `epoch${epoch}:turn${k}` : `turn${k}`;
663
+ return `mud:${character}:${when}${voided ? VOIDED_TESTIMONY_SUFFIX : ""}`;
664
+ }
665
+
666
+ async function appendTestimony(memoryDir, { knower, source, thing, k, epoch = 0, voided = false, cache }) {
659
667
  await appendFacts(memoryDir, [{
660
668
  subject: knower, predicate: KNOWS_ABOUT_PREDICATE, object: thing,
661
- provenance: characterTestimonyTag(source, k, voided),
669
+ provenance: characterTestimonyTag(source, k, { epoch, voided }),
662
670
  }]);
663
671
  if (cache) cache.rows = null;
664
672
  }
665
673
 
666
- /** Record that `teller` told `asker` about `thing` on turn `k`. The asker is
667
- * the subject — it is the one who now knows — and the teller is named in the
668
- * provenance, so the claim corroborates the teller's Source, not the asker's. */
669
- export async function recordTold(memoryDir, { asker, teller, thing, k, cache = null }) {
670
- return appendTestimony(memoryDir, { knower: asker, source: teller, thing, k, cache });
674
+ /** Record that `teller` told `asker` about `thing` on turn `k` of `epoch`. The
675
+ * asker is the subject — it is the one who now knows — and the teller is named
676
+ * in the provenance, so the claim corroborates the teller's Source, not the
677
+ * asker's. */
678
+ export async function recordTold(memoryDir, { asker, teller, thing, k, epoch = 0, cache = null }) {
679
+ return appendTestimony(memoryDir, { knower: asker, source: teller, thing, k, epoch, cache });
671
680
  }
672
681
 
673
- /** Record that `observer` examined `thing` on turn `k`. The observer is both
674
- * the subject and the provenance's character: it learned this by looking, so
675
- * it is its own source for it. */
676
- export async function recordExamined(memoryDir, { observer, thing, k, cache = null }) {
677
- return appendTestimony(memoryDir, { knower: observer, source: observer, thing, k, cache });
682
+ /** Record that `observer` examined `thing` on turn `k` of `epoch`. The observer
683
+ * is both the subject and the provenance's character: it learned this by
684
+ * looking, so it is its own source for it. */
685
+ export async function recordExamined(memoryDir, { observer, thing, k, epoch = 0, cache = null }) {
686
+ return appendTestimony(memoryDir, { knower: observer, source: observer, thing, k, epoch, cache });
678
687
  }
679
688
 
680
- /** Record that `observer` saw `thing` leave the world on turn `k` it ate the
681
- * last of it. Written as a fresh claim on the SAME edge an older one already
682
- * sits on, so the older claim stands untouched and stops being the one that
683
- * rules. The observer is its own source, the way examining is. */
684
- export async function recordGone(memoryDir, { observer, thing, k, cache = null }) {
685
- return appendTestimony(memoryDir, { knower: observer, source: observer, thing, k, voided: true, cache });
689
+ /** Record that `observer` saw `thing` leave the world on turn `k` of `epoch`
690
+ * it ate the last of it. Written as a fresh claim on the SAME edge an older one
691
+ * already sits on, so the older claim stands untouched and stops being the one
692
+ * that rules. The observer is its own source, the way examining is. */
693
+ export async function recordGone(memoryDir, { observer, thing, k, epoch = 0, cache = null }) {
694
+ return appendTestimony(memoryDir, { knower: observer, source: observer, thing, k, epoch, voided: true, cache });
686
695
  }
687
696
 
688
- const TESTIMONY_TAG_RE = /^mud:([^:\s]+):turn(\d+)(:gone)?$/;
697
+ const TESTIMONY_TAG_RE = /^mud:([^:\s]+):(?:epoch(\d+):)?turn(\d+)(:gone)?$/;
689
698
  const TURN_STAMP_RE = /:turn(\d+)\b/;
690
699
 
691
700
  /** How one provenance segment on a knows-about edge stands as a claim about
692
- * what `knower` knows: whether the knower vouches for it itself, the turn it
693
- * was asserted on, and whether it says the thing is gone. A tag that is no
694
- * character's testimony a world's own seed fact, a dig spawnreads as
695
- * hearsay stamped with whatever turn it carries. */
696
- function testimonyClaim(segment, knower) {
701
+ * what `knower` knows: which run of the world it was made in, whether the
702
+ * knower vouches for it itself, the turn it was asserted on, and whether it
703
+ * says the thing is gone. A tag that is no character's testimony a world's
704
+ * own seed fact, a dig spawn — reads as hearsay stamped with whatever turn it
705
+ * carries.
706
+ *
707
+ * Epoch reads the same way foldWorldState reads a row's: a stamped tag names
708
+ * its own run, a tag stamped with a turn but no epoch was written on epoch 0
709
+ * (or before epochs existed), and a tag with no turn at all is a seed the
710
+ * world lays down fresh on every recast, so it belongs to the run being read
711
+ * now. */
712
+ function testimonyClaim(segment, knower, currentEpoch = 0) {
697
713
  const mine = TESTIMONY_TAG_RE.exec(segment);
698
- const stamp = Number(mine ? mine[2] : (TURN_STAMP_RE.exec(segment)?.[1] ?? 0));
714
+ const turnStamp = mine ? mine[3] : TURN_STAMP_RE.exec(segment)?.[1];
715
+ const stamp = Number(turnStamp ?? 0);
716
+ const epochStamp = mine?.[2];
699
717
  return {
718
+ epoch: epochStamp ? Number(epochStamp) : (turnStamp === undefined ? currentEpoch : 0),
700
719
  firsthand: !!mine && mine[1] === knower,
701
720
  turn: Number.isFinite(stamp) ? stamp : 0,
702
- voided: !!(mine && mine[3]),
721
+ voided: !!(mine && mine[4]),
703
722
  };
704
723
  }
705
724
 
706
- /** Firsthand beats hearsay outright, then the later turn wins, then "gone"
707
- * takes the tie — an animal that examined a carrot and ate it on one turn ate
708
- * it second. Tier ABOVE recency is what stops an animal being talked back into
709
- * a meal it ate itself: a room-mate can tell it about that carrot the turn
710
- * after, and its own eyes still hold. */
725
+ /** The later epoch beats everything, then firsthand beats hearsay, then the
726
+ * later turn wins, then "gone" takes the tie — an animal that examined a carrot
727
+ * and ate it on one turn ate it second.
728
+ *
729
+ * Epoch on top mirrors the world-state fold: a recast starts the world over, so
730
+ * nothing said in the run it replaced can rule over what a character has seen
731
+ * since, however late in that old run it was said or however firsthand. Within
732
+ * one run, firsthand sits above recency, and that is what stops an animal being
733
+ * talked back into a meal it ate itself: a room-mate can tell it about that
734
+ * carrot the turn after, and its own eyes still hold. */
711
735
  const outranksClaim = (claim, best) => (
712
- claim.firsthand !== best.firsthand ? claim.firsthand
713
- : claim.turn !== best.turn ? claim.turn > best.turn
714
- : claim.voided && !best.voided
736
+ claim.epoch !== best.epoch ? claim.epoch > best.epoch
737
+ : claim.firsthand !== best.firsthand ? claim.firsthand
738
+ : claim.turn !== best.turn ? claim.turn > best.turn
739
+ : claim.voided && !best.voided
715
740
  );
716
741
 
717
742
  /** The claim that rules on one knows-about edge, across every segment its
718
743
  * provenance carries. */
719
- function rulingTestimonyClaim(provenance, knower) {
744
+ function rulingTestimonyClaim(provenance, knower, currentEpoch = 0) {
720
745
  let best = null;
721
746
  for (const segment of String(provenance || "").split(" | ")) {
722
747
  const tag = segment.trim();
723
748
  if (!tag) continue;
724
- const claim = testimonyClaim(tag, knower);
749
+ const claim = testimonyClaim(tag, knower, currentEpoch);
725
750
  if (!best || outranksClaim(claim, best)) best = claim;
726
751
  }
727
752
  return best;
@@ -730,12 +755,13 @@ function rulingTestimonyClaim(provenance, knower) {
730
755
  /** What `person` knows about NOW: the object of every knows-about edge whose
731
756
  * ruling claim still stands, in the order the edges were first written.
732
757
  * Nothing is deleted — an edge whose newest claim says the thing is gone just
733
- * stops reading back. */
734
- function currentKnowsAboutTopics(rows, person) {
758
+ * stops reading back. `currentEpoch` is the run the reader is on, so a claim a
759
+ * recast has left behind cannot decide what a character knows today. */
760
+ function currentKnowsAboutTopics(rows, person, currentEpoch = 0) {
735
761
  const topics = [];
736
762
  for (const row of rows || []) {
737
763
  if (row.subject !== person || row.predicate !== KNOWS_ABOUT_PREDICATE) continue;
738
- if (rulingTestimonyClaim(row.provenance, person)?.voided) continue;
764
+ if (rulingTestimonyClaim(row.provenance, person, currentEpoch)?.voided) continue;
739
765
  topics.push(row.object);
740
766
  }
741
767
  return topics;
@@ -1291,7 +1317,7 @@ export function personKnowledgeLines(rows, state, person) {
1291
1317
  ? `you'll find the ${thing} in the ${place.object}.`
1292
1318
  : `the ${thing} is in the ${place.object}.`);
1293
1319
  }
1294
- return { lines, aboutTopics: currentKnowsAboutTopics(rows, person) };
1320
+ return { lines, aboutTopics: currentKnowsAboutTopics(rows, person, state?.epoch ?? 0) };
1295
1321
  }
1296
1322
 
1297
1323
  /** The FOOD_CLASS things `person` durably knows about — from being told, or
@@ -1302,7 +1328,7 @@ export function personKnowledgeLines(rows, state, person) {
1302
1328
  * food query has no per-topic sub-digest to hand back, so this returns the
1303
1329
  * plain list of known food things rather than a {lines, topics} pair. Pure. */
1304
1330
  export function personKnownFoodLines(rows, state, person) {
1305
- return currentKnowsAboutTopics(rows, person)
1331
+ return currentKnowsAboutTopics(rows, person, state?.epoch ?? 0)
1306
1332
  .filter((thing) => objectClassChain(rows, thing).includes(FOOD_CLASS));
1307
1333
  }
1308
1334