@polycode-projects/the-mechanical-code-talker 2.7.12 → 2.7.13

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.
@@ -0,0 +1,88 @@
1
+ // adventure-browser-entry.mjs — the esbuild entry for the adventure's
2
+ // full-screen/home-page pages (public/adventure-browser.bundle.js, built by
3
+ // scripts/build-adventure-bundle.mjs), mirroring
4
+ // spider-fly-browser-entry.mjs's own session-factory shape.
5
+ //
6
+ // Unlike spider-fly's board, Ashcombe Hall's own facts+rules cannot be
7
+ // regenerated in-browser from a pure JS module — its canonical definition is
8
+ // a Node-only JSONL corpus source, read through an fs/gzip provider the
9
+ // browser cannot run. So this session takes the world as data
10
+ // (`worldPayload`, `{ name, facts, rules, opening }`), embedded into the page
11
+ // at build time by scripts/build-demo-site.mjs's own read through the real
12
+ // worlds-pack provider (see adventure-viz.mjs's header for the full
13
+ // rationale) — the bootstrap below then just appends it, exactly the shape
14
+ // openAdventure() itself writes for a real chat session.
15
+ //
16
+ // This session exposes ONLY a raw autoplay tick and a read-only snapshot —
17
+ // no chat dock. Every state-changing command adventure.mjs's own
18
+ // runWorldCommand issues (go/take/open/...) already re-narrates itself
19
+ // through the extractive completions digest on every turn (the
20
+ // "auto-relook"), so this bundle carries the same wink-nlp/completions
21
+ // dependency chain chat.mjs's own runTurn does; a second, lighter path was
22
+ // not available to duck under it. Nothing here calls runTurn, though — the
23
+ // one entry point exercised is adventureTurn itself, via
24
+ // adventure-autoplay.mjs, which is the "auto-play is a caller of the
25
+ // existing interpreter, never a second one" contract this whole feature
26
+ // rests on.
27
+ import {
28
+ createInMemoryStore, appendFacts, appendRule, loadMemory, readFactRows,
29
+ } from "../../adapters/memory/core.mjs";
30
+ import { foldWorldState, worldDigestRows } from "../../services/adventure.mjs";
31
+ import { runAdventureAutoplayTick } from "../../services/adventure-autoplay.mjs";
32
+ import { resolveSpriteForClass, SPRITE_REGISTRY } from "../../domain/sprite-map.mjs";
33
+
34
+ /** A live in-memory adventure this page's ticker drives one auto-play tick
35
+ * at a time. Returns `{ memoryDir, autoplayTick, snapshot }`.
36
+ * `worldPayload.facts`/`.rules` seed the store exactly the way
37
+ * openAdventure() itself does for a real session; `planHolder.state` is set
38
+ * the same way, so adventureTurn treats every subsequent call as a live,
39
+ * already-open world rather than a fresh opening line. */
40
+ export async function createAdventureSession(worldPayload) {
41
+ const memoryDir = createInMemoryStore();
42
+ const tag = `world:${worldPayload.name}`;
43
+ await appendFacts(memoryDir, worldPayload.facts.map((f) => ({
44
+ subject: f.subject, predicate: f.predicate, object: f.object, provenance: tag,
45
+ })));
46
+ for (const rule of worldPayload.rules) {
47
+ await appendRule(memoryDir, { name: rule.name, kind: rule.ruleKind, slots: rule.slots, provenance: tag });
48
+ }
49
+
50
+ const planHolder = { state: { adventure: { world: worldPayload.name } } };
51
+ const sessionId = globalThis.crypto?.randomUUID?.() ?? String(Date.now());
52
+ let exposedRoomIds = new Set();
53
+ const openingRows = readFactRows(await loadMemory(memoryDir));
54
+ const openingHere = foldWorldState(openingRows).placements.get("player")?.object ?? null;
55
+ if (openingHere) exposedRoomIds = new Set([openingHere]);
56
+
57
+ return {
58
+ memoryDir,
59
+
60
+ /** One auto-play tick: infer the goal, execute exactly one move through
61
+ * adventureTurn (adventure-autoplay.mjs's own contract), thread the
62
+ * exposed-room set forward. Returns runAdventureAutoplayTick's own
63
+ * `{ turn, goal, plan, done, stalled }` unmodified. */
64
+ async autoplayTick() {
65
+ const result = await runAdventureAutoplayTick(memoryDir, {
66
+ exposedRoomIds, planHolder, sessionId, env: {},
67
+ });
68
+ exposedRoomIds = result.exposedRoomIds;
69
+ return result;
70
+ },
71
+
72
+ /** A read-only fold of the current room — no engine advance — for the
73
+ * page's own redraw after boot and after every tick. */
74
+ async snapshot() {
75
+ const rows = readFactRows(await loadMemory(memoryDir));
76
+ const state = foldWorldState(rows);
77
+ const here = state.placements.get("player")?.object ?? null;
78
+ return { rows, state, here, turn: state.turnCount };
79
+ },
80
+ };
81
+ }
82
+
83
+ // Re-exported so the page's own rendering script (adventure-viz.mjs) never
84
+ // has to duplicate sprite resolution or the digest reader — the same posture
85
+ // spider-fly-browser-entry.mjs's own globalThis.tmctSpiderFly re-export takes.
86
+ globalThis.tmctAdventure = {
87
+ createAdventureSession, resolveSpriteForClass, SPRITE_REGISTRY, worldDigestRows,
88
+ };
@@ -23574,6 +23574,7 @@ ${JSON.stringify(envelope, null, 2)}`;
23574
23574
  // src/services/spider-fly.mjs
23575
23575
  init_planning();
23576
23576
  init_core();
23577
+ init_hash();
23577
23578
 
23578
23579
  // src/services/spider-fly-turn.mjs
23579
23580
  init_core();
@@ -52,7 +52,7 @@ import { loadLexicon } from "../../domain/grammar/lexicon.mjs";
52
52
  import {
53
53
  worldFactRows, WORLD_NAME, WORLD_OPENING, cellId, parseCellId, DIRECTION_DELTA, visibleCells,
54
54
  } from "../../domain/spider-fly-world.mjs";
55
- import { foldSpiderFlyState, runSpiderFlyTick, startSpiderFlyGame, DEFAULT_VISION_RADIUS } from "../../services/spider-fly.mjs";
55
+ import { foldSpiderFlyState, runSpiderFlyTick, startSpiderFlyGame, liveWebs, DEFAULT_VISION_RADIUS } from "../../services/spider-fly.mjs";
56
56
  import { resolveSpriteForClass, SPRITE_REGISTRY } from "../../domain/sprite-map.mjs";
57
57
 
58
58
  /** A live in-memory game the page's ticker and chat dock can both drive.
@@ -77,8 +77,8 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
77
77
  const { facts: startFacts } = await startSpiderFlyGame(memoryDir, { flyCount });
78
78
  const initialAgents = {};
79
79
  for (const f of startFacts) {
80
- if (f.predicate !== "mgx:currently-in") continue;
81
- initialAgents[f.subject] = { cell: f.object };
80
+ if (f.predicate === "mgx:currently-in") initialAgents[f.subject] = { ...initialAgents[f.subject], cell: f.object };
81
+ else if (f.predicate === "mgx:mass") initialAgents[f.subject] = { ...initialAgents[f.subject], mass: Number(f.object) };
82
82
  }
83
83
 
84
84
  const graph = parseEntities({ individuals: [], objectProperties: [] });
@@ -93,7 +93,7 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
93
93
  memoryDir,
94
94
  sessionId,
95
95
  opening: WORLD_OPENING,
96
- initial: { turn: 0, agents: initialAgents },
96
+ initial: { turn: 0, agents: initialAgents, activeWebs: [] },
97
97
  taxonomyRows,
98
98
 
99
99
  /** Run one real engine turn directly. Returns spider-fly.mjs's own
@@ -127,16 +127,18 @@ export async function createSpiderFlySession({ flyCount = 1 } = {}) {
127
127
 
128
128
  /** A read-only fold of the CURRENT board — no engine advance, no goal
129
129
  * lines (see the header comment: only a raw tick() recomputes those).
130
- * Lets the page resync positions/turn count after a chat-driven tick. */
130
+ * Lets the page resync positions/turn count/mass/active webs after a
131
+ * chat-driven tick. Web individuals are never listed as agents (that's
132
+ * spider-1/fly-1/... only) — they surface only through activeWebs. */
131
133
  async snapshot() {
132
134
  const rows = readFactRows(await loadMemory(memoryDir));
133
135
  const state = foldSpiderFlyState(rows);
134
136
  const agents = {};
135
137
  for (const [id, place] of state.placements) {
136
- if (state.removed.has(id)) continue;
137
- agents[id] = { cell: place.cell };
138
+ if (state.removed.has(id) || /^web-\d+$/.test(id)) continue;
139
+ agents[id] = { cell: place.cell, mass: state.mass.get(id)?.value ?? null };
138
140
  }
139
- return { turn: state.turnCount, agents };
141
+ return { turn: state.turnCount, agents, activeWebs: liveWebs(state.webs, state.turnCount) };
140
142
  },
141
143
  };
142
144
  }