Sprint 13 gate 1.4: NIGHT 5 RULED — the garden is beyond saving BY DESIGN, and the verdict teaches it

- week.js night 5 carries gardenBeyondSaving: true with the measured case
  (bare 0.0, best buyable 27.7 vs WIN>=50 — B's game-true table, my probe
  agreeing) and the arc argument; nightAt defaults the flag FALSE so new
  nights can never inherit the excuse. Brief levels with the player up front.
- verdictFor honours it on a LOSS only: no more 'the hail fell where your sail
  wasn't' on a night where no placement wins; a 4/4 hold is credited as the
  whole job, a torn sail is still named and owned. A win ignores the flag (a
  stale flag must never eat a real win). Asserted both ways + mutation notes.
- GARDEN_DRAIN untouched, per the standing ruling; icenight hail budget also
  untouched — the loss is the design, so the surfaces now say so.
This commit is contained in:
type-two 2026-07-18 14:11:58 +10:00
parent 1c0fcc757b
commit 80b53e9547
2 changed files with 42 additions and 3 deletions

View File

@ -193,7 +193,7 @@ export function applyMute(sky, on) {
*
* @returns {{verdict: string, mode: string}}
*/
export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }) {
export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped, beyondSaving = false }) {
// SPRINT12 — B's flag, actioned: "weakest link that went first" reduces on
// the EFFECTIVE rating (rating × ratingHint), matching sail.js's failure
// line and B's summary.weakest tie-break fix. On the bare rating a rated
@ -217,6 +217,25 @@ export function verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped }) {
verdict: `THE GARDEN MADE IT. The sail didn't — the ${named} went first and took `
+ `${lost.length - 1} more with it. That is what the sail was for.` };
}
// SPRINT13 gate 1.4 — A's night-5 ruling (week.js gardenBeyondSaving): on a
// night whose data says the garden cannot reach the win line at ANY price,
// every "you could have rigged better" sentence below is a lie, and the
// uncovered/rain modes are the worst liars — they blame placement on a night
// where no placement wins. This branch comes before every loss mode: the
// garden's fate was sealed at the forecast; only the STEEL's fate was the
// player's. Note it deliberately does NOT fire on a win — if a retune ever
// makes the flagged night winnable, the flag is stale and week.js says to
// delete it, not to trust this to paper over it.
if (!win && beyondSaving) {
if (lost.length >= 1) {
return { mode: 'beyond-saving',
verdict: `THE BED WAS BEYOND SAVING — no sail in the shop stops this much ice. `
+ `The ${named} letting go is the part that's on you.` };
}
return { mode: 'beyond-saving',
verdict: 'THE BED WAS BEYOND SAVING — no sail in the shop stops this much ice. '
+ 'Yours held anyway. That was the whole job tonight, and you did it.' };
}
if (!win && lost.length >= 2) {
return { mode: 'cascade',
verdict: `THE SAIL LOST. The ${named} went first — and took ${lost.length - 1} more with it.` };
@ -773,7 +792,8 @@ export async function boot(opts = {}) {
*/
const win = hp >= 50;
const dmg = garden.damage;
const { verdict, mode } = verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped });
const { verdict, mode } = verdictFor({ hp, lost, win, dmg, pondPeak, pondDumped,
beyondSaving: week.job.gardenBeyondSaving });
return {
hp,

View File

@ -81,7 +81,23 @@ export const NIGHTS = [
storm: 'storm_02b_icenight', site: 'backyard_01',
client: 'the Hendersons', addr: '14 Kurrajong St — the backyard',
brief: 'Less wind than last night and more ice, which is worse for the bed and easier on the rig. '
+ 'Last night before they land.',
+ 'Last night before they land. Nobody\'s pretending the seedlings ride this one out — keep '
+ 'the sail on its feet and the ice off the windows.',
// SPRINT13 gate 1.4 — A's ruling, DESIGN CANON: night 5's garden is BEYOND
// SAVING, by design, at any price. Measured game-true (B's pay table and
// A's probe, agreeing): bare bed 0.0 DEAD; best buyable garden 27.7; best
// clean 15.3 — every line in the game sits under WIN's hp >= 50, wallet or
// bank. The week's arc WANTS this: full / full / full, won-but-tattered
// (night 4, the pinned separation), then the night you cannot save — the
// icenight is where the job stops being about the bed and becomes about
// your steel (the line that would hold it needs $105 the shop caps at
// 3.20 kN shackles against 3.22/3.25 peaks — C's few-hundredths whisker,
// kept on purpose). This flag exists so surfaces TEACH the loss instead of
// implying a better rig existed: verdictFor reads it (main.js) and stops
// blaming placement; the brief above levels with the player before they
// spend a dollar. If a retune ever makes night 5 winnable, delete this
// flag in the same commit or the verdict lies in the other direction.
gardenBeyondSaving: true,
},
];
@ -106,6 +122,9 @@ export function nightAt(i) {
addr: base.addr ?? null,
brief: base.brief ?? null,
pay: base.pay ?? {},
// False by default on purpose: a night is presumed savable unless its data
// says otherwise, so a new night can never inherit the icenight's excuse.
gardenBeyondSaving: base.gardenBeyondSaving ?? false,
};
}