@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
@@ -0,0 +1,184 @@
1
+ import { isLinked, CALL_COLOR } from './comm-style.js';
2
+ import { isWatched, camerasLive, canSnoopFeeds } from './surveillance.js';
3
+ import { Category } from '../types/shared/item-enum.js';
4
+ import { hint } from './hints.js';
5
+ /**
6
+ * AROs -- AUGMENTED REALITY OBJECTS (player request 2026-08-26: "we
7
+ * need AROs on anything online"). The 2075 street is not bare: anything
8
+ * broadcasting wears an icon in the eye of anyone whose commlink is up.
9
+ * Until now that layer existed only from the INSIDE -- a jacked-in
10
+ * persona saw hosts, PANs and camera clusters as icons (grid-view.ts),
11
+ * and a decker standing in the same room in the flesh saw a bar.
12
+ *
13
+ * This is the same objects seen from the meat side, and deliberately
14
+ * the SAME GLYPHS (● host, ▣ PAN, ◎ cameras, ▤ a loose device), so the
15
+ * two views read as one world looked at twice rather than two games.
16
+ *
17
+ * WHAT IS DELIBERATELY NOT HERE:
18
+ * - Anything not broadcasting. Silent PANs, air-gapped hosts and
19
+ * powered-down gear have no wireless presence to annotate; that is
20
+ * what silence and a hard line BUY, and grid-view.ts omits them for
21
+ * the same reason.
22
+ * - Loot you have not found. Only items already in plain sight get a
23
+ * tag (Room.plainSightItems -- the same subset take.ts lets you
24
+ * sweep unsearched). An AR overlay that x-rayed a drawer would hand
25
+ * the room's whole inventory to anyone with a commlink and make
26
+ * "search" pointless.
27
+ * - Marks, alert states and host internals. Those are a persona's
28
+ * read, bought by being out there on the grid. AR is the shop
29
+ * window, not the back office.
30
+ */
31
+ /** Whether this actor's AR overlay is actually up right now. */
32
+ export function arSightUp(actor) {
33
+ // Meat only. A persona IS on the grid (grid-view.ts renders it), an
34
+ // astral form is nowhere near a commlink, and a jumped-in rigger is
35
+ // looking through a drone's cameras.
36
+ if (actor.plane !== 'meat')
37
+ return false;
38
+ // SILENCE IS NOT A BLINDFOLD (canon p.229 vs p.235-236, RAG-checked
39
+ // 2026-08-27). This used to return false while runningSilent, on the
40
+ // reasoning that the overlay rides the broadcast. Canon says
41
+ // otherwise: AR is what you RECEIVE (p.229), running silent is about
42
+ // what you EMIT -- it hides your icon from others and costs you -2
43
+ // dice on your own Matrix actions (p.235-236, see
44
+ // Player.matrixActionPenalty), and it "doesn't stop [your traffic]
45
+ // entirely". A silent runner still sees the street's AROs.
46
+ //
47
+ // Keeping the check here was ALSO a live bug: the district map paints
48
+ // its host markers off Player.hasMatrixEyes(), which never tested
49
+ // silence, so going silent printed prose about a dead overlay while
50
+ // the map kept painting hosts. hasMatrixEyes is the single source of
51
+ // truth now -- one predicate, so the two views cannot disagree.
52
+ return actor.hasMatrixEyes();
53
+ }
54
+ /**
55
+ * Every ARO in this room, one line each. Empty when AR is down, muted,
56
+ * hacked dark, or nothing here is online.
57
+ */
58
+ export function aroTags(scene, actor, room) {
59
+ if (!arSightUp(actor))
60
+ return [];
61
+ const tags = [];
62
+ // THE HOST's public face. An air-gapped host has no wireless presence
63
+ // at all -- from the street it simply is not there (canReachHost is
64
+ // the persona-side twin of this rule).
65
+ if (room.hasNode && room.nodeAccess !== 'wired') {
66
+ tags.push(room.hostCracked
67
+ ? `● ${room.name} host -- its marquee still turning, its walls in shreds.`
68
+ : `● ${room.name} host -- a public marquee turning slowly over the room.`);
69
+ }
70
+ // EVERY OTHER PRESENCE that is broadcasting. Same test grid-view.ts
71
+ // uses from the other side, so the two views never disagree about who
72
+ // is loud.
73
+ for (const other of scene.getActorsInRoom(room)) {
74
+ if (other === actor)
75
+ continue;
76
+ if (other.isIncapacitated() || !isLinked(other))
77
+ continue;
78
+ const master = other.getPanMaster();
79
+ if (!master)
80
+ continue;
81
+ tags.push(`▣ ${other.name} -- ${master.name} broadcasting, public profile up.`);
82
+ }
83
+ // THE EYES. Whether they are looped is knowledge you had to take from
84
+ // the host, so it shows only to whoever owns the feeds.
85
+ if (isWatched(room)) {
86
+ const rooms = scene.getRooms();
87
+ // The verb rides the tag: standing in the room IS the requirement
88
+ // for a direct connection (commands/tap.ts), so this is the one
89
+ // place the player is always in a position to use it.
90
+ tags.push(canSnoopFeeds(rooms, room, actor) && !camerasLive(rooms, room)
91
+ ? `◎ Camera cluster -- wireless, and looping empty hallways for the house.`
92
+ : `◎ Camera cluster -- wireless, and watching.${hint(` ("tap" cables into it -- a slaved lens can't hide behind its host)`)}`);
93
+ }
94
+ // LOOSE DEVICES lying in plain sight. A wireless deck on a table
95
+ // announces itself; one in a drawer you never opened does not.
96
+ for (const item of room.inventory.getAllItems()) {
97
+ if (item.plane !== 'meat')
98
+ continue;
99
+ if (!room.plainSightItems.has(item.name.toLowerCase()))
100
+ continue;
101
+ if (!WIRELESS_CATEGORIES.has(item.category))
102
+ continue;
103
+ tags.push(`▤ ${item.name} -- powered up and on the grid.`);
104
+ }
105
+ return tags;
106
+ }
107
+ /**
108
+ * THE HUD's AR READ (backlog item 4 -- Maka: "I still can't tell if I
109
+ * am in AR, there is no status icon"). TWO SLOTS, NEVER ONE. The HUD
110
+ * ranked five states down a single chain and could therefore only ever
111
+ * report the winner, so an overlay state was unreadable the moment
112
+ * anything outranked it. These answer different questions and have
113
+ * different cures:
114
+ *
115
+ * OVERLAY -- is the world being painted FOR me? Muting is my own
116
+ * choice ("ar" flips it back); a hacker cutting it is not
117
+ * ("reboot" is the only cure).
118
+ * LINK -- is my commlink BROADCASTING? That is what calls ride
119
+ * (call.ts wants a worn commlink) and what silence kills.
120
+ *
121
+ * They are genuinely independent -- canon p.229 vs p.235-236: AR is
122
+ * what you RECEIVE, silence is what you EMIT -- so a silent runner
123
+ * reads "AR ON | Link SILENT", both true at once. One slot could never
124
+ * say that, which was the whole complaint.
125
+ *
126
+ * The overlay slot asks arSightUp() rather than re-deriving state, so
127
+ * the HUD, the AR block on "look", and the district map's host markers
128
+ * all answer to one predicate and cannot drift apart. The old line
129
+ * tested `equipment.head?.commlink` for BOTH meanings, so a decker
130
+ * whose PAN master is a cyberdeck and who wears no commlink was told
131
+ * "Link offline" while their overlay painted happily -- literally the
132
+ * state Maka could not read.
133
+ *
134
+ * No gray anywhere (standing ruling): blessed's gray is ANSI
135
+ * bright-black and vanishes on stock dark palettes. White is the
136
+ * neutral.
137
+ */
138
+ export function arStatusSlots(actor) {
139
+ const overlay = arSightUp(actor)
140
+ ? `{${CALL_COLOR}-fg}◉ AR ON{/${CALL_COLOR}-fg}`
141
+ : actor.arOffline
142
+ // CUT outranks MUTED: the state that was done TO you, and that
143
+ // survives you flipping your own switch, is the one you need to
144
+ // see. Its cure is named once, on the link slot.
145
+ ? `{red-fg}◌ AR CUT{/red-fg}`
146
+ : actor.arMuted
147
+ ? `{white-fg}◌ AR OFF{/white-fg}`
148
+ : !actor.getPanMaster() && !actor.isTechnomancer()
149
+ ? `{white-fg}◌ no AR rig{/white-fg}`
150
+ // Off-plane, or any future state that puts the overlay down
151
+ // without being one of the above. game.ts drops the slot
152
+ // entirely while off-plane -- a persona has its own HUD line.
153
+ : `{white-fg}◌ AR dark{/white-fg}`;
154
+ // The link slot keeps asking for a WORN commlink, because that is
155
+ // what call.ts asks for. A deck-only decker reading "AR ON | Link
156
+ // offline" is not a contradiction -- it is the true and previously
157
+ // unsayable answer: the overlay paints, nobody can call you.
158
+ const link = actor.equipment.head?.commlink == null
159
+ ? `{white-fg}Link offline{/white-fg}`
160
+ : actor.arOffline
161
+ ? `{red-fg}Link CRACKED -- reboot{/red-fg}`
162
+ : actor.runningSilent
163
+ ? `{magenta-fg}Link SILENT{/magenta-fg}`
164
+ : `{${CALL_COLOR}-fg}Link online{/${CALL_COLOR}-fg}`;
165
+ return { overlay, link };
166
+ }
167
+ /** The tags as the standard cyan block, or '' when there is nothing to
168
+ * show -- callers append it to their own output. */
169
+ export function aroBlock(scene, actor, room) {
170
+ const tags = aroTags(scene, actor, room);
171
+ if (tags.length === 0)
172
+ return '';
173
+ return `{cyan-fg}AR OVERLAY:{/cyan-fg}\n${tags.map(t => ` {cyan-fg}${t}{/cyan-fg}`).join('\n')}`;
174
+ }
175
+ /** Gear that talks to the grid on its own. Weapons are absent on
176
+ * purpose: a smartgun's link belongs to its carrier's PAN, and it is
177
+ * already covered by their ▣ line. */
178
+ const WIRELESS_CATEGORIES = new Set([
179
+ Category.Commlink,
180
+ Category.Cyberdeck,
181
+ Category.RCC,
182
+ Category.Drone,
183
+ ]);
184
+ //# sourceMappingURL=ar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ar.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/ar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import type { Player } from '../models/player.js';
2
+ import type { NPC } from '../models/npc.js';
3
+ import type { Room } from '../models/room.js';
4
+ /**
5
+ * WHO CAN OVERHEAR A MURMUR (playtest, Deditri: "a private place for
6
+ * calls"). A call is audible to the room, and that is correct and
7
+ * load-bearing -- it is how a table learns what a partner is arranging,
8
+ * and NPC AIs react to the half of a conversation they catch. What was
9
+ * missing was anywhere to GO to avoid it: say.ts's call fan-out
10
+ * iterated `room.getActors()` flat, while ordinary speech (Room.say)
11
+ * had been spot-local since the "at" spots pass. Two code paths
12
+ * answering "who hears this" had drifted apart, so ducking into the
13
+ * booths changed nothing -- Patch at the bar and Old Cray in the booths
14
+ * overheard you either way.
15
+ *
16
+ * The place to duck into already existed. The hub seeds carry it and
17
+ * the fiction was already written for it: "High-backed booths built for
18
+ * quiet deals", "the dim table nobody chooses by accident", the Night
19
+ * Market's "shadowed edge". Nothing new is invented here; the call path
20
+ * just respects the position everyone else already respects.
21
+ *
22
+ * THE RULE, and why it is not Room.say's rule: room speech that finds
23
+ * nobody at your spot escalates to a SHOUT and carries room-wide -- that
24
+ * is how you call across a bar. A commlink held to your face never
25
+ * escalates; talking quietly into it is the whole point of it. So a
26
+ * murmur reaches your spot and stops there.
27
+ *
28
+ * WHAT DOES NOT BUY PRIVACY, deliberately:
29
+ * - CIRCULATING (no atSpot) is the compat state and means "anywhere in
30
+ * the room" -- it both reaches and is reached by everything. It is
31
+ * also the common case, and it stays exactly as loud as it has always
32
+ * been.
33
+ * - THE OPEN FLOOR is a real position but it is bare ground in the
34
+ * middle of the room, no cover, always visible (see spots.ts). Being
35
+ * apart from people is not the same as being out of earshot, and a
36
+ * runner muttering into their link in the middle of a bar is not
37
+ * having a private call.
38
+ * Privacy is furniture you go and stand at. You never get it by
39
+ * accident, and you never get it by standing back.
40
+ *
41
+ * Position is read off `Player.atSpot` through spots.ts on every call.
42
+ * Nothing here caches, stores, or derives a second notion of where
43
+ * anybody is.
44
+ */
45
+ /**
46
+ * Everyone in the speaker's room close enough to catch a murmur.
47
+ * From a named spot: whoever shares it, plus anyone circulating.
48
+ * From the open floor or while circulating: the whole room.
49
+ */
50
+ export declare function murmurAudience(speaker: Player): (Player | NPC)[];
51
+ export interface EarshotReading {
52
+ /** The room declares named places at all. When it doesn't there is
53
+ * nowhere in THIS room to duck into and the answer is another room. */
54
+ spotted: boolean;
55
+ /** Where the speaker stands; undefined = circulating (see spots.ts). */
56
+ spot?: string;
57
+ /** Circulating or on the open floor: nothing between you and the room. */
58
+ inTheOpen: boolean;
59
+ /** Who would catch a murmur from here. */
60
+ audience: (Player | NPC)[];
61
+ /** Nobody would. */
62
+ unheard: boolean;
63
+ /** Named places here with nobody at them -- where to go instead. */
64
+ quiet: string[];
65
+ }
66
+ export declare function readEarshot(speaker: Player): EarshotReading;
67
+ /**
68
+ * Named places in this room that nobody is standing at -- the honest
69
+ * answer to "so where do I go", thresholds sorted to the back. A
70
+ * CIRCULATING actor is at none of them and all of them at once (the
71
+ * compat rule), so their presence disqualifies every spot: there is
72
+ * nowhere to get away from somebody who is everywhere. The open floor
73
+ * is never offered; it is the one position that explicitly buys
74
+ * nothing.
75
+ */
76
+ export declare function quietSpotsIn(room: Room, speaker: Player): string[];
@@ -0,0 +1,98 @@
1
+ import { sameSpot, spotOf, spotsActive, OPEN_FLOOR } from './spots.js';
2
+ /**
3
+ * WHO CAN OVERHEAR A MURMUR (playtest, Deditri: "a private place for
4
+ * calls"). A call is audible to the room, and that is correct and
5
+ * load-bearing -- it is how a table learns what a partner is arranging,
6
+ * and NPC AIs react to the half of a conversation they catch. What was
7
+ * missing was anywhere to GO to avoid it: say.ts's call fan-out
8
+ * iterated `room.getActors()` flat, while ordinary speech (Room.say)
9
+ * had been spot-local since the "at" spots pass. Two code paths
10
+ * answering "who hears this" had drifted apart, so ducking into the
11
+ * booths changed nothing -- Patch at the bar and Old Cray in the booths
12
+ * overheard you either way.
13
+ *
14
+ * The place to duck into already existed. The hub seeds carry it and
15
+ * the fiction was already written for it: "High-backed booths built for
16
+ * quiet deals", "the dim table nobody chooses by accident", the Night
17
+ * Market's "shadowed edge". Nothing new is invented here; the call path
18
+ * just respects the position everyone else already respects.
19
+ *
20
+ * THE RULE, and why it is not Room.say's rule: room speech that finds
21
+ * nobody at your spot escalates to a SHOUT and carries room-wide -- that
22
+ * is how you call across a bar. A commlink held to your face never
23
+ * escalates; talking quietly into it is the whole point of it. So a
24
+ * murmur reaches your spot and stops there.
25
+ *
26
+ * WHAT DOES NOT BUY PRIVACY, deliberately:
27
+ * - CIRCULATING (no atSpot) is the compat state and means "anywhere in
28
+ * the room" -- it both reaches and is reached by everything. It is
29
+ * also the common case, and it stays exactly as loud as it has always
30
+ * been.
31
+ * - THE OPEN FLOOR is a real position but it is bare ground in the
32
+ * middle of the room, no cover, always visible (see spots.ts). Being
33
+ * apart from people is not the same as being out of earshot, and a
34
+ * runner muttering into their link in the middle of a bar is not
35
+ * having a private call.
36
+ * Privacy is furniture you go and stand at. You never get it by
37
+ * accident, and you never get it by standing back.
38
+ *
39
+ * Position is read off `Player.atSpot` through spots.ts on every call.
40
+ * Nothing here caches, stores, or derives a second notion of where
41
+ * anybody is.
42
+ */
43
+ /**
44
+ * Everyone in the speaker's room close enough to catch a murmur.
45
+ * From a named spot: whoever shares it, plus anyone circulating.
46
+ * From the open floor or while circulating: the whole room.
47
+ */
48
+ export function murmurAudience(speaker) {
49
+ const others = speaker.currentLocation.getActors().filter(a => a !== speaker);
50
+ const spot = spotOf(speaker);
51
+ if (spot === undefined || spot === OPEN_FLOOR)
52
+ return others;
53
+ return others.filter(a => sameSpot(speaker, a));
54
+ }
55
+ export function readEarshot(speaker) {
56
+ const room = speaker.currentLocation;
57
+ const spot = spotOf(speaker);
58
+ const audience = murmurAudience(speaker);
59
+ return {
60
+ spotted: spotsActive(room),
61
+ spot,
62
+ inTheOpen: spot === undefined || spot === OPEN_FLOOR,
63
+ audience,
64
+ unheard: audience.length === 0,
65
+ quiet: quietSpotsIn(room, speaker),
66
+ };
67
+ }
68
+ /**
69
+ * A THRESHOLD is not a hiding place. The same name convention spots.ts
70
+ * uses to find the spot that owns a doorway (see entrySpotFor) -- an
71
+ * empty doorway is still empty, and still worth listing, but it is the
72
+ * worst place in the room to take a call and must never be the one the
73
+ * report recommends.
74
+ */
75
+ const DOORISH = /door|entrance|entry|threshold|gate/i;
76
+ /**
77
+ * Named places in this room that nobody is standing at -- the honest
78
+ * answer to "so where do I go", thresholds sorted to the back. A
79
+ * CIRCULATING actor is at none of them and all of them at once (the
80
+ * compat rule), so their presence disqualifies every spot: there is
81
+ * nowhere to get away from somebody who is everywhere. The open floor
82
+ * is never offered; it is the one position that explicitly buys
83
+ * nothing.
84
+ */
85
+ export function quietSpotsIn(room, speaker) {
86
+ if (!spotsActive(room))
87
+ return [];
88
+ const others = room.getActors().filter(a => a !== speaker);
89
+ if (others.some(a => spotOf(a) === undefined))
90
+ return [];
91
+ const taken = new Set(others.map(a => spotOf(a)));
92
+ const mine = spotOf(speaker);
93
+ const empty = (room.spots ?? [])
94
+ .map(s => s.name)
95
+ .filter(name => name !== OPEN_FLOOR && name !== mine && !taken.has(name));
96
+ return [...empty.filter(n => !DOORISH.test(n)), ...empty.filter(n => DOORISH.test(n))];
97
+ }
98
+ //# sourceMappingURL=earshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"earshot.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/earshot.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU;QAAE,OAAO,MAAM,CAAC;IAC7D,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAW,CAAC,CAAC,CAAC;AAC5D,CAAC;AAkBD,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IACzC,OAAO;QACL,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC;QAC1B,IAAI;QACJ,SAAS,EAAE,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU;QACpD,QAAQ;QACR,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;QAC9B,KAAK,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC;KACnC,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,OAAO,GAAG,qCAAqC,CAAC;AAEtD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU,EAAE,OAAe;IACtD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAW,CAAC,KAAK,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAChB,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC"}
@@ -52,15 +52,27 @@ export class GenerationCapture {
52
52
  prompt: clampPrompt(rec.prompt ?? ''),
53
53
  reply: clampReply(rec.reply ?? ''),
54
54
  });
55
- // EVICT THE OLDEST, don't refuse the newest (fixed 2026-08-26 after
56
- // review). The first cut returned early once full, which is
57
- // first-12-wins -- and the records a bad run produces LAST are its
58
- // repair-round failures, precisely the ones worth training on. A
59
- // pathological run therefore dropped its most interesting evidence
60
- // and kept its least. The bound was the point; which end it bites
61
- // was an accident.
62
- while (this.records.length > this.MAX_RECORDS)
63
- this.records.shift();
55
+ // EVICT BY VALUE, NOT BY POSITION (fixed 2026-08-27; supersedes the
56
+ // 2026-08-26 evict-oldest fix, which superseded the original
57
+ // first-12-wins refusal). Both earlier policies were positional,
58
+ // and the first production batch proved position is the wrong axis
59
+ // outright: 12 records, exactly MAX_RECORDS, and pipeline 1 was
60
+ // entirely absent along with pipeline 2's skeleton. But reaching
61
+ // pipeline 3 MEANS pipelines 1 and 2 failed -- so evict-oldest had
62
+ // thrown away precisely the fault records and kept the successful
63
+ // run. The corpus preserved the successes and discarded the faults,
64
+ // the exact inverse of what this module exists for.
65
+ //
66
+ // Successes are cheap and numerous (one per stage per pipeline);
67
+ // faults are the entire point. So when the buffer is full, drop the
68
+ // OLDEST ACCEPTED record, and only fall back to dropping the oldest
69
+ // fault when there is nothing else left to give up. A 12-slot
70
+ // buffer under this policy would have kept everything interesting
71
+ // from that run and lost nothing that mattered.
72
+ while (this.records.length > this.MAX_RECORDS) {
73
+ const victim = this.records.findIndex(r => r.outcome === 'accepted');
74
+ this.records.splice(victim === -1 ? 0 : victim, 1);
75
+ }
64
76
  }
65
77
  /** Writes only when something was actually captured. Never throws --
66
78
  * a corpus is a nice-to-have and must never cost the player a run. */
@@ -1 +1 @@
1
- {"version":3,"file":"generation-capture.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/generation-capture.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generation-capture.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/generation-capture.ts"],"names":[],"mappings":"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"}
@@ -12,5 +12,21 @@ import { Scene } from '../models/scene.js';
12
12
  * air-gapped, ◆ persona, ▣ PAN, ◇ data.
13
13
  */
14
14
  export declare function gridIcons(scene: Scene, actor: Player, room: Room): string[];
15
+ /**
16
+ * THE ROOM AS THE GRID DRAWS IT (player ruling 2026-08-26: "looking in
17
+ * the matrix shouldn't show the meatworld"). A persona's `look` used to
18
+ * open with the room's own meat prose -- steam off the noodle pot, the
19
+ * cracked vinyl, whoever is leaning on the counter. None of that is
20
+ * where a persona stands: the grid OVERLAYS a space, it does not
21
+ * furnish it, and a decker reading furniture they cannot touch (from a
22
+ * body slumped rooms away) is the plane fiction coming apart.
23
+ *
24
+ * So this is the orientation that replaces the prose: the room's NAME
25
+ * -- icons are labelled, and the grid map (map.ts) lists rooms by name
26
+ * for exactly the same reason -- and how dense the local grid is. The
27
+ * host itself is deliberately NOT described here: it is an ICON, and
28
+ * gridIcons below already names it with its state and its verbs.
29
+ */
30
+ export declare function gridSculpt(actor: Player, room: Room): string;
15
31
  /** The icons rendered as the standard cyan block, or the thin-grid line. */
16
32
  export declare function gridIconBlock(scene: Scene, actor: Player, room: Room): string;
@@ -58,11 +58,44 @@ export function gridIcons(scene, actor, room) {
58
58
  icons.push(`◎ Camera cluster -- live, and answering to YOU as much as the house. ("snoop <room>" watches remotely)`);
59
59
  }
60
60
  else {
61
- icons.push(`◎ Camera cluster -- live, feeding the site's host. Loud acts here travel. (own the host to loop them)`);
61
+ // Seen from the grid, the cluster is worth naming as a WAY IN,
62
+ // not just a hazard (backlog item 10): it is slaved to the host,
63
+ // and a cable into a slave is a road to its master (p.233). The
64
+ // catch is that a persona cannot hold a cable -- so this reads as
65
+ // something your BODY could do, which is the price the rule
66
+ // charges. See commands/tap.ts.
67
+ icons.push(`◎ Camera cluster -- live, feeding the site's host. Loud acts here travel. (own the host to loop them -- or walk in and "tap" a lens in the flesh: slaved to the host means a key to the host)`);
62
68
  }
63
69
  }
64
70
  return icons;
65
71
  }
72
+ /**
73
+ * THE ROOM AS THE GRID DRAWS IT (player ruling 2026-08-26: "looking in
74
+ * the matrix shouldn't show the meatworld"). A persona's `look` used to
75
+ * open with the room's own meat prose -- steam off the noodle pot, the
76
+ * cracked vinyl, whoever is leaning on the counter. None of that is
77
+ * where a persona stands: the grid OVERLAYS a space, it does not
78
+ * furnish it, and a decker reading furniture they cannot touch (from a
79
+ * body slumped rooms away) is the plane fiction coming apart.
80
+ *
81
+ * So this is the orientation that replaces the prose: the room's NAME
82
+ * -- icons are labelled, and the grid map (map.ts) lists rooms by name
83
+ * for exactly the same reason -- and how dense the local grid is. The
84
+ * host itself is deliberately NOT described here: it is an ICON, and
85
+ * gridIcons below already names it with its state and its verbs.
86
+ */
87
+ export function gridSculpt(actor, room) {
88
+ const header = `{cyan-fg}THE GRID :: ${room.name.toUpperCase()}{/cyan-fg}`;
89
+ // Thin ground says nothing extra on purpose: gridIconBlock's own
90
+ // empty-case line already calls it thin, and where there ARE icons
91
+ // they speak for themselves. Only a host earns a second line.
92
+ if (!room.hasNode)
93
+ return header;
94
+ const ground = canReachHost(actor, room)
95
+ ? `Dense ground -- a host's architecture stands over this patch, and everything on it answers to that.`
96
+ : `Dead ground -- there is architecture here, but no door onto it from the wireless grid.`;
97
+ return `${header}\n{cyan-fg}${ground}{/cyan-fg}`;
98
+ }
66
99
  /** The icons rendered as the standard cyan block, or the thin-grid line. */
67
100
  export function gridIconBlock(scene, actor, room) {
68
101
  const icons = gridIcons(scene, actor, room);
@@ -1 +1 @@
1
- {"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/grid-view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../../../../../../../src/commands/game/sideQuest/utilities/grid-view.ts"],"names":[],"mappings":"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"}
@@ -600,6 +600,40 @@ export const OPEN_FLOOR_NAME = 'open floor';
600
600
  function clamp(n, lo, hi) { return Math.max(lo, Math.min(hi, n)); }
601
601
  function jitter(rng) { return Math.floor(rng() * 3) - 1; }
602
602
  function chebyshev(a, b) { return Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y)); }
603
+ /**
604
+ * LATENT HAZARD, investigated 2026-08-27 and deliberately NOT fixed:
605
+ * this scans a SQUARE neighbourhood with no wall constraint, so an exit
606
+ * cell whose wall midpoint is taken can in principle be walked one step
607
+ * INWARD, off its wall and into open floor. That is the shape of the
608
+ * open backlog item "the back door is in the middle of the room" -- but
609
+ * it is NOT that bug. Probed with a tiny room, four exits and a
610
+ * deliberately crowded north wall: all four exit cells stayed on their
611
+ * walls, because the r=1 ring reaches the along-wall neighbours before
612
+ * any interior cell. It needs a fully occupied wall ROW to bite, which
613
+ * the placement order makes hard to arrange. Left alone rather than
614
+ * fixed speculatively.
615
+ *
616
+ * WHERE THAT BUG ACTUALLY LIVES, for whoever picks the item up (probed,
617
+ * not guessed -- all 25 shipped seed rooms are clean, so it only bites
618
+ * GENERATED scenes):
619
+ * 1. Room.namedDoorwayFor() rescues only ONE doorway-named spot per
620
+ * room -- it is a `.find`, singular. A room drafted with both a
621
+ * "front door" and a "back door" binds the first and leaves the
622
+ * second attached to no exit, however many exits are free.
623
+ * 2. Any spot left unbound falls through to the "unplaced spots:
624
+ * spread out" sampler at the bottom of synthesizeGrid, which is a
625
+ * max-min distance rejection sample with NO perimeter constraint.
626
+ * Correct for a table, wrong for a door: it seats the thing in
627
+ * open floor. Reproduced at (1,4) of a 12x8 room.
628
+ * 3. namedDoorwayFor only fires at all when some exit direction is
629
+ * UNCLAIMED, so a room whose every exit carries a seed `atSpot`
630
+ * pointing at non-doorway furniture strands its doorway spot the
631
+ * same way even when there is only one.
632
+ * The multi-exit centroid hub rule below is NOT implicated: it is
633
+ * reachable only for a spot the seed explicitly bound to several exits,
634
+ * and Night Market's "stalls" -- the case it was written for -- places
635
+ * correctly.
636
+ */
603
637
  function nearestFree(start, occupied, dims, exists) {
604
638
  if (exists(start) && !occupied.has(key(start)))
605
639
  return start;