@polycode-projects/the-mechanical-code-talker 2.7.8 → 2.7.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polycode-projects/the-mechanical-code-talker",
3
- "version": "2.7.8",
3
+ "version": "2.7.10",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The Mechanical Code Talker (tmct) — a tolerant, offline, $0 chat surface that guides you toward precision queries about a software repository. ELIZA/PARRY-style but domain-obsessed with code. No model calls; no codebase index of its own.",
@@ -91,6 +91,15 @@ async function openAdventure(opening, { planHolder, memoryDir, sessionId, env, c
91
91
  note: "ADVENTURE — opening declined: the world's shard failed to load",
92
92
  };
93
93
  }
94
+ // A world sharing this pack but shaped for a different game entirely (e.g.
95
+ // spider-fly, which has no player-controlled entity at all — its board is
96
+ // reusable static content, and player/spider/fly individuals are minted
97
+ // fresh by that game's own opener, never shipped in the pack) has no
98
+ // starting player placement. Decline cleanly rather than load a broken
99
+ // adventure session — the same "not necessarily an adventure ask at all"
100
+ // fallthrough an unrecognized name already gets, so whichever lane DOES
101
+ // own this name gets a chance to claim it instead.
102
+ if (!payload.facts.some((f) => f.subject === "player")) return null;
94
103
 
95
104
  const tag = worldProvenanceTag(world);
96
105
  await appendFacts(memoryDir, payload.facts.map((f) => ({
@@ -490,7 +499,12 @@ async function runWorldCommand(cmd, { world, memoryDir, env, graph, cache }) {
490
499
  const digest = await worldDigest(object, { memoryDir, memory, rows, state, graph });
491
500
  const body = digest ?? `nothing more about the ${object} is written down yet.`;
492
501
  const containerNote = !person && isContainer(rows, object) ? ` ${containerStatusPhrase(object, { state })}` : "";
493
- const text = person ? `the ${object} doesn't have much to say, but you know: ${body}` : `${body}${containerNote}`;
502
+ // Framing follows the VERB the player typed, not the object's type: talking
503
+ // to a lamp still reads as an attempted conversation (nothing replies, but
504
+ // you learn what's known), and examining a person still reads as a plain
505
+ // inspection, never the "doesn't have much to say" framing that belongs to
506
+ // a failed talk attempt.
507
+ const text = cmd.verb === "talk" ? `the ${object} doesn't have much to say, but you know: ${body}` : `${body}${containerNote}`;
494
508
  return answer(
495
509
  text,
496
510
  noteFor(`${cmd.verb} — an extractive completions digest over the current world facts mentioning "${object}"`),
@@ -26,12 +26,14 @@ import { appendFacts, appendRule, loadMemory, readFactRows } from "../adapters/m
26
26
  // ---- recognizers: the closed opening/stop/tick/address set -------------------
27
27
 
28
28
  // The opener names the game without requiring a specific phrasing order —
29
- // "watch the spider and the fly" / "play spider and fly" / "start the
30
- // spider game" all match. Closed vocabulary only (watch/play/start/begin,
31
- // spider, fly, game) no general "start X" grammar, matching this
32
- // project's standing preference and adventure.mjs's own opener style.
29
+ // "watch the spider and the fly" / "play spider and fly" / "play spider fly"
30
+ // (the "and" is optional — playtests/PLAYTEST_LOG_006.md found it's a
31
+ // natural drop) / "start the spider game" all match. Closed vocabulary only
32
+ // (watch/play/start/begin, spider, fly, game) no general "start X"
33
+ // grammar, matching this project's standing preference and adventure.mjs's
34
+ // own opener style.
33
35
  const SPIDER_FLY_OPEN_RE =
34
- /^(?:let'?s\s+)?(?:watch|play|start|begin)\s+(?:the\s+)?spider(?:\s+and\s+(?:the\s+)?fly)?(?:\s+game)?[.!?\s]*$/i;
36
+ /^(?:let'?s\s+)?(?:watch|play|start|begin)\s+(?:the\s+)?spider(?:\s+(?:and\s+)?(?:the\s+)?fly)?(?:\s+game)?[.!?\s]*$/i;
35
37
  // "stop watching" is this game's own stop word (there's nothing to "play" in
36
38
  // the sense of typing moves — you watch, or address an agent), kept
37
39
  // alongside "stop playing" so either reads naturally depending on how the