@maka/maka-cli 5.61.0 → 5.63.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.
Files changed (147) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js +4 -1
  3. package/bundle/typescript/src/commands/game/sideQuest/commands/advance.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/ar.d.ts +34 -0
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js +93 -0
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/ar.js.map +1 -0
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js +4 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/backlog.js.map +1 -1
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/breach.d.ts +7 -2
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js +7 -2
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/breach.js.map +1 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.d.ts +6 -0
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js +56 -7
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/bypass-command.js.map +1 -1
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/call.d.ts +9 -0
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +62 -23
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -1
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js +5 -5
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js.map +1 -1
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js +41 -2
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/contacts.js.map +1 -1
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/crew.d.ts +7 -14
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/crew.js +86 -51
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/crew.js.map +1 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js +1 -1
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/deck.js.map +1 -1
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +4 -1
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js.map +1 -1
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js +6 -1
  30. package/bundle/typescript/src/commands/game/sideQuest/commands/equipment.js.map +1 -1
  31. package/bundle/typescript/src/commands/game/sideQuest/commands/follow.d.ts +37 -0
  32. package/bundle/typescript/src/commands/game/sideQuest/commands/follow.js +216 -0
  33. package/bundle/typescript/src/commands/game/sideQuest/commands/follow.js.map +1 -0
  34. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +23 -5
  35. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
  36. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js +30 -3
  37. package/bundle/typescript/src/commands/game/sideQuest/commands/hack.js.map +1 -1
  38. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +4 -1
  39. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js.map +1 -1
  40. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +6 -1
  41. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -1
  42. package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js +3 -3
  43. package/bundle/typescript/src/commands/game/sideQuest/commands/jobs.js.map +1 -1
  44. package/bundle/typescript/src/commands/game/sideQuest/commands/lead.js +1 -1
  45. package/bundle/typescript/src/commands/game/sideQuest/commands/lead.js.map +1 -1
  46. package/bundle/typescript/src/commands/game/sideQuest/commands/look.d.ts +21 -1
  47. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js +165 -59
  48. package/bundle/typescript/src/commands/game/sideQuest/commands/look.js.map +1 -1
  49. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js +5 -2
  50. package/bundle/typescript/src/commands/game/sideQuest/commands/map.js.map +1 -1
  51. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js +6 -4
  52. package/bundle/typescript/src/commands/game/sideQuest/commands/mark.js.map +1 -1
  53. package/bundle/typescript/src/commands/game/sideQuest/commands/note.js +9 -3
  54. package/bundle/typescript/src/commands/game/sideQuest/commands/note.js.map +1 -1
  55. package/bundle/typescript/src/commands/game/sideQuest/commands/overwatch.js +3 -1
  56. package/bundle/typescript/src/commands/game/sideQuest/commands/overwatch.js.map +1 -1
  57. package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js +1 -1
  58. package/bundle/typescript/src/commands/game/sideQuest/commands/pan.js.map +1 -1
  59. package/bundle/typescript/src/commands/game/sideQuest/commands/players.js +4 -1
  60. package/bundle/typescript/src/commands/game/sideQuest/commands/players.js.map +1 -1
  61. package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js +4 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/commands/quality-trade.js.map +1 -1
  63. package/bundle/typescript/src/commands/game/sideQuest/commands/roles.js +4 -1
  64. package/bundle/typescript/src/commands/game/sideQuest/commands/roles.js.map +1 -1
  65. package/bundle/typescript/src/commands/game/sideQuest/commands/say.d.ts +21 -0
  66. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js +95 -8
  67. package/bundle/typescript/src/commands/game/sideQuest/commands/say.js.map +1 -1
  68. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +3 -3
  69. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
  70. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.d.ts +8 -0
  71. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js +13 -2
  72. package/bundle/typescript/src/commands/game/sideQuest/commands/silent.js.map +1 -1
  73. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js +4 -1
  74. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js.map +1 -1
  75. package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js +1 -1
  76. package/bundle/typescript/src/commands/game/sideQuest/commands/snoop.js.map +1 -1
  77. package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js +11 -1
  78. package/bundle/typescript/src/commands/game/sideQuest/commands/solve.js.map +1 -1
  79. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js +5 -1
  80. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js.map +1 -1
  81. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js +21 -0
  82. package/bundle/typescript/src/commands/game/sideQuest/commands/stance.js.map +1 -1
  83. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.d.ts +49 -0
  84. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js +181 -0
  85. package/bundle/typescript/src/commands/game/sideQuest/commands/tap.js.map +1 -0
  86. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js +4 -1
  87. package/bundle/typescript/src/commands/game/sideQuest/commands/thread.js.map +1 -1
  88. package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js +6 -2
  89. package/bundle/typescript/src/commands/game/sideQuest/commands/unlock.js.map +1 -1
  90. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +13 -1
  91. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +85 -4
  92. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
  93. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +43 -1
  94. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -1
  95. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +9 -0
  96. package/bundle/typescript/src/commands/game/sideQuest/game.js +90 -25
  97. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  98. package/bundle/typescript/src/commands/game/sideQuest/headless.js +58 -0
  99. package/bundle/typescript/src/commands/game/sideQuest/headless.js.map +1 -1
  100. package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +30 -0
  101. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +234 -63
  102. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
  103. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +19 -1
  104. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +31 -1
  105. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  106. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.d.ts +23 -4
  107. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js +54 -8
  108. package/bundle/typescript/src/commands/game/sideQuest/models/puzzle.js.map +1 -1
  109. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js +1 -1
  110. package/bundle/typescript/src/commands/game/sideQuest/models/scene.js.map +1 -1
  111. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +6 -0
  112. package/bundle/typescript/src/commands/game/sideQuest/ui.js +21 -0
  113. package/bundle/typescript/src/commands/game/sideQuest/ui.js.map +1 -1
  114. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.d.ts +74 -0
  115. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js +184 -0
  116. package/bundle/typescript/src/commands/game/sideQuest/utilities/ar.js.map +1 -0
  117. package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.d.ts +76 -0
  118. package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.js +98 -0
  119. package/bundle/typescript/src/commands/game/sideQuest/utilities/earshot.js.map +1 -0
  120. package/bundle/typescript/src/commands/game/sideQuest/utilities/generation-capture.js +21 -9
  121. package/bundle/typescript/src/commands/game/sideQuest/utilities/generation-capture.js.map +1 -1
  122. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.d.ts +16 -0
  123. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js +34 -1
  124. package/bundle/typescript/src/commands/game/sideQuest/utilities/grid-view.js.map +1 -1
  125. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +34 -0
  126. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js.map +1 -1
  127. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +3 -1
  128. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
  129. package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.d.ts +26 -2
  130. package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js +92 -7
  131. package/bundle/typescript/src/commands/game/sideQuest/utilities/shared-run.js.map +1 -1
  132. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +19 -0
  133. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +28 -0
  134. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
  135. package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.d.ts +33 -0
  136. package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.js +61 -0
  137. package/bundle/typescript/src/commands/game/sideQuest/utilities/surveillance.js.map +1 -1
  138. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +12 -11
  139. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
  140. package/bundle/typescript/src/maka.js +26 -0
  141. package/bundle/typescript/src/maka.js.map +1 -1
  142. package/bundle/typescript/src/tools/sdk-loader/relocate.js +7 -0
  143. package/bundle/typescript/src/tools/sdk-loader/relocate.js.map +1 -1
  144. package/bundle/typescript/src/tools/self-spawn/self-spawn.d.ts +10 -0
  145. package/bundle/typescript/src/tools/self-spawn/self-spawn.js +68 -0
  146. package/bundle/typescript/src/tools/self-spawn/self-spawn.js.map +1 -0
  147. package/package.json +1 -1
@@ -17,6 +17,7 @@ import { Logger } from './utilities/logger.js';
17
17
  import { currentSession, runInSession } from './utilities/session-context.js';
18
18
  import { restorePlayer, serializePlayer } from './utilities/persistence.js';
19
19
  import { renderMapViewport } from './utilities/map-view.js';
20
+ import { renderRoomLayoutCompact } from './utilities/room-view.js';
20
21
  import { entrySpotFor, spotOf } from './utilities/spots.js';
21
22
  /**
22
23
  * The session's Logger: same shape the whole engine already talks to,
@@ -197,10 +198,44 @@ export async function createHeadlessSession(opts) {
197
198
  continue;
198
199
  if (p.plane === 'matrix') {
199
200
  logger.system('', { actor: p.name }, 'map', {});
201
+ logger.system('', { actor: p.name }, 'room', {});
200
202
  continue;
201
203
  }
202
204
  const eyes = { visited: p.visitedRooms, arEyes: p.hasMatrixEyes() };
203
205
  logger.system(renderMapViewport(rooms, here, sealing, eyes).join('\n'), { actor: p.name }, 'map');
206
+ // THE ROOM BOX'S TWIN (playtest 2026-08-27, reported twice:
207
+ // "the room minimap isn't updating in the shared run, I only
208
+ // see @open floor"). Game.updateExits early-returns on
209
+ // `remoteSession`, so in a shared run the room box kept
210
+ // whatever the HUB painted into it and then FROZE -- the stale
211
+ // caption the player was reading was from the bar they left.
212
+ // The district map has had a server push since the map-overlay
213
+ // wave; this is the same wiring for the panel beside it.
214
+ //
215
+ // Rendered at renderRoomLayoutCompact's DEFAULT width, exactly
216
+ // as renderMapViewport is above: the server cannot know the
217
+ // client's box width (23% of a terminal it never sees), and
218
+ // the district map has shipped on that same compromise since
219
+ // 2026-08-24. Width only moves the elevation bar's right
220
+ // justification and how much grid is windowed in.
221
+ //
222
+ // A DECORATION MUST NEVER KILL THE RUN -- the solo path wraps
223
+ // this same render for the same reason, and a throw HERE would
224
+ // take down the whole table's command, not one player's panel.
225
+ try {
226
+ const roomLines = renderRoomLayoutCompact(here, p, {
227
+ isOtherPlayer: a => game.scene.isHumanControlled(a),
228
+ });
229
+ if (roomLines.length > 0) {
230
+ const spot = spotOf(p);
231
+ roomLines.push(`{bold}${spot ? `@ ${spot}` : '(moving through)'}{/bold}`);
232
+ }
233
+ logger.system(roomLines.join('\n'), { actor: p.name }, 'room');
234
+ }
235
+ catch (err) {
236
+ logger.write(`Room overlay render failed for ${p.name} in ${here.name}: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
237
+ logger.system('', { actor: p.name }, 'room', {});
238
+ }
204
239
  }
205
240
  };
206
241
  const session = {
@@ -213,6 +248,29 @@ export async function createHeadlessSession(opts) {
213
248
  return res;
214
249
  }),
215
250
  addPlayer: (save) => runInSession(ctx, async () => {
251
+ // REJOIN IS NOT A JOIN (playtest 2026-08-27, Sherry: "got an
252
+ // internal server error"). A dropped DDP connection -- a
253
+ // laptop lid, a wifi blip, a client restart -- calls
254
+ // sideQuest.join again with the same runner, and this used to
255
+ // walk straight into Scene.addActor, which throws "Actor with
256
+ // name X already exists in the scene." The method died, the
257
+ // player saw a raw 500, and their seat was unreachable for
258
+ // the rest of the run even though the engine still held a
259
+ // perfectly good actor for them.
260
+ //
261
+ // The right answer is to hand the existing actor back: their
262
+ // position, inventory, wounds and watchers are all still live
263
+ // on the table. Re-push status and the overlays so the
264
+ // reconnecting client repaints from the server's truth, and
265
+ // deliberately DON'T re-narrate the taxi -- they never left,
266
+ // and the table shouldn't be told they arrived twice.
267
+ const existing = game.scene.getPlayers().find(x => x.name === save.playerName);
268
+ if (existing) {
269
+ logger.write(`addPlayer: ${existing.name} is already seated -- treating as a RECONNECT, not a join.`);
270
+ logger.status(existing.name, game.statusLinesFor(existing));
271
+ pushMap();
272
+ return existing.name;
273
+ }
216
274
  const p = buildPlayerFromSave(save);
217
275
  const room = spawnRoom();
218
276
  game.scene.addPlayer(p, room);
@@ -1 +1 @@
1
- {"version":3,"file":"headless.js","sourceRoot":"","sources":["../../../../../../src/commands/game/sideQuest/headless.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"headless.js","sourceRoot":"","sources":["../../../../../../src/commands/game/sideQuest/headless.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,36 @@ export interface INPCConstructorConfig {
8
8
  description: string;
9
9
  playerConstructorConfig: IPlayerConstructorConfig;
10
10
  }
11
+ /**
12
+ * THE CAST PIN -- geographySummary's missing twin. See the note at its
13
+ * call site in respondTo(). Exported and PURE for the same reason as
14
+ * credentialHonestyNote: an NPC inventing a person fails silently, and
15
+ * the player is the only detector.
16
+ */
17
+ export declare function castPin(names: string[]): string;
18
+ /**
19
+ * THE ANTI-CONFABULATION CLAUSE for barrier credentials -- see the long
20
+ * note at its call site in respondTo(). `passesHeld` is how many real
21
+ * passes this NPC was actually handed by the BARRIER AT YOUR POST block
22
+ * (0 for everyone not standing at an unsolved barrier, which is almost
23
+ * everyone).
24
+ *
25
+ * Exported and PURE for the same reason splitSpokenLines is: it fails
26
+ * SILENTLY. Nothing throws when this clause goes missing or softens --
27
+ * the NPC just starts inventing door codes again, and the only place it
28
+ * surfaces is a player three rooms away typing a code that was never
29
+ * real. There is no assertion anywhere else in the engine that would
30
+ * notice.
31
+ */
32
+ export declare function credentialHonestyNote(passesHeld: number): string;
33
+ /**
34
+ * SPEECH REPAIR: turns a model reply's raw lines into lines the
35
+ * classifier below can actually read. Exported and PURE so the rules
36
+ * can be tested directly -- every one of them was written in response
37
+ * to a specific playtest report, and each is a silent failure when it
38
+ * regresses: the words still print, just in the wrong voice.
39
+ */
40
+ export declare function splitSpokenLines(lines: string[]): string[];
11
41
  export declare class NPC extends Player {
12
42
  private _dialogue;
13
43
  private _description;
@@ -8,6 +8,171 @@ import { spotsActive, spotOf, describeSpotRoster, spotDistanceMeters, spotCoverB
8
8
  import { classifyWeapon, rangePenalty, rangeBracketName } from '../utilities/range.js';
9
9
  import { priceOf } from '../utilities/commerce.js';
10
10
  import { loadCatalog, ROLE_DOMAINS } from '../utilities/catalog.js';
11
+ /**
12
+ * THE CAST PIN -- geographySummary's missing twin. See the note at its
13
+ * call site in respondTo(). Exported and PURE for the same reason as
14
+ * credentialHonestyNote: an NPC inventing a person fails silently, and
15
+ * the player is the only detector.
16
+ */
17
+ export function castPin(names) {
18
+ if (names.length === 0)
19
+ return '';
20
+ return `The ONLY people who exist in this world: ${names.join(', ')}. When you tell anyone WHO to talk to, who holds something, or who to ask, name one of these people EXACTLY. Never invent a person for them to go and find -- no cousin with a contact, no guy who owes you one, no name you half-remember. Mentioning other people as FLAVOR (who you used to work for, who died last winter) is fine; naming them as someone the runner can actually reach is not.`;
21
+ }
22
+ /**
23
+ * THE ANTI-CONFABULATION CLAUSE for barrier credentials -- see the long
24
+ * note at its call site in respondTo(). `passesHeld` is how many real
25
+ * passes this NPC was actually handed by the BARRIER AT YOUR POST block
26
+ * (0 for everyone not standing at an unsolved barrier, which is almost
27
+ * everyone).
28
+ *
29
+ * Exported and PURE for the same reason splitSpokenLines is: it fails
30
+ * SILENTLY. Nothing throws when this clause goes missing or softens --
31
+ * the NPC just starts inventing door codes again, and the only place it
32
+ * surfaces is a player three rooms away typing a code that was never
33
+ * real. There is no assertion anywhere else in the engine that would
34
+ * notice.
35
+ */
36
+ export function credentialHonestyNote(passesHeld) {
37
+ const known = passesHeld > 0
38
+ ? `the ${passesHeld === 1 ? 'pass' : `${passesHeld} passes`} for the barrier${passesHeld === 1 ? '' : 's'} at your own post, named above, and NO others`
39
+ : `NO code, pass, or combination to anything -- you hold none`;
40
+ return `
41
+ CREDENTIALS YOU DO NOT HOLD: you know ${known}. You cannot deduce, guess, or
42
+ reason your way to a credential you were never given, and you must NEVER invent one --
43
+ not as a guess, not as a "try this", not as a number you half-remember. A code you make
44
+ up is a code the lock refuses, and the runner who trusts it burns their whole approach on
45
+ it. Asked for a pass you do not hold, say so plainly and point them at where such things
46
+ actually live: written down somewhere in the world by whoever has to remember it, or in
47
+ the hands of whoever works that door.`;
48
+ }
49
+ /**
50
+ * SPEECH REPAIR: turns a model reply's raw lines into lines the
51
+ * classifier below can actually read. Exported and PURE so the rules
52
+ * can be tested directly -- every one of them was written in response
53
+ * to a specific playtest report, and each is a silent failure when it
54
+ * regresses: the words still print, just in the wrong voice.
55
+ */
56
+ export function splitSpokenLines(lines) {
57
+ // A BARE VERB IS STILL A COMMAND (playtest 2026-08-25: Ratchet's
58
+ // whole sales pitch printed as `say You got a datajack, right?
59
+ // ...` -- the literal word "say", no speaker, straight into the
60
+ // narration). Classification below keys on the [COMMAND] prefix,
61
+ // so a reply that drops it falls through to exposition and gets
62
+ // echoed verbatim: the line never reaches the conversation, never
63
+ // gets the "Ratchet:" attribution, and reads to the player as
64
+ // narrative cross-chatter (their words) sitting on top of the
65
+ // dialogue.
66
+ //
67
+ // The DONE/FAILED handler right below already learned this lesson
68
+ // for its own markers; this generalizes it to the verb that
69
+ // actually carries the fiction. Only `say` is repaired -- it is
70
+ // the one verb whose payload is free prose, so a bare `say ...`
71
+ // is unambiguous. Every other verb stays strict, because "take
72
+ // the credstick" as narration must NOT silently become a take.
73
+ //
74
+ // ...AND A BRACKETED ONE IS TOO (playtest 2026-08-26: "the AI
75
+ // conversation is still bleeding into the description text").
76
+ // Patch's line arrived as `[say] Maka, you're bleeding cred dry
77
+ // on that lowlife...` -- the model reaching for the [COMMAND]
78
+ // bracket convention and putting the VERB inside the brackets.
79
+ // The bare-verb repair above doesn't match it (it starts with
80
+ // "["), so it fell through to exposition and printed raw, marker
81
+ // and all, as narration. Same fault as the bare verb wearing a
82
+ // different hat, and the same reasoning bounds the fix: only
83
+ // `say` is repaired, because only `say` carries free prose.
84
+ const rebuilt = [];
85
+ for (let i = 0; i < lines.length; i++) {
86
+ const t = lines[i].trimStart();
87
+ if (t.startsWith('[COMMAND]')) {
88
+ rebuilt.push(lines[i]);
89
+ continue;
90
+ }
91
+ if (/^say\s+\S/.test(t)) {
92
+ rebuilt.push(`[COMMAND] ${t}`);
93
+ continue;
94
+ }
95
+ const bracketed = t.match(/^\[\s*say\s*\]\s*(\S.*)$/i);
96
+ if (bracketed) {
97
+ rebuilt.push(`[COMMAND] say ${bracketed[1]}`);
98
+ continue;
99
+ }
100
+ // ...AND A LINE THAT IS NOTHING BUT SPEECH MARKS IS SPEECH
101
+ // (playtest 2026-08-27, reported twice in one session: 'the
102
+ // "Take a seat..." comment isn't showing as he said it. It's in
103
+ // blue font, not in green' and, from the other player, 'I can
104
+ // hear him talking, all in blue text. Not the normal green').
105
+ //
106
+ // Mr. Osprey's whole briefing arrived as bare quoted prose with
107
+ // no marker at all, so it fell to exposition: narration colour,
108
+ // no "Mr. Osprey:" in front of it, and no way for a reader to
109
+ // tell the meet's terms from the room's furniture.
110
+ //
111
+ // A line whose ENTIRE content is one quoted string is dialogue.
112
+ // That is a narrow test on purpose -- narration that merely
113
+ // contains a quote ("he mutters \"fine\" and turns away") keeps
114
+ // its quotes inside other words and is left alone.
115
+ const quoted = t.match(/^["“]([^"“”]+)["”]$/);
116
+ if (quoted) {
117
+ rebuilt.push(`[COMMAND] say ${quoted[1]}`);
118
+ continue;
119
+ }
120
+ // ...AND A LINE THAT WRAPS NARRATION AROUND A SPOKEN SENTENCE
121
+ // IS BOTH (playtest 2026-08-27: "conversation is still
122
+ // appearing in blue text" -- filed AFTER the wholly-quoted
123
+ // repair above shipped in v5.61.0, which is why that repair
124
+ // alone didn't close it).
125
+ //
126
+ // The common briefing shape is mixed: `Mr. Osprey taps the
127
+ // table. "Take a seat, chummer."` -- not wholly quoted, so it
128
+ // fell past every check to exposition and printed entirely as
129
+ // narration: no speaker attribution, no speech colour, the
130
+ // terms of the meet indistinguishable from the furniture.
131
+ // Both players described the same symptom in the same words.
132
+ //
133
+ // The fix is to SPLIT, not to reclassify: the narration half
134
+ // is still narration and keeps its voice, the quoted half
135
+ // becomes real dialogue. Order is preserved -- a line that
136
+ // OPENS on a quote speaks first, so `"Take a seat," he says`
137
+ // doesn't come out backwards.
138
+ //
139
+ // The bar for "spoken sentence" is deliberately high, because
140
+ // the comment above is still right that a quote inside prose is
141
+ // usually just emphasis: three words, or terminal punctuation.
142
+ // `he mutters "fine" and turns away` keeps its quotes and stays
143
+ // one narration line, exactly as before.
144
+ const spoken = [];
145
+ const narration = t
146
+ .replace(/["“]([^"“”]+)["”]/g, (whole, inner) => {
147
+ const body = inner.trim();
148
+ if (body.split(/\s+/).length >= 3 || /[.!?…]$/.test(body)) {
149
+ // `"Take a seat," he says` -- the comma belongs to the
150
+ // speech TAG, not to what was said, and it reads as a
151
+ // dangling fragment once the tag is a separate line.
152
+ spoken.push(body.replace(/,$/, ''));
153
+ return '';
154
+ }
155
+ return whole;
156
+ })
157
+ .replace(/\s{2,}/g, ' ')
158
+ .replace(/^[\s,;:–—-]+/, '')
159
+ .replace(/[\s,;:–—-]+$/, '')
160
+ .trim();
161
+ if (spoken.length > 0) {
162
+ const speechFirst = /^["“]/.test(t);
163
+ const say = `[COMMAND] say ${spoken.join(' ')}`;
164
+ if (speechFirst)
165
+ rebuilt.push(say);
166
+ if (narration.length > 0)
167
+ rebuilt.push(narration);
168
+ if (!speechFirst)
169
+ rebuilt.push(say);
170
+ continue;
171
+ }
172
+ rebuilt.push(lines[i]);
173
+ }
174
+ return rebuilt;
175
+ }
11
176
  export class NPC extends Player {
12
177
  _dialogue;
13
178
  _description;
@@ -962,6 +1127,27 @@ ${worldEventsSummary}
962
1127
  const geographySummary = worldRooms.length > 0
963
1128
  ? `The ONLY locations that exist in this world: ${worldRooms.join(', ')}. When you tell anyone WHERE to go, where something is, or where something happened, use one of these room names EXACTLY. Never invent streets, bars, districts, or landmarks as places to actually visit -- atmospheric references to the wider city are fine as flavor, but never as a destination or objective location.`
964
1129
  : '';
1130
+ // The world's ACTUAL CAST -- geographySummary's missing twin, found
1131
+ // in the credential audit (2026-08-27). Rooms were pinned; people
1132
+ // never were, so an NPC could name someone who does not exist and
1133
+ // send the player off to find them. That is worse than an invented
1134
+ // place: a player who can't find a room concludes quickly that they
1135
+ // misheard it, but a NAME sounds like a lead, and they will work the
1136
+ // whole map looking for a person who was never in it.
1137
+ //
1138
+ // Deliberately the same shape as the geography pin, including its
1139
+ // escape valve -- names as FLAVOR (rivals, bosses, the dead) are
1140
+ // what makes a fixer sound like a fixer, so only names offered as
1141
+ // someone to actually go and TALK to are constrained.
1142
+ // Players come from a separate roster than NPCs (see Scene.allActors
1143
+ // vs Scene.getPlayers) -- both belong here, or a shared run's NPC
1144
+ // would treat a rider at the next table as someone who doesn't
1145
+ // exist.
1146
+ const worldCast = [
1147
+ ...(this._scene?.allActors ?? []),
1148
+ ...(this._scene?.getPlayers?.() ?? []),
1149
+ ].map(a => a.name).filter((n, i, all) => !!n && all.indexOf(n) === i);
1150
+ const castSummary = castPin(worldCast);
965
1151
  // ---------- exits (fully defensive) ----------
966
1152
  let safeExits = [];
967
1153
  try {
@@ -1064,6 +1250,31 @@ An ORDER is the only way these goods change hands -- never a dialogue sale, neve
1064
1250
  return `\nBARRIER AT YOUR POST (the lock${dirNote}): ${t.puzzle.riddle} It opens ONLY by its own mechanism -- the pass is "${t.puzzle.requiredPhrase ?? 'unknown even to you'}". You CANNOT unlock or open it any other way (no key, no shoulder, no goodwill), so NEVER claim to have opened it or promise to. The pass is a SECRET you guard with your standing: give it up only under real pressure -- beaten, genuinely frightened, well bribed, or masterfully played. Under that pressure, telling them how it opens IS how you comply.`;
1065
1251
  }).join('')
1066
1252
  : '';
1253
+ // CREDENTIALS YOU DO NOT HOLD (a real session: "the code Oren gave me
1254
+ // is wrong"). The block above is the ONLY place an NPC is ever handed
1255
+ // a real requiredPhrase, and it is keyed to the room they stand in --
1256
+ // so every NPC anywhere else was told nothing at all about codes, and
1257
+ // nothing is not the same as "you don't know". He isn't lying, he was
1258
+ // never told he doesn't know: asked for a pass, the AI supplies a
1259
+ // plausible one, the player types it, and the barrier -- correctly --
1260
+ // refuses it. The invented code costs the player their whole approach
1261
+ // and makes the NPC a liar by accident.
1262
+ //
1263
+ // The denial is CATEGORICAL, never an enumeration: listing the
1264
+ // scene's other barriers here would hand a stranger a map of every
1265
+ // lock in the world. And it always names the honest alternative,
1266
+ // because there always is one -- generation guarantees every puzzle's
1267
+ // answer is written down somewhere findable (see
1268
+ // scene-seed-generator.validateClueItems), so "I don't have it, toss
1269
+ // the place" is true advice, not a brush-off.
1270
+ //
1271
+ // Applies to EVERYONE, companions and the client included: a bound
1272
+ // spirit inventing its master a code is the same bug wearing a
1273
+ // leash.
1274
+ const passesHeld = (!this.allyOf && this.currentLocation?.getPuzzleTargets)
1275
+ ? this.currentLocation.getPuzzleTargets().filter(t => !t.puzzle.isSolved() && !!t.puzzle.requiredPhrase).length
1276
+ : 0;
1277
+ const credentialHonesty = credentialHonestyNote(passesHeld);
1067
1278
  // HOME TURF familiarity: if this NPC is on the player's contact
1068
1279
  // roster (the whole hub cast is, from session start -- see
1069
1280
  // Game.seedHomeTurfContacts), the AI should treat them as a KNOWN
@@ -1125,14 +1336,30 @@ An ORDER is the only way these goods change hands -- never a dialogue sale, neve
1125
1336
  // runner for it until she got shot over it). The client HIRED this
1126
1337
  // team and wants the job DONE: everything they know that helps --
1127
1338
  // routes, names, patterns, passwords -- is given freely on request.
1339
+ //
1340
+ // "PASSPHRASES" USED TO BE IN THAT LIST, and it was the single most
1341
+ // direct manufacturer of the invented-code bug (see
1342
+ // credentialHonesty below): the client is the first person a player
1343
+ // asks, is almost never standing at a barrier, and so held no real
1344
+ // credential -- while being told in so many words to hand passwords
1345
+ // over freely. That is an instruction to confabulate. The ruling's
1346
+ // FIRST branch is the one that fits a Johnson: they do not know how
1347
+ // to get in. Naming that explicitly is what makes the brief's own
1348
+ // "if you genuinely don't know a thing, say so plainly" fire
1349
+ // honestly instead of never firing at all -- and it keeps the
1350
+ // designed route intact, since the answer is always written down
1351
+ // somewhere in the world for the finding.
1128
1352
  const gameRef = this._scene?.ownerGame;
1129
1353
  const clientNote = gameRef?.currentClient?.name === this.name
1130
1354
  ? `
1131
1355
  YOU ARE THE CLIENT on this job: you hired ${this._scene?.getPlayer?.()?.name ?? 'the runner'}'s team and you WANT THE JOB DONE.
1132
- Everything you know that helps them -- locations, names, access patterns, passphrases, who
1133
- guards what -- you share FREELY the moment they ask. You never barter, extort, or withhold
1356
+ Everything you know that helps them -- locations, names, who guards what, what the job is
1357
+ worth -- you share FREELY the moment they ask. You never barter, extort, or withhold
1134
1358
  job-relevant information from your own runners: every obstacle they hit is YOUR money
1135
- burning. If you genuinely don't know a thing, say so plainly and point at who might. You
1359
+ burning. What you do NOT have is the inside of the place: you are the money, not the
1360
+ staff, so codes, passphrases, and lock combinations are exactly the thing you were hiring
1361
+ THEM to solve -- say so plainly when they ask, and send them to find it rather than
1362
+ handing them a number you'd be making up. If you genuinely don't know a thing, say so plainly and point at who might. You
1136
1363
  front half the pay at the meet and settle the rest on delivery (the engine moves the money
1137
1364
  -- never haggle it yourself unless they invoke a negotiation).`
1138
1365
  : '';
@@ -1177,11 +1404,12 @@ Your objective is to drive the story line.
1177
1404
  ${formattedExitsStr}
1178
1405
  ${roomInventoryDesc}
1179
1406
  ${waresDesc}
1180
- ${swagNote}${clientNote}${barrierBlock}
1407
+ ${swagNote}${clientNote}${barrierBlock}${credentialHonesty}
1181
1408
  ${familiarity}
1182
1409
  ${droneNote}
1183
1410
  ${companionNote}
1184
1411
  ${geographySummary}
1412
+ ${castSummary}
1185
1413
 
1186
1414
  ${lifestyleSummary}
1187
1415
  ${npcInventoryDesc}
@@ -1206,65 +1434,8 @@ Your objective is to drive the story line.
1206
1434
  const reply = await AI.ask(prompt);
1207
1435
  this._addToHistory(reply);
1208
1436
  const lines = toLines(reply);
1209
- // A BARE VERB IS STILL A COMMAND (playtest 2026-08-25: Ratchet's
1210
- // whole sales pitch printed as `say You got a datajack, right?
1211
- // ...` -- the literal word "say", no speaker, straight into the
1212
- // narration). Classification below keys on the [COMMAND] prefix,
1213
- // so a reply that drops it falls through to exposition and gets
1214
- // echoed verbatim: the line never reaches the conversation, never
1215
- // gets the "Ratchet:" attribution, and reads to the player as
1216
- // narrative cross-chatter (their words) sitting on top of the
1217
- // dialogue.
1218
- //
1219
- // The DONE/FAILED handler right below already learned this lesson
1220
- // for its own markers; this generalizes it to the verb that
1221
- // actually carries the fiction. Only `say` is repaired -- it is
1222
- // the one verb whose payload is free prose, so a bare `say ...`
1223
- // is unambiguous. Every other verb stays strict, because "take
1224
- // the credstick" as narration must NOT silently become a take.
1225
- //
1226
- // ...AND A BRACKETED ONE IS TOO (playtest 2026-08-26: "the AI
1227
- // conversation is still bleeding into the description text").
1228
- // Patch's line arrived as `[say] Maka, you're bleeding cred dry
1229
- // on that lowlife...` -- the model reaching for the [COMMAND]
1230
- // bracket convention and putting the VERB inside the brackets.
1231
- // The bare-verb repair above doesn't match it (it starts with
1232
- // "["), so it fell through to exposition and printed raw, marker
1233
- // and all, as narration. Same fault as the bare verb wearing a
1234
- // different hat, and the same reasoning bounds the fix: only
1235
- // `say` is repaired, because only `say` carries free prose.
1236
- for (let i = 0; i < lines.length; i++) {
1237
- const t = lines[i].trimStart();
1238
- if (t.startsWith('[COMMAND]'))
1239
- continue;
1240
- if (/^say\s+\S/.test(t)) {
1241
- lines[i] = `[COMMAND] ${t}`;
1242
- continue;
1243
- }
1244
- const bracketed = t.match(/^\[\s*say\s*\]\s*(\S.*)$/i);
1245
- if (bracketed) {
1246
- lines[i] = `[COMMAND] say ${bracketed[1]}`;
1247
- continue;
1248
- }
1249
- // ...AND A LINE THAT IS NOTHING BUT SPEECH MARKS IS SPEECH
1250
- // (playtest 2026-08-27, reported twice in one session: 'the
1251
- // "Take a seat..." comment isn't showing as he said it. It's in
1252
- // blue font, not in green' and, from the other player, 'I can
1253
- // hear him talking, all in blue text. Not the normal green').
1254
- //
1255
- // Mr. Osprey's whole briefing arrived as bare quoted prose with
1256
- // no marker at all, so it fell to exposition: narration colour,
1257
- // no "Mr. Osprey:" in front of it, and no way for a reader to
1258
- // tell the meet's terms from the room's furniture.
1259
- //
1260
- // A line whose ENTIRE content is one quoted string is dialogue.
1261
- // That is a narrow test on purpose -- narration that merely
1262
- // contains a quote ("he mutters \"fine\" and turns away") keeps
1263
- // its quotes inside other words and is left alone.
1264
- const quoted = t.match(/^["“]([^"“”]+)["”]$/);
1265
- if (quoted)
1266
- lines[i] = `[COMMAND] say ${quoted[1]}`;
1267
- }
1437
+ const repaired = splitSpokenLines(lines);
1438
+ lines.splice(0, lines.length, ...repaired);
1268
1439
  // DIRECTIVE MARKERS, any shape (real session: the heartbeat asked
1269
1440
  // for 'a line starting "DONE:"' and Jax's AI answered with bare
1270
1441
  // `say DONE: ...` -- no [COMMAND] prefix -- which fell through to