@maka/maka-cli 5.42.0 → 5.43.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 (26) hide show
  1. package/bundle/typescript/package.json +1 -1
  2. package/bundle/typescript/src/commands/game/sideQuest/archetypes.js +20 -2
  3. package/bundle/typescript/src/commands/game/sideQuest/archetypes.js.map +1 -1
  4. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js +26 -4
  5. package/bundle/typescript/src/commands/game/sideQuest/commands/docwagon.js.map +1 -1
  6. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js +30 -0
  7. package/bundle/typescript/src/commands/game/sideQuest/commands/install.js.map +1 -1
  8. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js +17 -4
  9. package/bundle/typescript/src/commands/game/sideQuest/commands/inv.js.map +1 -1
  10. package/bundle/typescript/src/commands/game/sideQuest/commands/treat.js +3 -0
  11. package/bundle/typescript/src/commands/game/sideQuest/commands/treat.js.map +1 -1
  12. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js +5 -1
  13. package/bundle/typescript/src/commands/game/sideQuest/factories/scene-seed-generator.js.map +1 -1
  14. package/bundle/typescript/src/commands/game/sideQuest/game.d.ts +1 -5
  15. package/bundle/typescript/src/commands/game/sideQuest/game.js +20 -39
  16. package/bundle/typescript/src/commands/game/sideQuest/game.js.map +1 -1
  17. package/bundle/typescript/src/commands/game/sideQuest/types/save-file.d.ts +1 -1
  18. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.d.ts +41 -0
  19. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js +117 -14
  20. package/bundle/typescript/src/commands/game/sideQuest/utilities/sin.js.map +1 -1
  21. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js +3 -1
  22. package/bundle/typescript/src/commands/game/sideQuest.sub.cmd.js.map +1 -1
  23. package/bundle/typescript/src/tools/ai/ai.class.d.ts +14 -2
  24. package/bundle/typescript/src/tools/ai/ai.class.js +25 -4
  25. package/bundle/typescript/src/tools/ai/ai.class.js.map +1 -1
  26. package/package.json +1 -1
@@ -10,6 +10,7 @@ import { heartbeatPresence, heartbeatPresenceNow } from './utilities/social.js';
10
10
  import { pushSave, burnCloudSaveFor } from './utilities/cloud-saves.js';
11
11
  import { DOCWAGON_TIERS, RESUSC_FEE, DEATH_COMP } from './utilities/docwagon.js';
12
12
  import { isFence, LIFESTYLE_TIERS } from './utilities/commerce.js';
13
+ import { bestFakeSin, wandRead, processArrest } from './utilities/sin.js';
13
14
  import { rollPool, formatRoll } from './utilities/dice.js';
14
15
  import { Direction } from './types/shared/direction-enum.js';
15
16
  import { Logger } from './utilities/logger.js';
@@ -260,6 +261,10 @@ export default class Game {
260
261
  // Rooms already swept this run (utilities/sin.ts maybeSinSweep) --
261
262
  // a patrol works a floor once, not every time you pace it.
262
263
  sweptRooms = new Set();
264
+ // Counters that watched a fake SIN burn (utilities/sin.ts
265
+ // venueSinCheck) -- they refuse that face for the rest of the
266
+ // session. Session-only, never saved (same model as sweptRooms).
267
+ venueBans = new Set();
263
268
  /** The district is already on alert -- sweeps come more often. */
264
269
  get runHeatIsHot() {
265
270
  return this._runHeat >= Game.CHECKPOINT_HEAT;
@@ -2188,6 +2193,12 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2188
2193
  if (!this._useAi) {
2189
2194
  return { allowed: false, message: `Continuing needs an AI-generated job, which requires an AI provider to be configured (OPENAI_API_KEY or ANTHROPIC_API_KEY) -- or a maka-cli.com login with server AI access (\`maka login\`).` };
2190
2195
  }
2196
+ // INTERACTIONS-tier relay (ruling 2026-08-24): NPCs talk, but solo
2197
+ // generation isn't funded -- unless a crew is seated, in which case
2198
+ // the SERVER writes the job with its own key.
2199
+ if (!AI.canGenerate() && this.livePartyFingerprint() === '') {
2200
+ return { allowed: false, message: `Solo jobs need an AI key of your own -- but seat a crew ("crew") and the street's own brain writes the job.` };
2201
+ }
2191
2202
  return { allowed: true };
2192
2203
  }
2193
2204
  /**
@@ -2436,23 +2447,16 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2436
2447
  return lines.join('\n');
2437
2448
  }
2438
2449
  const verifierDice = heat >= 12 ? 8 : 6;
2439
- const fakes = p.inventory.getAllItems()
2440
- .map(i => ({ item: i, m: /^Fake SIN \(Rating (\d)\)$/.exec(i.name) }))
2441
- .filter(x => x.m !== null)
2442
- .map(x => ({ item: x.item, rating: parseInt(x.m[1], 10) }))
2443
- .sort((a, b) => b.rating - a.rating);
2444
- if (fakes.length > 0) {
2445
- // Canon three-band check (p.364, RAG-verified): under the rating
2446
- // = no problem; reached but not exceeded = "something seems odd";
2447
- // exceeded = busted.
2448
- const fake = fakes[0];
2449
- const scan = rollPool(verifierDice);
2450
- Logger.getInstance().meta(`SIN verification (KE scanner, ${verifierDice}d6): ${formatRoll(scan)} (under ${fake.rating} clean, ${fake.rating} odd, over busts)`);
2451
- if (scan.hits < fake.rating) {
2450
+ const fake = bestFakeSin(p);
2451
+ if (fake) {
2452
+ // Canon three-band check (p.364) via the shared wandRead --
2453
+ // checkpoint, sweeps, and venue counters roll the same machine.
2454
+ const band = wandRead(fake.rating, verifierDice, l => Logger.getInstance().meta(l), `SIN verification (KE scanner, ${verifierDice}d6)`);
2455
+ if (band === 'clean') {
2452
2456
  lines.push(`You hand over the Rating ${fake.rating} fake and hold a bored face. The wand chews on it... green light. "Move along."`);
2453
2457
  return lines.join('\n');
2454
2458
  }
2455
- if (scan.hits === fake.rating) {
2459
+ if (band === 'odd') {
2456
2460
  const oddFee = Math.min(p.currency, 200 + heat * 50);
2457
2461
  if (oddFee > 0)
2458
2462
  p.adjustCurrency(-oddFee);
@@ -2461,7 +2465,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2461
2465
  }
2462
2466
  p.inventory.removeItem(fake.item.name);
2463
2467
  lines.push(`You hand over the Rating ${fake.rating} fake. The wand chews... and SPITS. "This SIN is flagged as of now." The fake is BURNED -- worthless in every database at once.`);
2464
- lines.push(this.processArrest(heat));
2468
+ lines.push(processArrest(p, heat));
2465
2469
  return lines.join('\n');
2466
2470
  }
2467
2471
  const con = p.skillRating('con');
@@ -2473,30 +2477,7 @@ ${client.name} won't be remembering anything. Dead Johnsons pay nothing -- and t
2473
2477
  return lines.join('\n');
2474
2478
  }
2475
2479
  lines.push(`No SIN, and no story that holds. Zip ties.`);
2476
- lines.push(this.processArrest(heat));
2477
- return lines.join('\n');
2478
- }
2479
- /** Processing: prints, retinas, a fee -- and for the SINless, the
2480
- * street's cruelest joke: they ISSUE you a SIN. A criminal one.
2481
- * Catch-and-release always (arrest never ends a career by fiat --
2482
- * the record it leaves does the long-term damage). */
2483
- processArrest(heat) {
2484
- const p = this.player;
2485
- const lines = [];
2486
- const fine = Math.min(p.currency, 1000 + heat * 100);
2487
- if (fine > 0)
2488
- p.adjustCurrency(-fine);
2489
- lines.push(`Processing: prints, retinas, a genome swab, every camera in the room.${fine > 0 ? ` The "administrative fee" is ${fine} nuyen.` : ` Your sticks come up empty; the fee rides your new file.`}`);
2490
- if (!p.qualities.has('sinner-criminal') && !p.qualities.has('sinner-national') && !p.qualities.has('sinner-corp')) {
2491
- p.addQuality('sinner-criminal');
2492
- lines.push(`{red-fg}And the worst of it: they ISSUE you a SIN. A CRIMINAL SIN -- broadcast always, 15% of every payout withheld, forever in the system. Get caught being nobody, become somebody with a record.{/red-fg}`);
2493
- }
2494
- else {
2495
- lines.push(`The record deepens. (Notoriety.)`);
2496
- }
2497
- p.addNotoriety('arrested on the ride home');
2498
- lines.push(`They cut you loose before dawn -- catch-and-release. Holding a runner costs more than the paperwork is worth.`);
2499
- Logger.getInstance().write(`Checkpoint arrest: fine ${fine}, heat ${heat}, criminal SIN ${p.qualities.has('sinner-criminal')}.`);
2480
+ lines.push(processArrest(p, heat));
2500
2481
  return lines.join('\n');
2501
2482
  }
2502
2483
  /**