@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.
- 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
|
@@ -652,76 +652,101 @@ async function writeWorldTurn(memoryDir, world, k, facts, cache) {
|
|
|
652
652
|
|
|
653
653
|
const VOIDED_TESTIMONY_SUFFIX = ":gone";
|
|
654
654
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
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
|
|
667
|
-
* the subject — it is the one who now knows — and the teller is named
|
|
668
|
-
* provenance, so the claim corroborates the teller's Source, not the
|
|
669
|
-
|
|
670
|
-
|
|
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
|
|
674
|
-
* the subject and the provenance's character: it learned this by
|
|
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`
|
|
681
|
-
* last of it. Written as a fresh claim on the SAME edge an older one
|
|
682
|
-
* sits on, so the older claim stands untouched and stops being the one
|
|
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:
|
|
693
|
-
*
|
|
694
|
-
*
|
|
695
|
-
* hearsay stamped with whatever turn it
|
|
696
|
-
|
|
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
|
|
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[
|
|
721
|
+
voided: !!(mine && mine[4]),
|
|
703
722
|
};
|
|
704
723
|
}
|
|
705
724
|
|
|
706
|
-
/**
|
|
707
|
-
* takes the tie — an animal that examined a carrot
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
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.
|
|
713
|
-
: claim.
|
|
714
|
-
: claim.
|
|
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
|
-
|
|
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
|
|