@polycode-projects/the-mechanical-code-talker 2.8.7 → 2.8.9

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.8.7",
3
+ "version": "2.8.9",
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.",
@@ -397,7 +397,11 @@ ${THEME_TOKENS_CSS}
397
397
  /* the portrait frame — an ornate double-rule border with two small corner
398
398
  fleurons (real glyphs, no external asset), sized to its OWN content
399
399
  (the sprite row) rather than a fixed tall box, per operator feedback on
400
- an earlier, mostly-empty version of this panel. */
400
+ an earlier, mostly-empty version of this panel. Once shrunk to its own
401
+ content it's shorter than the right column's own account/pills/digest/
402
+ chat/satchel/map/quest stack, so it centers in the row instead of
403
+ sitting top-anchored above a dead gap of raw background. */
404
+ #playStage .room-frame { align-self: center; }
401
405
  .room-frame { position: relative; background: var(--parchment); border: 1px solid var(--gilt); outline: 1px solid var(--line); outline-offset: 4px; padding: 1.1rem; display: flex; flex-direction: column; gap: .6rem; }
402
406
  .room-frame::before, .room-frame::after { content: "\\2766"; position: absolute; font-size: 1.1rem; color: var(--gilt); opacity: .85; line-height: 1; }
403
407
  .room-frame::before { top: -.6rem; left: -.35rem; }
@@ -494,8 +498,15 @@ ${THEME_TOKENS_CSS}
494
498
  /* edit mode */
495
499
  body:not(.editing) #editStage { display: none; }
496
500
  body.editing #playStage, body.editing #playControls { display: none; }
497
- .editor-stage { margin-top: .5rem; }
498
- .edittext textarea { width: 100%; box-sizing: border-box; min-height: 380px; font-family: ${MONO_STACK}; font-size: .82rem; line-height: 1.55; background: var(--bg); color: var(--ink); border: 1px solid var(--line); padding: .6rem; resize: vertical; }
501
+ /* .stage's inherited align-items: start (kept for #playStage's own fixed-
502
+ size room panel) would otherwise top-align .edittext against the
503
+ manor-map/room-detail/legend column and leave a dead gap below the
504
+ textarea once that column grows taller — override to stretch just for
505
+ the editor, and let the textarea (not just its wrapper) absorb the
506
+ extra height so the editing area actually grows, not just its padding. */
507
+ .editor-stage { margin-top: .5rem; align-items: stretch; }
508
+ .editor-stage .edittext { display: flex; flex-direction: column; }
509
+ .edittext textarea { width: 100%; box-sizing: border-box; min-height: 380px; flex: 1 1 auto; font-family: ${MONO_STACK}; font-size: .82rem; line-height: 1.55; background: var(--bg); color: var(--ink); border: 1px solid var(--line); padding: .6rem; resize: vertical; }
499
510
  .edit-status { font-family: ${MONO_STACK}; font-size: .74rem; color: var(--muted); margin-top: .4rem; min-height: 1.1em; }
500
511
  .edit-status.pending { color: var(--entail); }
501
512
  .edit-status.ok { color: var(--taught); }
@@ -294,7 +294,7 @@ ${THEME_TOKENS_CSS}
294
294
  h1 { font-size: 1.4rem; margin: .3rem 0 .9rem; text-wrap: balance; }
295
295
  button { font: inherit; color: inherit; background: none; cursor: pointer; }
296
296
  button:focus-visible, input:focus-visible, .sprite:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
297
- .stage { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 360px); gap: 1.2rem; align-items: start; }
297
+ .stage { display: grid; grid-template-columns: minmax(0, 1fr) minmax(280px, 360px); gap: 1.2rem; }
298
298
  @media (max-width: 760px) { .stage { grid-template-columns: 1fr; } }
299
299
  /* A dusty window corner: a soft light glow near the top-left (WEB_HOME
300
300
  already sits near that corner — spider-fly-world.mjs's own header
@@ -302,6 +302,14 @@ ${THEME_TOKENS_CSS}
302
302
  in the light. Decoration only — the 10x10 game grid itself is drawn by
303
303
  drawBoard() on the canvas beneath, unchanged. */
304
304
  .board-frame {
305
+ /* The side column's own height grows with the live agent count
306
+ (.hud-list caps out at 420px, then scrolls) — align-self keeps this
307
+ fixed-square board centered in whatever row height that produces,
308
+ instead of top-aligning it and leaving a dead gap below once the
309
+ side column outgrows the board. The grid's default align-items:
310
+ stretch would otherwise force this box tall, breaking its own
311
+ aspect-ratio square. */
312
+ align-self: center;
305
313
  position: relative; width: ${BOARD_PX}px; max-width: 100%; aspect-ratio: 1 / 1;
306
314
  background:
307
315
  radial-gradient(140% 140% at 6% 6%, rgba(255, 241, 199, .55), transparent 52%),
@@ -55,18 +55,76 @@ import { THEME_TOKENS_CSS, SERIF_STACK, MONO_STACK, escapeHtml, embedJson } from
55
55
  const DEFAULT_TITLE = "tmct — the sprite library";
56
56
  const MAX_CHAIN_DISPLAY = 6;
57
57
 
58
+ /** A curated gap-fill for classes wordnet-xl's own prioritized subset
59
+ * happens to carry NO rdfs:subClassOf row for at all (115 of 198 catalog
60
+ * classes, checked directly against a build of this page) — every pair
61
+ * here is real WordNet-derived data, the same corpus/wordnet/
62
+ * wordnet-full.jsonl this module's header already describes evaluating
63
+ * and rejecting as a BLANKET source (sense-conflation, 3000+ ancestors for
64
+ * "poodle", minutes to walk). That rejection doesn't apply to a single
65
+ * hand-verified relation per class: each pair below is the one /r/IsA row
66
+ * (of however many wordnet-full.jsonl actually carries for that word) that
67
+ * reads as the correct sense for a physical/common-noun catalog entry —
68
+ * chosen the same way SEED_TAXONOMY above is hand-curated, not generated.
69
+ * A term with only implausible senses on record (e.g. "pig" -> only
70
+ * "ingot"/"live", "portable" -> only the archaic noun "typewriter") is
71
+ * left OUT here on purpose rather than forced — it keeps today's honest
72
+ * self-only chain instead of a confidently wrong one. Same for a term with
73
+ * no /r/IsA row anywhere in wordnet-full.jsonl at all (autumn, grandmother,
74
+ * human, manager) — a real, checked absence, not an oversight. */
75
+ const CATALOG_TAXONOMY_GAPFILL = Object.freeze([
76
+ ["airport", "airfield"], ["ant", "hymenopterous insect"], ["artist", "creator"],
77
+ ["audience", "gathering"], ["baby", "child"], ["beach", "land"],
78
+ ["bee", "hymenopterous insect"], ["bicycle", "wheeled vehicle"], ["bird", "vertebrate"],
79
+ ["birthday", "anniversary"], ["boat", "vessel"], ["body of water", "thing"],
80
+ ["breakfast", "meal"], ["butler", "manservant"], ["butterfly", "lepidopterous insect"],
81
+ ["cabinet", "furniture"], ["car", "motor vehicle"], ["castle", "fortification"],
82
+ ["chair", "seat"], ["champion", "defender"], ["cheese", "dairy product"],
83
+ ["church", "place of worship"], ["citizen", "national"], ["city", "municipality"],
84
+ ["coin", "coinage"], ["container", "instrumentality"], ["crowd", "gathering"],
85
+ ["customer", "consumer"], ["daughter", "female offspring"], ["desk", "table"],
86
+ ["dinner", "meal"], ["doctor", "medical practitioner"], ["drink", "helping"],
87
+ ["elephant", "proboscidean"], ["factory", "plant"], ["family", "kin"],
88
+ ["farm", "workplace"], ["farmer", "creator"], ["fish", "aquatic vertebrate"],
89
+ ["food", "substance"], ["forest", "biome"], ["frog", "amphibian"],
90
+ ["furniture", "furnishing"], ["garden", "yard"], ["glove", "handwear"],
91
+ ["gold", "precious metal"], ["grandfather", "grandparent"], ["guest", "visitor"],
92
+ ["hate", "emotion"], ["home", "residence"], ["horse", "equine"],
93
+ ["hospital", "medical institution"], ["housekeeper", "domestic"], ["jewelry", "adornment"],
94
+ ["joy", "emotion"], ["lamp", "source of illumination"], ["lawyer", "professional"],
95
+ ["letter", "document"], ["lion", "big cat"], ["meal", "foodstuff"],
96
+ ["meat", "solid food"], ["meeting", "assembly"], ["money", "currency"],
97
+ ["mother", "parent"], ["mountain", "natural elevation"], ["museum", "depository"],
98
+ ["nurse", "health professional"], ["ocean", "body of water"], ["officer", "mariner"],
99
+ ["owl", "bird of prey"], ["planet", "celestial body"], ["portrait", "likeness"],
100
+ ["president", "head of state"], ["priest", "spiritual leader"], ["rabbit", "leporid"],
101
+ ["rain", "precipitation"], ["resident", "inhabitant"], ["river", "stream"],
102
+ ["road", "way"], ["room", "area"], ["sheep", "bovid"],
103
+ ["shoe", "footwear"], ["shop", "mercantile establishment"], ["snow", "precipitation"],
104
+ ["sock", "hosiery"], ["soldier", "enlisted person"], ["son", "male offspring"],
105
+ ["spring", "season"], ["star", "celestial body"], ["street", "thoroughfare"],
106
+ ["student", "enrollee"], ["sugar", "sweetening"], ["summer", "season"],
107
+ ["sun", "star"], ["table", "furniture"], ["teacher", "educator"],
108
+ ["team", "group"], ["town", "municipality"], ["train", "public transport"],
109
+ ["tree", "woody plant"], ["vehicle", "conveyance"], ["village", "settlement"],
110
+ ["visitor", "traveler"], ["waterway", "body of water"], ["wedding", "ceremony"],
111
+ ["wine", "alcohol"], ["winter", "season"], ["wolf", "canine"],
112
+ ["woman", "adult"],
113
+ ]);
114
+
58
115
  /** The real rdfs:subClassOf fact rows this catalog's ancestor chains walk —
59
116
  * see this module's own header for why these two sources and not a third.
60
117
  * I/O (reads corpus/wordnet/wordnet-xl.jsonl + its relation map); never
61
118
  * called from renderSpriteCatalogHtml itself, which stays pure. */
62
119
  export async function loadSpriteOntologyFactRows() {
63
120
  const seedRows = SEED_TAXONOMY.map(([subject, object]) => ({ subject, predicate: "rdfs:subClassOf", object }));
121
+ const gapfillRows = CATALOG_TAXONOMY_GAPFILL.map(([subject, object]) => ({ subject, predicate: "rdfs:subClassOf", object }));
64
122
  const assertions = await loadSlice(join(WORDNET_DIR, "wordnet-xl.jsonl"));
65
123
  const map = await loadMap();
66
124
  const wordnetRows = toFacts(assertions, map, "corpus:wordnet-xl")
67
125
  .filter((f) => f.predicate === "rdfs:subClassOf")
68
126
  .map((f) => ({ subject: f.subject, predicate: f.predicate, object: f.object }));
69
- return [...seedRows, ...wordnetRows];
127
+ return [...seedRows, ...gapfillRows, ...wordnetRows];
70
128
  }
71
129
 
72
130
  // ---- grouping (presentation only — every class still resolves through the