@polycode-projects/the-mechanical-code-talker 6.0.21 → 7.0.0
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 +5 -15
- package/bin/tmct.mjs +8 -3
- package/package.json +1 -5
- package/src/adapters/memory/core.mjs +108 -96
- package/src/domain/agent-traits.mjs +1 -1
- package/src/domain/answer-variants.json +1 -1
- package/src/domain/cli-verbs.mjs +1 -0
- package/src/domain/memory/causal-stability.mjs +22 -5
- package/src/domain/memory/fact-order.mjs +3 -3
- package/src/domain/memory/provenance-time.mjs +35 -0
- package/src/domain/memory/retraction.mjs +3 -5
- package/src/domain/memory/trust.mjs +11 -11
- package/src/domain/news-feed.mjs +1 -1
- package/src/domain/seeded-random.mjs +6 -6
- package/src/services/adventure.mjs +10 -41
- package/src/services/chat-page-viz.mjs +12 -1111
- package/src/services/chat-session.mjs +20 -6
- package/src/services/chat.mjs +269 -197
- package/src/services/extract-facts.mjs +1 -1
- package/src/services/import-file.mjs +1 -1
- package/src/services/mud-viz.mjs +21 -1082
- package/src/services/mudiii-viz.mjs +0 -4
- package/src/services/pill-complete.mjs +5 -8
- package/src/services/predator-prey.mjs +3 -5
- package/src/surfaces/web/memory-ask-browser.bundle.js +107 -107
- package/src/surfaces/web/mud-browser-entry.mjs +8 -48
- package/test-benchmarks/agentbench/README.md +7 -10
- package/src/adapters/p2p/webrtc-transport.mjs +0 -169
- package/src/domain/p2p/facts.mjs +0 -102
- package/src/domain/p2p/peer-id.mjs +0 -47
- package/src/domain/p2p/provenance-relabel.mjs +0 -37
- package/src/domain/p2p/sync-filter.mjs +0 -43
- package/src/domain/p2p/wire.mjs +0 -126
- package/src/services/p2p-room.mjs +0 -848
- package/src/services/share-overlay-viz.mjs +0 -623
- package/src/surfaces/web/p2p-browser-entry.mjs +0 -39
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// memory/provenance-time.mjs — reading "when" off a fact's provenance tag.
|
|
2
|
+
//
|
|
3
|
+
// A fact's provenance is a " | "-joined union of tags, because appendFacts
|
|
4
|
+
// unions a fresh tag onto the SAME fact id when a triple is asserted again
|
|
5
|
+
// rather than minting a second row. So "when was this most recently true" is a
|
|
6
|
+
// question about the newest segment, not about the string as a whole.
|
|
7
|
+
import { provenanceTagToSource } from "./trust.mjs";
|
|
8
|
+
|
|
9
|
+
/** The newest asserted-at timestamp across every segment of `provenance`, in
|
|
10
|
+
* milliseconds. Null when no segment parses to a timestamp at all. */
|
|
11
|
+
export function latestProvenanceTimestamp(provenance) {
|
|
12
|
+
const tag = String(provenance || "");
|
|
13
|
+
if (!tag) return null;
|
|
14
|
+
let latest = null;
|
|
15
|
+
for (const segment of tag.split(" | ")) {
|
|
16
|
+
const source = provenanceTagToSource(segment);
|
|
17
|
+
const at = source?.createdAt ? Date.parse(source.createdAt) : NaN;
|
|
18
|
+
if (!Number.isNaN(at) && (latest === null || at > latest)) latest = at;
|
|
19
|
+
}
|
|
20
|
+
return latest;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** The latest-by-timestamp row for a subject+predicate pair — the "current
|
|
24
|
+
* value" read for an add-only fact that is never retracted. A first-wins read
|
|
25
|
+
* takes the oldest of these instead. */
|
|
26
|
+
export function latestFact(rows, subject, predicate) {
|
|
27
|
+
let best = null;
|
|
28
|
+
let bestAt = -Infinity;
|
|
29
|
+
for (const row of rows) {
|
|
30
|
+
if (row.subject !== subject || row.predicate !== predicate) continue;
|
|
31
|
+
const at = latestProvenanceTimestamp(row.provenance) ?? -Infinity;
|
|
32
|
+
if (at > bestAt) { best = row; bestAt = at; }
|
|
33
|
+
}
|
|
34
|
+
return best;
|
|
35
|
+
}
|
|
@@ -23,17 +23,15 @@
|
|
|
23
23
|
// Max is a join too, so that field merges in either order and agrees.
|
|
24
24
|
//
|
|
25
25
|
// Pure: this module plans, merges and encodes retraction RECORDS. core.mjs owns
|
|
26
|
-
// the store
|
|
27
|
-
//
|
|
26
|
+
// the store. Its own class, its own id suffix and its own predicate keep it
|
|
27
|
+
// clear of compaction — a compacted record and a
|
|
28
28
|
// retracted one mean opposite things, and one namespace would let a summary
|
|
29
29
|
// read as a tombstone. The CRDT vocabulary above is pinned in
|
|
30
30
|
// docs/references/papers/crdt.md.
|
|
31
31
|
|
|
32
32
|
export const RETRACTION_CLASS = "Retraction";
|
|
33
33
|
|
|
34
|
-
/** The predicate a retraction travels under.
|
|
35
|
-
* own, because a retraction has to cross a wire that a chat room gates on
|
|
36
|
-
* provenance kind and a mud room gates on world predicates. */
|
|
34
|
+
/** The predicate a retraction travels under. */
|
|
37
35
|
export const RETRACTION_PREDICATE = "mgx:retracted";
|
|
38
36
|
|
|
39
37
|
export const RETRACTED_RECORD_IDS_PROP = "mgx:retractedRecordIds";
|
|
@@ -33,12 +33,12 @@ function parseChatTagRest(rest) {
|
|
|
33
33
|
const PEER_NODE_MARKER = "#node:";
|
|
34
34
|
const PEER_TAG_PREFIX = "peer:";
|
|
35
35
|
|
|
36
|
-
/** `peer:<displayName>#node:<nodeId>@<ts>` — the
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
/** `peer:<displayName>#node:<nodeId>@<ts>` — the shape a tag takes when it
|
|
37
|
+
* names the node that authored it. The node id is the origin's stable
|
|
38
|
+
* identity and the only part that keys the Source; the display name is
|
|
39
39
|
* user-chosen, mutable and collidable, so it records who to SHOW, not who it
|
|
40
40
|
* is — the same discipline `child:`'s term and `world:`'s turn segments hold.
|
|
41
|
-
* Null for anything without the segment, so
|
|
41
|
+
* Null for anything without the segment, so a tag missing it falls through to
|
|
42
42
|
* the plain teach parse unchanged. */
|
|
43
43
|
function parsePeerNodeTagRest(rest) {
|
|
44
44
|
if (!rest.startsWith(PEER_TAG_PREFIX)) return null;
|
|
@@ -79,11 +79,11 @@ function parsePeerNodeTagRest(rest) {
|
|
|
79
79
|
* teach:chat:<session>@<ts> -> { kind:"teach", createdAt:<ts>, sessionId:<session> }
|
|
80
80
|
* teach:peer:<name>#node:<id>@<ts>
|
|
81
81
|
* -> { kind:"teachNode", nodeId:<id>, displayName:<name>, createdAt:<ts> }
|
|
82
|
-
* (a
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
* plain "teach" whose session slot is the whole name
|
|
86
|
-
*
|
|
82
|
+
* (a tag another node authored. The node id keys the Source; the display
|
|
83
|
+
* name is presentation only, so two nodes that chose the same name stay
|
|
84
|
+
* separate Sources. A tag with no `#node:` segment predates the segment
|
|
85
|
+
* and parses as a plain "teach" whose session slot is the whole name, so
|
|
86
|
+
* a store holding both shapes reads both.)
|
|
87
87
|
* web:<url> | url:<url> -> { kind:"web", url:<url> }
|
|
88
88
|
* reference:<pack>:<article>[@revid] -> { kind:"reference", pack, article }
|
|
89
89
|
* (split on the first two colons only; the article keeps any @revid and
|
|
@@ -198,8 +198,8 @@ export function provenanceTagToSource(tag) {
|
|
|
198
198
|
}
|
|
199
199
|
if (head.startsWith("teach:")) {
|
|
200
200
|
const rest = head.slice("teach:".length);
|
|
201
|
-
// teach:peer:<name>#node:<id>@<ts> — a
|
|
202
|
-
//
|
|
201
|
+
// teach:peer:<name>#node:<id>@<ts> — a tag another node authored, keyed on
|
|
202
|
+
// the node id rather than the name beside it.
|
|
203
203
|
const peerNode = parsePeerNodeTagRest(rest);
|
|
204
204
|
if (peerNode) return peerNode;
|
|
205
205
|
// the chat teach lane's natural frames — chat.mjs's teachProvenanceTag
|
package/src/domain/news-feed.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// sub-graphs, assemble news items, and render the fixed paraphrase paragraph
|
|
3
3
|
// (PLAN_NEWS_FEED.md sections 8.2-8.3). Pure throughout: no clock, no I/O, no
|
|
4
4
|
// reliance on the caller's row order — feeding one fact set in two different
|
|
5
|
-
// orders yields byte-identical items, the same discipline
|
|
5
|
+
// orders yields byte-identical items, the same discipline rows.mjs's
|
|
6
6
|
// sortFactIndividualsById holds for a CRDT-merged fact set.
|
|
7
7
|
|
|
8
8
|
import { sha256Bytes, normFactTerm } from "./hash.mjs";
|
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
// it. Both are pure arithmetic (no I/O, no imports), so a seed reproduces the
|
|
4
4
|
// same sequence on every machine and every run.
|
|
5
5
|
//
|
|
6
|
-
// The bench case generators (infbench
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
6
|
+
// The bench case generators (infbench) draw their committed fixtures through
|
|
7
|
+
// these, so the byte sequence they produce is part of those artifacts' identity:
|
|
8
|
+
// two callers on one seed must shuffle identically or the committed cases.jsonl
|
|
9
|
+
// drifts. That is the same reason the content-address hashes live once in
|
|
10
|
+
// hash.mjs beside this file — a deterministic primitive shared across writers has
|
|
11
|
+
// exactly one definition.
|
|
12
12
|
|
|
13
13
|
/** mulberry32 PRNG — small, seedable, deterministic across platforms. */
|
|
14
14
|
export function mulberry32(seed) {
|
|
@@ -181,13 +181,13 @@ async function resumedPosition(memoryDir) {
|
|
|
181
181
|
|
|
182
182
|
// ---- the world-state fold ----------------------------------------------------
|
|
183
183
|
|
|
184
|
-
/** Which run of the world a store is on. Recasting a
|
|
184
|
+
/** Which run of the world a store is on. Recasting a world (mud.html's
|
|
185
185
|
* RESET, a slider, the scenario dropdown) reopens the same deterministic
|
|
186
|
-
* instance ids over a fresh store
|
|
187
|
-
*
|
|
188
|
-
* over. It is an ordinary add-only fact: each recast
|
|
189
|
-
* the fold takes the max, and merging two
|
|
190
|
-
* is order-free. */
|
|
186
|
+
* instance ids over a fresh store, so the old run's snapshots can still be
|
|
187
|
+
* sitting in a store somewhere — this marker is how every reader agrees the
|
|
188
|
+
* world has started over. It is an ordinary add-only fact: each recast
|
|
189
|
+
* appends a larger value, the fold takes the max, and merging two stores
|
|
190
|
+
* converges because max is order-free. */
|
|
191
191
|
export const WORLD_EPOCH_PREDICATE = "mgx:world-epoch";
|
|
192
192
|
const WORLD_EPOCH_SUBJECT = "world";
|
|
193
193
|
|
|
@@ -257,36 +257,6 @@ export function worldActionRows(rows) {
|
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
-
// The predicates a played turn can write. Every one of them already exists
|
|
261
|
-
// above as a private constant; this set is the one place they are gathered so
|
|
262
|
-
// a caller outside this file can ask "is this fact part of the live world"
|
|
263
|
-
// without learning each name. rdf:type and the display name earn their place
|
|
264
|
-
// alongside the folded ones: a dug room and a dug object are minted mid-play,
|
|
265
|
-
// and a reader that never receives their class or their plain name cannot draw
|
|
266
|
-
// them at all.
|
|
267
|
-
const MUD_STATE_PREDICATES = new Set([
|
|
268
|
-
...PLACEMENT_PREDICATES,
|
|
269
|
-
...POSITION_PREDICATES,
|
|
270
|
-
OPEN_PREDICATE,
|
|
271
|
-
MASS_PREDICATE,
|
|
272
|
-
KNOWS_ABOUT_PREDICATE,
|
|
273
|
-
DISPLAY_NAME_PREDICATE,
|
|
274
|
-
"rdf:type",
|
|
275
|
-
// Which run the world is on IS live world state: a peer that misses the
|
|
276
|
-
// recast marker keeps folding the old run's snapshots as current.
|
|
277
|
-
WORLD_EPOCH_PREDICATE,
|
|
278
|
-
]);
|
|
279
|
-
|
|
280
|
-
/** Whether `predicate` carries live world state — where a thing stands, what
|
|
281
|
-
* it weighs, whether it is open, what somebody knows, which way a room leads,
|
|
282
|
-
* and the class and name a dug thing is minted with. The P2P sync filter
|
|
283
|
-
* reads this to tell a fact a turn produced from the page chrome around it.
|
|
284
|
-
* Pure. */
|
|
285
|
-
export function isMudStatePredicate(predicate) {
|
|
286
|
-
const p = String(predicate || "");
|
|
287
|
-
return MUD_STATE_PREDICATES.has(p) || EXIT_PREDICATE_RE.test(p);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
260
|
/** Every individual the world names — its rooms, its cast, its props, and
|
|
291
261
|
* anything dug up since — as the plain id strings a parser has to have
|
|
292
262
|
* DECLARED before it can resolve them. @turnN snapshots are skipped: a
|
|
@@ -308,7 +278,7 @@ export function worldIndividualNames(rows) {
|
|
|
308
278
|
* stored), and the epoch itself.
|
|
309
279
|
*
|
|
310
280
|
* Rows rank by the (epoch, turn) pair, so a recast can never be outranked by
|
|
311
|
-
* the run it replaced: a
|
|
281
|
+
* the run it replaced: a turn-9 snapshot from before the recast loses
|
|
312
282
|
* to a turn-1 snapshot written after it. Base rows carry no stamp of their
|
|
313
283
|
* own and rank as turn 0 of the CURRENT epoch — a recast re-seeds the same
|
|
314
284
|
* deterministic ids, so the shard's own rows are exactly the state the new
|
|
@@ -653,10 +623,9 @@ async function writeWorldTurn(memoryDir, world, k, facts, cache) {
|
|
|
653
623
|
// the last carrot appends a SECOND claim to the same edge, tagged `:gone`, and
|
|
654
624
|
// appendFacts unions the two tags onto the one fact exactly as it unions any
|
|
655
625
|
// repeat assertion. "The carrot was here on turn 2" and "the carrot is gone on
|
|
656
|
-
// turn 5" are both true; the reader's job is to say which one rules
|
|
657
|
-
//
|
|
658
|
-
//
|
|
659
|
-
// ever made.
|
|
626
|
+
// turn 5" are both true; the reader's job is to say which one rules. So
|
|
627
|
+
// reading knowledge back means reading the newest claim per edge, never the
|
|
628
|
+
// union of every claim ever made.
|
|
660
629
|
|
|
661
630
|
const VOIDED_TESTIMONY_SUFFIX = ":gone";
|
|
662
631
|
|