@polycode-projects/the-mechanical-code-talker 2.7.14 → 2.7.16
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.
|
|
3
|
+
"version": "2.7.16",
|
|
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.",
|
|
@@ -780,6 +780,15 @@ async function runWorldCommand(cmd, { world, memoryDir, env, graph, cache }) {
|
|
|
780
780
|
// the same with or without it, and the fold IS the now.
|
|
781
781
|
const WORLD_WHERE_RE = /^where(?:'s|\s+is|\s+are)\s+(?:the\s+|a\s+|an\s+)?(.+?)(?:\s+now)?[?.!\s]*$/i;
|
|
782
782
|
|
|
783
|
+
// A mid-game "is X open/closed" aside. mgx:is-open is a datatype fact
|
|
784
|
+
// ("true"/"false"), so the generic ask engine's adjective/property reader —
|
|
785
|
+
// which looks for a CLASS/adjective membership fact, not a literal value —
|
|
786
|
+
// has nothing to match and answers "I don't have a fact saying X", reading
|
|
787
|
+
// as an epistemic gap even though the negation is fully known (the taught
|
|
788
|
+
// effect wrote the opposite value). This aside reads state.openness directly,
|
|
789
|
+
// the same fold containerStatusPhrase already reads for "look"/"examine".
|
|
790
|
+
const WORLD_IS_OPEN_RE = /^is\s+(?:the\s+|a\s+|an\s+)?(.+?)\s+(open|closed|shut)[?.!\s]*$/i;
|
|
791
|
+
|
|
783
792
|
/** A locative aside about a placed world thing, answered from the SAME @turnN
|
|
784
793
|
* fold every other world reader uses — never the raw base rows, whose
|
|
785
794
|
* superseded placements would answer where things stood at load time. Null
|
|
@@ -823,6 +832,28 @@ async function worldWhereAnswer(line, { memoryDir }) {
|
|
|
823
832
|
);
|
|
824
833
|
}
|
|
825
834
|
|
|
835
|
+
/** A mid-game "is X open/closed" aside, read from state.openness — the same
|
|
836
|
+
* fold "look"/"examine" already phrase via containerStatusPhrase. Null when
|
|
837
|
+
* the named thing has no openness fact at all (never a container, or one
|
|
838
|
+
* never opened/closed this session), so an ordinary ask keeps its lane. */
|
|
839
|
+
async function worldOpennessAnswer(line, { memoryDir }) {
|
|
840
|
+
const m = String(line).match(WORLD_IS_OPEN_RE);
|
|
841
|
+
if (!m) return null;
|
|
842
|
+
const thing = normFactTerm(m[1]);
|
|
843
|
+
const askedOpen = /^open$/i.test(m[2]);
|
|
844
|
+
let rows;
|
|
845
|
+
try { rows = readFactRows(await loadMemory(memoryDir)); } catch { return null; }
|
|
846
|
+
const state = foldWorldState(rows);
|
|
847
|
+
const openness = state.openness.get(thing);
|
|
848
|
+
if (!openness) return null;
|
|
849
|
+
const matches = askedOpen ? openness.open : !openness.open;
|
|
850
|
+
return answer(
|
|
851
|
+
`${matches ? "yes" : "no"} — the ${thing} is ${openness.open ? "open" : "closed"}.`,
|
|
852
|
+
`ADVENTURE — is-open-aside: ${thing}'s current openness from the world fold (as of turn ${openness.turn})`,
|
|
853
|
+
{ goal: `check whether the ${thing} is ${m[2].toLowerCase()}` },
|
|
854
|
+
);
|
|
855
|
+
}
|
|
856
|
+
|
|
826
857
|
async function inventoryAnswer({ memoryDir, graph }) {
|
|
827
858
|
const memory = await loadMemory(memoryDir);
|
|
828
859
|
const rows = readFactRows(memory);
|
|
@@ -945,5 +976,7 @@ export async function adventureTurn(line, { planHolder, memoryDir, sessionId = "
|
|
|
945
976
|
}
|
|
946
977
|
const whereAside = await worldWhereAnswer(line, { memoryDir });
|
|
947
978
|
if (whereAside) return whereAside;
|
|
979
|
+
const opennessAside = await worldOpennessAnswer(line, { memoryDir });
|
|
980
|
+
if (opennessAside) return opennessAside;
|
|
948
981
|
return null; // a mid-game aside — the ordinary lanes answer, world untouched
|
|
949
982
|
}
|
|
@@ -651,6 +651,18 @@ export async function runSpiderFlyTick(memoryDir, opts = {}) {
|
|
|
651
651
|
}
|
|
652
652
|
|
|
653
653
|
const ecology = runEcologyPass({ state, postMovePlacements, postMoveMassByFly, postMoveMassBySpider, turn: k });
|
|
654
|
+
// A fly eaten or starved THIS tick was already assigned a pre-ecology
|
|
655
|
+
// goal/position above (movement runs before the ecology pass resolves
|
|
656
|
+
// eating) — left as-is, the same response would both announce "fly-5 was
|
|
657
|
+
// eaten" and still list fly-5's stale "trapped, can't move" goal one clause
|
|
658
|
+
// later, as if it were still on the board. Drop it from `agents` (its own
|
|
659
|
+
// goal is moot) and let the eating spider's line say what actually
|
|
660
|
+
// happened instead of the now-false "co-located with fly-5 in the web".
|
|
661
|
+
for (const { fly, spider } of ecology.events.eaten) {
|
|
662
|
+
delete agents[fly];
|
|
663
|
+
if (agents[spider]) agents[spider].goal = `just ate ${fly} in the web.`;
|
|
664
|
+
}
|
|
665
|
+
for (const flyId of ecology.events.starved) delete agents[flyId];
|
|
654
666
|
const writes = [...movementWrites, ...ecology.writes];
|
|
655
667
|
const provenance = `${worldProvenanceTag(WORLD_NAME)}:turn${k}`;
|
|
656
668
|
await appendFacts(memoryDir, writes.map((f) => ({ ...f, provenance })));
|