@maka/maka-cli 5.50.0 → 5.52.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 (99) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/augmentations.d.ts +61 -0
  3. package/bundle/typescript/src/commands/game/sideQuest/augmentations.js +222 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/augmentations.js.map +1 -1
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js +1 -1
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/ask.js.map +1 -1
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js +1 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/bluff.js.map +1 -1
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/buy.d.ts +4 -0
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js +35 -0
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/buy.js.map +1 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js +32 -2
  13. package/bundle/typescript/src/commands/game/sideQuest/commands/call.js.map +1 -1
  14. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.d.ts +11 -0
  15. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js +183 -13
  16. package/bundle/typescript/src/commands/game/sideQuest/commands/cast.js.map +1 -1
  17. package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js +30 -10
  18. package/bundle/typescript/src/commands/game/sideQuest/commands/catalog.js.map +1 -1
  19. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +4 -1
  20. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js.map +1 -1
  21. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js +18 -2
  22. package/bundle/typescript/src/commands/game/sideQuest/commands/go.js.map +1 -1
  23. package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js +2 -2
  24. package/bundle/typescript/src/commands/game/sideQuest/commands/haggle.js.map +1 -1
  25. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +45 -9
  26. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js.map +1 -1
  27. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.d.ts +0 -6
  28. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +43 -4
  29. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -1
  30. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js +1 -1
  31. package/bundle/typescript/src/commands/game/sideQuest/commands/move.js.map +1 -1
  32. package/bundle/typescript/src/commands/game/sideQuest/commands/note.d.ts +20 -5
  33. package/bundle/typescript/src/commands/game/sideQuest/commands/note.js +34 -10
  34. package/bundle/typescript/src/commands/game/sideQuest/commands/note.js.map +1 -1
  35. package/bundle/typescript/src/commands/game/sideQuest/commands/persuade.js +1 -1
  36. package/bundle/typescript/src/commands/game/sideQuest/commands/persuade.js.map +1 -1
  37. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js +1 -1
  38. package/bundle/typescript/src/commands/game/sideQuest/commands/rest.js.map +1 -1
  39. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js +2 -2
  40. package/bundle/typescript/src/commands/game/sideQuest/commands/search.js.map +1 -1
  41. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js +17 -5
  42. package/bundle/typescript/src/commands/game/sideQuest/commands/sheet.js.map +1 -1
  43. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.d.ts +21 -0
  44. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js +94 -0
  45. package/bundle/typescript/src/commands/game/sideQuest/commands/sin.js.map +1 -0
  46. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js +52 -30
  47. package/bundle/typescript/src/commands/game/sideQuest/commands/spells.js.map +1 -1
  48. package/bundle/typescript/src/commands/game/sideQuest/commands/use.js +1 -1
  49. package/bundle/typescript/src/commands/game/sideQuest/commands/use.js.map +1 -1
  50. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.d.ts +0 -8
  51. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js +41 -0
  52. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-chunks.js.map +1 -1
  53. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +28 -0
  54. package/bundle/typescript/src/commands/game/sideQuest/game.js +109 -27
  55. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  56. package/bundle/typescript/src/commands/game/sideQuest/models/npc.d.ts +20 -0
  57. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js +117 -6
  58. package/bundle/typescript/src/commands/game/sideQuest/models/npc.js.map +1 -1
  59. package/bundle/typescript/src/commands/game/sideQuest/models/player.d.ts +24 -1
  60. package/bundle/typescript/src/commands/game/sideQuest/models/player.js +63 -15
  61. package/bundle/typescript/src/commands/game/sideQuest/models/player.js.map +1 -1
  62. package/bundle/typescript/src/commands/game/sideQuest/models/room.js +18 -1
  63. package/bundle/typescript/src/commands/game/sideQuest/models/room.js.map +1 -1
  64. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +7 -1
  65. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.d.ts +1 -0
  66. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js +4 -0
  67. package/bundle/typescript/src/commands/game/sideQuest/types/shared/item-enum.js.map +1 -1
  68. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.d.ts +14 -4
  69. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js +219 -86
  70. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog-data.js.map +1 -1
  71. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog.js +18 -4
  72. package/bundle/typescript/src/commands/game/sideQuest/utilities/catalog.js.map +1 -1
  73. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js +14 -4
  74. package/bundle/typescript/src/commands/game/sideQuest/utilities/persistence.js.map +1 -1
  75. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.d.ts +18 -0
  76. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js +23 -0
  77. package/bundle/typescript/src/commands/game/sideQuest/utilities/planes.js.map +1 -1
  78. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.d.ts +9 -0
  79. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js +11 -0
  80. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-grid.js.map +1 -1
  81. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js +16 -2
  82. package/bundle/typescript/src/commands/game/sideQuest/utilities/room-view.js.map +1 -1
  83. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.d.ts +13 -0
  84. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js +19 -2
  85. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js.map +1 -1
  86. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.d.ts +20 -0
  87. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js +141 -5
  88. package/bundle/typescript/src/commands/game/sideQuest/utilities/spots.js.map +1 -1
  89. package/bundle/typescript/src/commands/set/global.sub.cmd.js +18 -1
  90. package/bundle/typescript/src/commands/set/global.sub.cmd.js.map +1 -1
  91. package/bundle/typescript/src/tools/ai/ai.class.d.ts +1 -1
  92. package/bundle/typescript/src/tools/ai/ai.class.js +39 -7
  93. package/bundle/typescript/src/tools/ai/ai.class.js.map +1 -1
  94. package/bundle/typescript/src/tools/fsi/fsi.interfaces.d.ts +1 -0
  95. package/bundle/typescript/src/tools/fsi/fsi.interfaces.js.map +1 -1
  96. package/bundle/typescript/src/tools/https/https.class.d.ts +19 -0
  97. package/bundle/typescript/src/tools/https/https.class.js +36 -0
  98. package/bundle/typescript/src/tools/https/https.class.js.map +1 -1
  99. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import blessed from 'blessed';
2
+ import { dirname } from 'path';
2
3
  import { capitalCase } from 'change-case';
3
4
  import { Category } from './types/shared/item-enum.js';
4
5
  import { Item } from './models/item.js';
@@ -12,6 +13,7 @@ import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js'
12
13
  import { isFence, LIFESTYLE_TIERS } from './utilities/commerce.js';
13
14
  import { bestFakeSin, wandRead, processArrest } from './utilities/sin.js';
14
15
  import { renderMapViewport } from './utilities/map-view.js';
16
+ import { tallestRoomRows } from './utilities/room-grid.js';
15
17
  import { renderRoomLayoutCompact } from './utilities/room-view.js';
16
18
  import { getPref } from './utilities/prefs.js';
17
19
  import { rollPool, formatRoll } from './utilities/dice.js';
@@ -24,6 +26,7 @@ import { LookCommand } from './commands/look.js';
24
26
  import { TakeCommand } from './commands/take.js';
25
27
  import { LootCommand } from './commands/loot.js';
26
28
  import { NoteCommand } from './commands/note.js';
29
+ import { SinCommand } from './commands/sin.js';
27
30
  import { GoCommand } from './commands/go.js';
28
31
  import { UseCommand } from './commands/use.js';
29
32
  import { EquipCommand } from './commands/equip.js';
@@ -182,6 +185,17 @@ export default class Game {
182
185
  get hasHub() {
183
186
  return this._hubScene !== undefined;
184
187
  }
188
+ /**
189
+ * This play session's own directory -- the timestamped folder holding
190
+ * game.log, session.log, launch.json and any scenes drafted during
191
+ * the run. Derived from the log path the same way SceneSeedGenerator
192
+ * derives it (dirname), so everything a session produces lands
193
+ * together. undefined for harnesses and headless clients, which run
194
+ * with no log path at all -- callers must have a fallback.
195
+ */
196
+ get sessionDir() {
197
+ return this._logFilePath ? dirname(this._logFilePath) : undefined;
198
+ }
185
199
  /** The active job's name (seed name) -- notoriety incidents cite it. */
186
200
  get currentJobName() {
187
201
  return this.sceneSeed?.name;
@@ -1617,6 +1631,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
1617
1631
  CommandFactory.registerCommand('take', TakeCommand);
1618
1632
  CommandFactory.registerCommand('loot', LootCommand);
1619
1633
  CommandFactory.registerCommand('note', NoteCommand);
1634
+ CommandFactory.registerCommand('sin', SinCommand);
1635
+ CommandFactory.registerCommand('sins', SinCommand);
1636
+ CommandFactory.registerCommand('papers', SinCommand);
1620
1637
  CommandFactory.registerCommand('use', UseCommand);
1621
1638
  CommandFactory.registerCommand('equip', EquipCommand);
1622
1639
  CommandFactory.registerCommand('unequip', UnequipCommand);
@@ -1836,6 +1853,29 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
1836
1853
  this.initStatusBox(screen);
1837
1854
  this.initMapBox(screen); // docked atop the Mechanics column
1838
1855
  this._screen = screen;
1856
+ // Paint the meat-plane border up front rather than leaving blessed's
1857
+ // default until the first status refresh.
1858
+ this.paintPlaneBorder();
1859
+ // RESIZE REDRAWS (player request 2026-08-25). blessed re-solves its
1860
+ // own percentage geometry on a resize, but the docked panels are
1861
+ // drawn CONTENT, not layout: the district viewport's width and the
1862
+ // room box's elevation justification are both computed from
1863
+ // screen.width at paint time (see updateExits), so after a resize
1864
+ // they kept the old terminal's dimensions until the next command
1865
+ // happened to repaint them -- a map sized for a window that no
1866
+ // longer exists, which is exactly how content spills a border.
1867
+ screen.on('resize', () => {
1868
+ try {
1869
+ this.updateStatus();
1870
+ const here = this.player?.currentLocation;
1871
+ if (here)
1872
+ this.updateExits(here);
1873
+ screen.render();
1874
+ }
1875
+ catch (err) {
1876
+ Logger.getInstance().write(`resize redraw failed: ${err instanceof Error ? err.message : String(err)}`);
1877
+ }
1878
+ });
1839
1879
  }
1840
1880
  /** The engine half of startup: scene synthesis, command registration,
1841
1881
  * hub seeding, resume overlay -- no widget contact. */
@@ -3177,9 +3217,13 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3177
3217
  * (the "eexxiitt" bug, see initInputBox). Hidden until the first
3178
3218
  * setMapOverlay/setRoomOverlay with content.
3179
3219
  */
3180
- // 9 viewport rows + a caption row (the room name / "@ spot", moved off
3181
- // the HUD 2026-08-25) + border.
3182
- static MAP_DOCK_ROWS = 12;
3220
+ // DERIVED, not chosen: the tallest room class's rows + a caption row
3221
+ // (the room name / "@ spot", moved off the HUD 2026-08-25) + border.
3222
+ // Hardcoding this is what clipped the bottom two rows off every 'huge'
3223
+ // room when the size classes were retuned upward -- the panel stayed
3224
+ // at 9 while the rooms grew to 11 (player note: "the Room minimap is
3225
+ // very important, let's set the height of the largest room size").
3226
+ static MAP_DOCK_ROWS = tallestRoomRows() + 3;
3183
3227
  /** Must track the roomMapBox's `width` below -- updateExits derives
3184
3228
  * the inner width from it to right-justify the elevation bar. */
3185
3229
  static ROOM_DOCK_PCT = 0.23;
@@ -3305,6 +3349,9 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3305
3349
  if (this.remoteSession)
3306
3350
  return;
3307
3351
  this._statusBox.setContent(this.statusLinesFor(this.player).join('\n'));
3352
+ // The log's border tracks the plane -- updateStatus is the one hook
3353
+ // every plane transition already funnels through.
3354
+ this.paintPlaneBorder();
3308
3355
  this._screen.render();
3309
3356
  }
3310
3357
  /** ui plumbing for session mode (utilities/shared-run.ts). */
@@ -3319,6 +3366,51 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3319
3366
  * no widgets. updateStatus paints it for the local player; a shared-run
3320
3367
  * server ships it per player as status events (Phase C).
3321
3368
  */
3369
+ /**
3370
+ * What's in your hands, in one phrase. Three armed states on the meat
3371
+ * plane: drawn, HOLSTERED (carried but riding leather -- "brandish"
3372
+ * puts it in hand; combat auto-draws, so this is posture rather than
3373
+ * readiness), or nothing at all. Off-plane the profile is attack
3374
+ * programs / astral will and reads as Armed. White, not gray, for the
3375
+ * same legibility reason as the stance it now sits beside.
3376
+ */
3377
+ armedLine(player) {
3378
+ const weapon = player.getWeaponProfile();
3379
+ const weaponItem = player.getCarriedWeapon();
3380
+ const ammoNote = weaponItem?.isFirearm()
3381
+ ? (weaponItem.jammed
3382
+ ? ` {red-fg}[JAMMED -- reboot]{/red-fg}`
3383
+ : weaponItem.ammo === 0 ? ` {red-fg}[DRY]{/red-fg}` : ` [${weaponItem.ammo} rds]`)
3384
+ : '';
3385
+ if (player.plane === 'meat' && weaponItem && !player.weaponDrawn) {
3386
+ return `{white-fg}Holstered: ${weaponItem.name}${ammoNote}${hint(' -- "brandish"')}{/white-fg}`;
3387
+ }
3388
+ if (weapon.name === 'bare fists')
3389
+ return `{gray-fg}Unarmed{/gray-fg}`;
3390
+ return `Armed: ${weapon.name} (DV ${weapon.damage}${weapon.poolBonus > 0 ? `, +${weapon.poolBonus} dice` : ''})${ammoNote}`;
3391
+ }
3392
+ /**
3393
+ * THE LOG WEARS THE PLANE (player request 2026-08-25). Jacking in or
3394
+ * stepping out of your body changes what every line in that log even
3395
+ * MEANS, and the only marker was a HUD row well below it. The border
3396
+ * takes the plane's own established colour -- cyan for the Matrix,
3397
+ * magenta for astral, yellow for a jumped-in drone, matching the
3398
+ * tints those planes already use throughout the prose.
3399
+ */
3400
+ planeBorderColor(player) {
3401
+ switch (player.plane) {
3402
+ case 'matrix': return 'cyan';
3403
+ case 'astral': return 'magenta';
3404
+ case 'drone': return 'yellow';
3405
+ default: return 'white';
3406
+ }
3407
+ }
3408
+ paintPlaneBorder() {
3409
+ if (!this._logBox)
3410
+ return;
3411
+ const style = this._logBox.style;
3412
+ style.border = { ...(style.border ?? {}), fg: this.planeBorderColor(this.player) };
3413
+ }
3322
3414
  statusLinesFor(player) {
3323
3415
  const lines = [];
3324
3416
  // Line 1: the fight autopilot mode. The stance lives HERE -- the
@@ -3336,7 +3428,13 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3336
3428
  // what two panels already show. The breadcrumb went with it -- the
3337
3429
  // district map draws the way you came far better than a text trail.
3338
3430
  const stanceColor = player.autoStance === 'aggressive' ? 'red' : player.autoStance === 'guarded' ? 'yellow' : 'white';
3339
- lines.push(`{${stanceColor}-fg}⚔ ${player.autoStance.toUpperCase()}{/${stanceColor}-fg}`);
3431
+ // WHAT'S IN YOUR HANDS rides alongside the stance (player ruling
3432
+ // 2026-08-25). The two answer the same question -- how ready are you
3433
+ // -- and the stance line was left short and lonely once the location
3434
+ // moved out to the map captions, while the readiness line below ran
3435
+ // long. armedLine is built further down with the rest of the gear
3436
+ // read; only its placement moved.
3437
+ lines.push(`{${stanceColor}-fg}⚔ ${player.autoStance.toUpperCase()}{/${stanceColor}-fg} ${this.armedLine(player)}`);
3340
3438
  // Line 2: both condition monitors -- in a game where a fight can kill
3341
3439
  // you and casting can knock you out, current damage on either track is
3342
3440
  // never something a player should have to ask for. Colors shift as
@@ -3355,26 +3453,10 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3355
3453
  const heat = this.heatBand();
3356
3454
  if (heat && player === this.player)
3357
3455
  lines.push(heat);
3358
- // Line 3: readiness -- armed state, armor, and whether the commlink is
3359
- // actually live (equipped), the recurring "why can't I call anyone"
3360
- // friction surfaced at a glance.
3361
- const weapon = player.getWeaponProfile();
3362
- const weaponItem = player.getCarriedWeapon();
3363
- const ammoNote = weaponItem?.isFirearm()
3364
- ? (weaponItem.jammed
3365
- ? ` {red-fg}[JAMMED -- reboot]{/red-fg}`
3366
- : weaponItem.ammo === 0 ? ` {red-fg}[DRY]{/red-fg}` : ` [${weaponItem.ammo} rds]`)
3367
- : '';
3368
- // Three armed states on the meat plane: drawn, holstered (weapon
3369
- // carried but riding leather -- "brandish" puts it in hand; combat
3370
- // auto-draws so this is posture, not readiness), or nothing at all.
3371
- // Off-plane the profile is attack programs / astral will and reads as
3372
- // Armed. White, not gray, for the same legibility reason as the stance.
3373
- const armed = player.plane === 'meat' && weaponItem && !player.weaponDrawn
3374
- ? `{white-fg}Holstered: ${weaponItem.name}${ammoNote}${hint(' -- "brandish"')}{/white-fg}`
3375
- : weapon.name === 'bare fists'
3376
- ? `{gray-fg}Unarmed{/gray-fg}`
3377
- : `Armed: ${weapon.name} (DV ${weapon.damage}${weapon.poolBonus > 0 ? `, +${weapon.poolBonus} dice` : ''})${ammoNote}`;
3456
+ // Line 3: the rest of the readiness read -- armor, and whether the
3457
+ // commlink is actually live (equipped), the recurring "why can't I
3458
+ // call anyone" friction surfaced at a glance. The armed state used
3459
+ // to lead this line; it now rides with the stance on line 1.
3378
3460
  const armorNote = `Armor +${player.getArmorValue()}`;
3379
3461
  const hasLink = player.equipment.head?.commlink != null;
3380
3462
  const link = !hasLink
@@ -3384,7 +3466,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3384
3466
  : player.arOffline
3385
3467
  ? `{red-fg}AR CUT -- reboot{/red-fg}`
3386
3468
  : `{${CALL_COLOR}-fg}Link online{/${CALL_COLOR}-fg}`;
3387
- lines.push(`${armed} | ${armorNote} | ${link}`);
3469
+ lines.push(`${armorNote} | ${link}`);
3388
3470
  // Lines 4+: transient states, present only while active. Future
3389
3471
  // contexts (astral projection, VR hot-sim) join here the same way.
3390
3472
  if (player.sustainedArmor > 0) {
@@ -3517,7 +3599,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3517
3599
  const mapLines = renderMapViewport(this.scene.getRooms(), here, (r, d) => this.scene.barrierSealing(r, d), {
3518
3600
  visited: this.player.visitedRooms,
3519
3601
  arEyes: this.player.hasMatrixEyes(),
3520
- }, mapView);
3602
+ }, mapView, tallestRoomRows());
3521
3603
  // The captions the HUD used to carry: where you are under the
3522
3604
  // district, where you stand under the room.
3523
3605
  if (mapLines.length > 0)
@@ -3728,7 +3810,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
3728
3810
  { title: 'social', entries: [['say'], ['emote', 'me'], ['talk-to'], ['call'], ['end-call', 'end', 'hangup'], ['accept'], ['decline', 'deny', 'refuse'], ['haggle', 'negotiate'], ['persuade', 'convince'], ['ask'], ['contacts']] },
3729
3811
  { title: 'street', entries: [['browse', 'buy'], ['sell'], ['catalog'], ['source', 'procure'], ['work', 'gig'], ['jobs'], ['perform'], ['palm'], ['docwagon'], ['treat'], ['eat'], ['drink'], ['lifestyle'], ['pay']] },
3730
3812
  { title: 'barriers', entries: [['solve'], ['pick'], ['breach'], ['dispel', 'dispell'], ['bluff'], ['unlock'], ['lock']] },
3731
- { title: 'character', entries: [['sheet', 'stats'], ['advance'], ['qualities', 'quality'], ['initiate', 'submerge'], ['install', 'chrome']] },
3813
+ { title: 'character', entries: [['sheet', 'stats'], ['advance'], ['qualities', 'quality'], ['sin', 'sins', 'papers'], ['initiate', 'submerge'], ['install', 'chrome']] },
3732
3814
  { title: 'session', entries: [['help'], ['hints'], ['clear'], ['quit', 'exit']] },
3733
3815
  ];
3734
3816
  /** Registered but deliberately UNLISTED: reachable as subcommands or