Alpha Release Notes

Angel Snack Patch Notes

Current game version: 0.1.0-alpha.15. 16 published releases, latest 0.1.0-alpha.15.

Back to game

Angel Snack 0.1.0-alpha.15 Patch Notes

Release date: 2026-07-19

Stage: alpha

Package version: 0.1.0-alpha.15

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Quest sites now cache a rune for your runeword project instead of forging the whole thing, and vendors stock a rune from your recipe rather than exactly the one you need next. The hunt is back.: Quest sites no longer hand over a fully forged runeword — they cache a single rune drawn from your project's recipe, which might even be one you already used. Town vendors likewise stock a rune from your recipe rather than exactly the one you need next. Between drops, caches, and vendor stock the funnel still points at your runeword, but finishing it is a hunt you can lose, not a delivery.

UI

  • Hall tabs now use the standard button styling: The tabs on the hall / front-door screens (section, archive, character, and unlock tabs) now use the game's standard button styling and selected-state highlight, matching the tabs used elsewhere (gear, inventory, arena). Behavior is unchanged — this is a visual consistency pass; the selected tab now shares the common ember highlight instead of a one-off style.
  • Buying from a town service (healer, blacksmith, mercenary, corven vale) now patches the open overlay instead of rebuilding the whole screen, and the overlay keeps your scroll position after a purchase.: Buying, selling, or otherwise using a town service — the healer, blacksmith, mercenary captain, or Corven Vale — no longer rebuilds the whole town screen for each purchase. The open service window updates in place, and if you had scrolled down a long list (e.g. vendor stock or the forge workboard), that scroll position is preserved instead of snapping back to the top after every click.
  • Town purchases now show a success toast: Buying from a vendor, selling or consigning gear, and using healer or quartermaster services in town now shows a brief confirmation toast (e.g. "Purchased", "Sold", "Restored", "Refilled") in the corner of the screen, so a successful purchase or service always gives clear feedback — even when the item card or overlay updates immediately after the click.

Fixes

  • Combat card previews show accurate damage/guard numbers: The damage and guard numbers on a card's preview chip now always match what the card will actually do. Previously the preview could disagree with the real play in a few cases: cards whose effect is gated by a condition (e.g. a form- or confluence-locked guard bonus) showed the full value even when the gate wasn't met, targeting a non-first enemy could show the wrong (or zero) damage, and forced-overpay cards understated their scaled damage. The card face now derives these numbers from the same engine the actual play uses, so the preview can no longer lie.
  • Card previews show accurate numbers for counter-scaling and AoE cards: The damage/Guard preview chip on hand cards now reads correctly for every card, derived directly from what the play would actually resolve rather than a fixed list of effect types. This fixes cards that previously showed "Resolve" or omitted their Guard/line numbers (counter-scaling, mark-payoff, AoE-counter-spend, and polymorphic effects like Chaos Surge), cards that mix a single-target hit with an area effect no longer double-count the selected enemy's damage into the area total, secondary damage from an active system (such as Barbarian War Howl's aura splash) now shows up in the line total, and Guard grants now attribute to self vs. party based on who actually received Guard rather than which card effect granted it. An area-of-effect card no longer wrongly splits out a "single target" number just because an enemy happens to be selected on screen, and Guard a mercenary gains entirely on its own is no longer mislabeled as shared "party" Guard.
  • Fix overlapping pill/title on charm rewards and tutorial popups: On the charm reward screen, the yellow "N pouch slots" pill no longer overlaps the charm name, and the tutorial popup's × close button no longer overlaps its step counter. Both now reserve space so the text stays readable.
  • Combat potion/End-Turn rejects now announce a spoken reason, hand-card labels speak the resolved outcome, paper-doll equipment slots are keyboard-operable, and run-summary filter changes preserve focus.: Screen-reader and keyboard-only players get four fixes: combat potion and End Turn rejections (and the End Turn "queued behind your remaining plays" defer) now announce a spoken reason instead of only flashing the button; a hand card's spoken label now states the resolved outcome (matching the number on screen) instead of the card's unresolved base text; inventory paper-doll equipment slots can now be activated with Enter or Space, not just a mouse click; and changing a run-summary filter pill no longer drops keyboard focus back to the top of the page.

Tech

  • Probe-gated T5-6 affixed-enemy pack cap softening (default-OFF) for the ROG-1230 necromancer T6-floor A/B: No player-facing change yet. This is a default-OFF ascension balance probe (softens the T5-6 affixed-enemy pack cap 2->1 when armed) added so simulations can A/B-measure the necromancer T6-floor fix before it is considered for normal play.
  • Necromancer balance: landed the Summoner's Ward summon-guard lever behind a default-OFF A/B probe (__necro_summoners_ward_v1__). Inert until validated + promoted; no player-facing change yet.: No player-facing change yet. This is a default-OFF balance probe for a Necromancer summon-guard passive, added so simulations can measure the lever before it is considered for a normal run.

Operations

  • Release follow-up hardening: complete patch-note copy, isolate GnuPG state, and remediate the production audit advisory: No gameplay change. Published alpha.14 patch notes now contain finished copy, encrypted backup state is kept outside the deploy checkout, and the production dependency graph overrides the vulnerable js-yaml release to the fixed version. The release-note package stays in production dependencies because the live feedback route imports it.
  • Deployment and release safeguards now fail closed before maintenance: Deployments now stay pinned to the build that passed local validation, prove the pruned production server can start before maintenance, and reject release or backup state that violates publishing and checkout-safety rules.
  • Production deploys now build and smoke-test in an isolated candidate checkout before atomically promoting the release during maintenance: Deploy preparation no longer rewrites files used by the running game. A candidate release is built and smoke-tested in isolation, then its static bundle is switched with an atomic pointer during maintenance; failures restore the exact prior release.

Angel Snack 0.1.0-alpha.14 Patch Notes

Release date: 2026-07-18

Stage: alpha

Package version: 0.1.0-alpha.14

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Act 4's roster gains ranged threats — the ash no longer only charges at you (ROG-1215): Act 4's rank-and-file learned some discipline. Black Lancers, the Damned, and Urdar no longer just charge the Wanderer every turn — they now fight like skirmishers, falling back behind Guard and sniping whoever on your side is closest to death. Their stats are untouched (same life, same damage), but the pressure feels different: instead of trading blows at the front, you'll need to shield a wounded mercenary or a low-life hero from picked shots while cracking their guard. Watch the intent telegraphs — the target markers tell you who's in the crosshairs.
  • Assassin Shadow counter glow now marks the real breakpoints (5/10/15/18 — spender range, burst range, Death Sentence, Overdraw) instead of 10/20.: The Assassin's Shadow counter now highlights the thresholds that matter in play: spender range at 5, burst range at 10, Death Sentence at 15, and Overdraw at 18. The glow is a better prompt for when to cash in or keep building.
  • Axes are now a real weapon family: 5 axes drop across acts 1-5, Barbarian favors them, and the Steel and Pattern runewords roll on axe bases.: Axes can now appear throughout acts 1–5 as a real weapon family, with Barbarian builds favoring them and Steel and Pattern accepting axe bases. They add another meaningful gear path instead of being decorative loot.
  • Skipping a card reward now banks Spoils — each stack adds an extra choice at your next boss reward (ROG-1209/1214): Skipping a card reward is no longer just a refusal: it banks a Spoils stack that adds an extra option to your next boss reward. That makes restraint a real deckbuilding decision rather than a dead end.
  • Mastery Hall is now a real choice — earn points, pick your path, chase capstones (ROG-1211): Mastery Hall gives long-term progress a clearer shape: earn points, choose a path through its tiers, and work toward capstones. Your account progression now offers distinct strategic commitments instead of a flat unlock list.
  • Paladin: Defiance now costs 2 (was 1); Holy Freeze now applies 2 Slow (was 1 Freeze) — it chills the pack instead of freezing it solid.: Paladin's Combat Zeal lane traded a bit less pack-clear immunity for the same core plan: Defiance still taunts, guards, and generates Faith, but now costs 2 Energy instead of 1, so it no longer slots into a full-cantrip turn for free. Holy Freeze still hits for 14 cold AoE and draws a card, but its status effect changed from 1 Freeze (fully skips the enemy's turn) to 2 Slow (delays but doesn't cancel it) — packs will still act against you, just a beat slower.
  • Paladin: Holy Freeze now deals 14 (was 20) and applies 1 Freeze (was 2); Defiance grants 10 party Guard (was 14) and deals 4 (was 6). Their + versions scale accordingly.: Paladin's strongest pack-control tools are less overwhelming: Holy Freeze deals less damage and applies one Freeze, while Defiance grants less party Guard and deals less damage. The tools remain powerful, but enemy packs have more room to answer them.
  • Six new runewords give every class a play-pattern lane: Fury (barbarian), Harmony (amazon), Beast (druid), Venom (assassin), Destruction (sorceress), Famine (warlock). Pyrostaff now rewards spell cadence instead of hoarded energy.: Six new socketable runewords each build toward a class's core card cadence — Fury rewards the barbarian's every-other Attack, Harmony and Venom pay off the amazon's and assassin's third Attack, Beast reinforces the druid's first summon each turn, and Destruction and Famine detonate on the sorceress's and warlock's third Spell. Pyrostaff also switches its finisher from "unspent Energy at turn end" to "your third Spell each turn," so it now rewards active spellcasting instead of holding Energy back.
  • Runeword hunting is a real gamble again: rune drops are biased less heavily toward your target, and bosses only guarantee a rune from act 3 onward while you have an active runeword project.: Rune drops still lean toward the runeword you are hunting, but far less heavily, and the free rune every boss and miniboss used to hand over is gone — only act 3+ bosses still pity-drop one, and only while you have an unfinished runeword project. Completing a runeword should now feel like winning a directed gamble rather than collecting a delivery.
  • Paying life for power now has its own sound, and overlapping combat sounds resolve by priority (ROG-1195): Life-for-power effects now have their own audible cue, making a costly play easier to recognize in a busy turn. Combat sounds also resolve by priority so the most important feedback is less likely to be buried by overlap.
  • Sixteen signature skills gain hand-crafted rank-5 upgrades that change how they play (ROG-1219).: Investing 5 skill ranks into one of sixteen class-signature skills (two per class — your starter identity cards and their closest partner) now upgrades that card into a hand-crafted rank-5 version with a real rule change, not just a bigger number: Barbarian's Bash spends banked Rage for bonus damage, Necromancer's Raise Skeleton reforms your last fallen minion, and so on across every class. This was fleet-tested and comes back stronger overall with no downside to how winnable runs are, so it's on by default.
  • Town arrivals now rotate through fresh narration each run (ROG-1196): Arriving in town now rotates through fresh narration instead of repeating one welcome every run. The safer moments between fights should feel less mechanical without getting in the way of play.
  • Four new large charms offer real trade-offs — power now, paid for in blood or ceiling (ROG-1208): Four new large charms offer stronger immediate effects with a real cost, asking you to trade life or capacity for power. They create more interesting loadout decisions than pure upgrades.
  • 48 skills reconnect to their tree ranks — investing points now empowers every card it should (ROG-1217): Investing in 48 skills now improves the cards those tree ranks promise to support. Skill points more reliably translate into visible build growth instead of silently missing part of their intended payoff.
  • Warlock's trees gain evolution paths and planning depth to match the roster (ROG-1216): Warlock's three trees now have fuller evolution paths and clearer decisions that match the rest of the roster. Building around a Warlock specialization should feel more deliberate from early picks through capstones.
  • Zone environments shape exploration flavor again — moors, tombs, jungles and hellscapes each read differently (ROG-1198): Exploration event flavor text now varies by where you actually are — a forge, shrine, or trader you meet in the moors of Act 1 reads differently than the same encounter deep in an Act 4 hellscape or an Act 5 ice cavern. This had quietly stopped working for nearly every zone after an earlier zone-title revert; it's fixed now, and rename-proof going forward.

Balance

  • Stealth runeword power reduced: The Stealth runeword's power has been reduced — less bonus max life, and it no longer buffs your max energy. Fleet A/B testing confirmed the trim is win-rate safe (95% vs 97.5% untrimmed) while raising resource pressure, so it now reads as an accessible enabler rather than an easy power spike. With this change, both Stealth and Steel have had their enabler-trim numbers baked in permanently, and the __runeword_enabler_trim__ sim A/B lever used to tune them has been retired.

Content

  • The world fully speaks its own names now — every boss, zone, and lore entry uses Blood Rogue canon: Blood Rogue now uses one consistent vocabulary across the game: enemy names, zones, story, and lore all refer to the same world. This removes leftover imported names that made the setting feel stitched together and makes discoveries easier to recognize wherever they appear.
  • Every recurring story beat now varies across runs, and your class has its own voice (ROG-1210): Recurring story moments now rotate instead of repeating the same line every run, and many gain a class-flavored variation. Town arrivals, transitions, and other familiar beats should feel more like part of the current character's journey.

UI

  • Enemy intent chips use the styled tooltip (hover, keyboard focus, and touch) instead of the native browser title, and intent threat colors are keyed to the intent kind.: Enemy intent chips now explain themselves through the game's tooltip system on hover, keyboard focus, and touch, rather than a browser-native title. Their threat colors also reflect the actual intent kind, making the next move easier to read quickly.
  • Buttons show a distinct focus ring for keyboard users, separate from hover.: Keyboard focus has a distinct visible ring, separate from hover styling. It is easier to see where the next keypress will land without changing how pointer users read buttons.

Fixes

  • Made Autopilot interruption reliable and simplified Battle Arena setup on phones.: Pause and Stop now cancel queued Autopilot work before it can take another combat, route, reward, or town action, and Stop remains authoritative if the HUD redraws. Battle Arena setup is also more compact and readable on phones, with one progress model and the first real choice visible sooner.
  • Ascension ladder tier picks and hero-rail preview clicks no longer rebuild the whole screen — the ladder keeps its scroll position and keyboard focus, and the rail no longer flashes/re-decodes portraits.: Tapping a rung in the Rifts (ascension) ladder, or clicking through hero portraits on the bloodline-select rail, used to rebuild the entire character-select screen on every click. That reset the ladder's own scroll position (later tiers scrolled back out of view right after being tapped) and dropped keyboard focus out of both controls. Both now update only the piece of the screen that changed, so the ladder stays scrolled where you left it, the hero rail keeps its scroll position, and focus stays on the control you just used.
  • An invalid gear drag now shows why it was rejected (wrong slot, pack full, etc.) instead of only shaking.: When a drag-and-drop gear action cannot happen, the game now says why—such as an incompatible slot or a full pack—instead of only shaking the item. That turns a confusing failed gesture into a clear next step.
  • The vault and pack Discard button now requires a confirm click (Really discard?) before permanently destroying an item, and is styled as destructive.: Discarding an item from the vault or field pack used to destroy it permanently on a single click, styled identically to safe moves like Withdraw to Pack or To Stash. Discard is now visually marked as destructive and requires a second "Really discard?" confirm click (with a Cancel option) before the item is actually gone — protecting the between-runs vault from the costliest possible misclick.
  • Hovering an item in the pack or on the paper doll shows its stat tooltip again — the preview was built but never wired to appear.: Item tooltips are reachable again from both pack and equipped slots, so you can inspect stats without opening another surface. The existing preview data now appears where players expect it.
  • Merchant portraits no longer show the fallback sigil bleeding behind a loaded portrait (a CSP-blocked inline handler is now a CSP-safe load listener).: Loaded merchant portraits now stand on their own instead of showing a fallback sigil behind them. The image fallback uses a CSP-safe listener, so stricter browser security no longer leaves the visual artifact behind.
  • Scroll-map toggle, act-transition scroll overlay, and loadout-candidate switches now patch in place instead of forcing a full app-shell re-render, preserving scroll/focus.: Changing the scroll map, act-transition scroll, or loadout candidate source now updates only the affected surface. Your scroll position and keyboard focus stay put instead of the entire app visibly rebuilding.
  • Run-end summary charts (floor gauges, sparklines, power/trend lines) render again — a stray tag rename had left them blank.: Run-end floor gauges, sparklines, and power/trend charts render again, so the summary once more explains how the run developed instead of leaving its analysis area blank.
  • Vendor Buy tab now splits equipment vs rune stock by item data, so no purchasable item can silently vanish when preview copy changes.: Vendor stock now separates equipment from runes using the item data itself, so a purchasable item cannot disappear just because its preview copy changes. Shopping inventory stays complete and predictably categorized.

Operations

  • Bump db-backup and release-kit for the pkg-18 shared-package convergence: No player-facing change. Updates the shared @andrewpopov/db-backup (v0.17.1 -> v0.18.0) and @andrewpopov/release-kit (v0.1.0 -> v0.1.3) dependencies to their latest additive releases as part of the cross-repo package convergence.
  • Add the Summit Wardens' "Sigil of the Ancients" relic behind a default-off probe (not yet obtainable): Internal/measurement only. Adds a Wardens-exclusive grand charm — "Sigil of the Ancients" (combat start: +12 Guard; every 4th turn: recover 10 Life and deal 8 magic damage to all enemies) — as a guaranteed drop from the Summit Wardens, gated behind the wardenRelicEnabled probe (default OFF) and the warden-relic sim arm. The charm is poolExcluded, so it never enters the random reward pool for any class and cannot be obtained in normal play until the probe is promoted. This lands the ROG-1182 lever-#1 instrument so the fleet can measure whether a commensurate visible reward makes the (optional, brutal) Wardens worth taking. No change to shipped gameplay.
  • Sim-pilot routing fix — the pilot no longer force-feeds itself optional superbosses. No player-facing change.: The sim pilot was a completionist: it cleared every reachable non-boss zone before the act boss was even a candidate, so it walked into the optional Summit Wardens every single run and died there. That one encounter caused roughly 70% of all run losses and contaminated every winnability number in the corpus — most of what looked like class imbalance was this routing artifact. The optional-miniboss readiness floor now defaults to 1.25 (was 0 = off), calibrated on 8 classes × 150 CRN-paired seeds: barbarian 68.7% → 96.7%, necromancer 58.0% → 86.7%, and nothing regresses. Both neighbouring values are worse — 0.9 still lets barbarian walk into the Wardens, and 1.5 over-skips and costs necromancer 7.4pp of forfeited miniboss rewards. Internal only: this changes how the *simulator* routes, not the game. It does fork the comparabilityKey, so winnability numbers measured before this commit are not comparable to ones measured after it — the corpus needs re-baselining.
  • Sim wall detector: every winnability read now reports per-encounter loss share; no player-facing change.: Internal balance-tooling only; no gameplay, RNG, or persistence change. Every LOCAL seed-winnability read now reports which encounter each run died in, and raises a WALL warning when a single encounter accounts for more than 40% of a class's trusted losses (gated on the Wilson lower bound, so tiny samples cannot trip it) — scripts/run-loss-site-report.js runs the same detector over any existing Postgres slice. (Fleet-sharded corpora needed a follow-up, ROG-1188, to get the same warning — see that patch note.) This closes the blind spot behind ROG-1186: the sim pilot force-took the OPTIONAL Summit Wardens every run and died there — 57 of 91 roster losses (63%) — which silently depressed every winnability number we balanced against. Also reworded a comment in sim-encounter-runner.ts that false-positived the engine-mirror ratchet and had been failing npm test on master.
  • Sim wall detector now fires on the fleet path too; fleetctl status/pooled report are the new default way to read fleet results.: Internal balance-tooling only; no gameplay, RNG, or persistence change. The ROG-1187 wall detector (warns when one encounter causes more than 40% of a class's trusted losses) was structurally inert on the fleet path: fleet experiments shard at 2 seeds/shard, each shard runs in its own process/accumulator, and the detector needs at least 3 concentrated losses to clear its Wilson gate — a 2-seed shard can produce at most 2. fleetctl-pg.js status --experiment <id> (the command every agent/doc already runs to watch a fleet experiment) and run-seed-winnability-pooled-report.js --experiment <id>/--seed-salt <salt> now run the same detector scoped to one fleet corpus and print it next to the per-class win rates it would invalidate. Both prefer the fleet_experiment_id provenance column stamped by the fleet ingest (server-side, authoritative); pre-migration or --crn-salt-collided corpora fall back to a seed_salt join and say so explicitly rather than silently guessing. docs/fleet/FLEET-GUIDE.md and the balance-master skill now point at these commands as the default way to read fleet results — a raw psql read has no channel to print a warning at all, so it stays an escape hatch for ad-hoc exploration, not the documented read path.
  • Consolidate the three hardcoded named-boss drops into one data-driven loot-table system (no player-facing change): Internal/refactor only. Replaces three parallel hardcoded drop hacks — Countess -> rune, Nihlathak -> Anya's Scarf, and the Summit Wardens -> Sigil of the Ancients (the ROG-1182 probe) — with a single data-driven LOOT_TABLES keyed on a bossId now stamped on miniboss enemy templates (never string-parsed, so it can't rot on a zone/display rename like ROG-1204 did). Adding a boss's exclusive loot is now a table row. Countess and Nihlathak drops are byte-identical to before; the Sigil stays behind its default-off wardenRelicEnabled probe (it now arrives as a main reward choice rather than a follow-up-cache choice — invisible until the probe is promoted). Fail-loud validation rejects a typo'd loot key at catalog load. No change to shipped gameplay.
  • Internal sim margin/dominance telemetry (hero/merc life-floor, potions, turns); no player-facing change.: Adds per-seed margin telemetry to the winnability sim — hero-life floor, mercenary-life floor, potions used, and turns — surfaced through the sim report and the fleet history row. Purely observational (it only reads combat life values via a shared sampler after every turn-advance path; no gameplay, RNG, or persistence change), so it lets the fleet measure how dominant a build is when winnability WR is ceiling-blind (both arms ~99%) — e.g. the ROG-779 stealth over-power question and future over-mitigation A/Bs.
  • Sim Lab runs list distinguishes concurrent fleet experiments: Dev tooling: the Sim Lab runs list now keys each row on its fleet experiment scope, so two concurrent experiments on the same commit appear as separate rows with their own labels and detail views instead of pooling into one. Balance reads (CRN pair reports, pooled winnability, sim-tools) are experiment-scoped the same way. No player-facing gameplay change.
  • Fleet submit rejects capability-mismatched runner flags loudly: Fleet infra: the sim-fleet flag-emission contract is now capability-honest — the daemon never emits a flag a runner can't parse, and a submitter-intent flag set for a runner that doesn't support it (arms/specs/through-act/throughput-mode/arm-filter/main-realm/decision-sweep) is rejected loudly at submit (both CLI and the HTTP API) and, as a backstop against direct-queue insertion, terminated cleanly at the worker instead of silently dropped. No player-facing change.

Angel Snack 0.1.0-alpha.13 Patch Notes

Release date: 2026-07-13

Stage: alpha

Package version: 0.1.0-alpha.13

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Fixes

  • Keep End Turn visible on portrait combat without covering battlefield controls.: Portrait combat keeps the turn-ending control reachable while preserving access to the battlefield.
  • Keep rotated phones in a readable responsive layout instead of shrinking controls below the usable size floor.: Rotated-phone layouts preserve readable controls instead of compressing them below a usable size.
  • Keep the sign-in action visible when guest play is closed.: When guest play is unavailable, the front door now keeps the sign-in action beside the explanation instead of leaving it below the cover.
  • Give Sim Lab jobs collision-resistant IDs and bound captured JSON output.: Sim Lab safely retains useful job results without allowing oversized output to consume unbounded memory.
  • Keep timeout and underplay exclusions mutually exclusive across simulator result views.: Sim Lab run summaries now use consistent exclusion counts across list and detail views.
  • Reject forged or stale Sim Lab balance-profile selections before launch.: Sim Lab validates the currently available balance profile before creating a job.

Tech

  • Sim-only oracle answers whether a run that died in an optional side zone would have finished the game had the pilot skipped it — default-off, no change to shipped routing.: The oracle reruns an identical seed with its fatal optional side zone banned, making routing artifacts measurable without changing normal simulation behavior.
  • Hardened the ascension affix-scaling implementation for release validation.: Improved the reliability of the optional high-tier ascension balance probe without changing its default behavior.

Balance

  • Steel runeword power reduced: The Steel runeword's power has been reduced — less bonus damage, and it no longer buffs your mercenary's attack. It's still a solid early-game option, but reads as an accessible enabler rather than an easy power spike.

Angel Snack 0.1.0-alpha.12 Patch Notes

Release date: 2026-07-12

Stage: alpha

Package version: 0.1.0-alpha.12

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Fixes

  • Keep launcher position restoration compatible with lightweight shell roots.: The saved bug-report button position now restores only when the active shell exposes a real queryable DOM root, avoiding noisy failures in lightweight render surfaces.

Angel Snack 0.1.0-alpha.11 Patch Notes

Release date: 2026-07-12

Stage: alpha

Package version: 0.1.0-alpha.11

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Operations

  • Keep deploy lint scoped to the checkout being deployed.: Production validation now lints only the checkout being deployed, so unrelated sibling worktrees cannot block or contaminate a release.

Angel Snack 0.1.0-alpha.10 Patch Notes

Release date: 2026-07-12

Stage: alpha

Package version: 0.1.0-alpha.10

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Balance

  • Barbarian's sim pilot no longer skips its own Blood Rite life-to-Rage engine — a scorer mispricing fix is now the shipped default: Barbarian's Blood Rite ("Lose 4 life, gain 4 Rage") was being priced by the sim pilot's static card-sorting heuristic as plain self-damage instead of the life-to-Rage conversion it actually is, which could make the pilot skip or under-value its own signature engine. The corrected weight — previously an opt-in A/B lever — is now barbarian's unconditional default. A fleet A/B on the correction showed win rate holding steady (non-inferior) with no shift in barbarian's skill-progression ladder. No other class is affected.

Tech

  • Keep movable bug-report launcher behavior within the UI module-size safety limit.: The movable bug-report button retains its saved-position behavior while its drag handling now lives in a focused, independently bounded UI module.

Angel Snack 0.1.0-alpha.9 Patch Notes

Release date: 2026-07-12

Stage: alpha

Package version: 0.1.0-alpha.9

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Fixes

  • Restore the movable bug-report launcher position without dynamic HTML interpolation.: Saved bug-report button positions continue to restore correctly while keeping the launcher markup safe and compatible with the production security gate.

Operations

  • Internal-only sim lever to A/B a steel/stealth runeword stat trim; no player-facing change.: Adds a default-off __runeword_enabler_trim__ sim probe that, when armed on the fleet, resolves the steel and stealth runewords with reduced enabler-band stat bonuses (steel dmg 6→3 / drop merc-attack; stealth life 8→5, guard 3→2 / drop max-energy) through the shared runeword-bonus resolver — so both combat and the pilot's item valuation see the trimmed stats. Byte-identical when the probe is off (the real-player default), so there is no gameplay change; it exists solely to fleet-A/B the ROG-779 easy-and-strong runeword trim before deciding whether to bake it in.

Angel Snack 0.1.0-alpha.8 Patch Notes

Release date: 2026-07-12

Stage: alpha

Package version: 0.1.0-alpha.8

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • The Daily Challenge is now playable from the front door — one seed, one attempt, everybody on the same board.: A new 🏆 Daily Challenge button on the title screen opens the ranked lobby. Every player of a class runs the exact same seed for the period, so the board is a real comparison rather than a race for a lucky roll. Pick your class, switch between the Daily and Weekly boards, and see the current top runs before you commit. You get one attempt per board, per period, and starting the run consumes it — so the lobby says so plainly before you begin, and shows you how long is left until the board resets. If you have already run today's board, the lobby tells you where you landed instead of offering a second attempt. A run still in progress can be resumed from here. Abandoning a ranked run now warns you that it forfeits that attempt, rather than quietly throwing it away behind the usual "abandon your run" prompt.
  • Ranked runs now show a RANKED badge in combat and a scored result panel when the run ends.: While a ranked run is in progress the combat header carries a RANKED · Daily (or Weekly) marker, so it's always clear which board you're spending your attempt on. When the run ends — win or lose — a Ranked Result panel shows your score straight away. The score is final the moment the run is over; it's worked out from how far you got, and nothing about it is up for revision. What takes a moment is your *place* on the board: the server re-runs your game to confirm it. Until that finishes the panel shows where you're projected to land ("Projected #7 of 23") and quietly firms up to a verified rank while you watch. If confirmation is taking unusually long, the panel tells you your run is safe and to check the board later rather than spinning forever. Fall in Act 3 and your score still posts. Finish first on an empty board and it says so.
  • The in-run "Abandon Run" menu option now actually works (and warns before forfeiting a ranked attempt).: Choosing "Abandon Run" from the in-game menu used to do nothing — it set a flag that only the title screen knew how to draw, so mid-run the click just silently failed. It now shows a proper confirm right there in the menu, with Keep Run / Abandon Run buttons. For a ranked run it spells out the consequence first: abandoning forfeits your one attempt on that board until it resets.
  • The Daily Challenge no longer quietly throws away another run, and it confirms your rank against the right board.: Beginning a Daily or Weekly Challenge used to overwrite whatever run you had going, without asking. If that run was another ranked attempt, it was gone for good — you only get one per board. Now the game asks first, and says plainly what you'd lose. "Resume your ranked run" now only appears for the run you're actually looking at. Before, an Amazon Daily lobby would happily offer to resume a Warlock Weekly attempt — or an ordinary expedition — and clicking it took you somewhere you didn't mean to go. And when a challenge board rolls over while you're finishing a run, your result is now checked against the board you actually played, instead of the new one that just opened.
  • View Board" from a finished ranked run now opens the board you actually played, even after it resets.: If a ranked board rolled over (a new day or week started) between finishing your run and tapping "View Board" on the results screen, it used to open the fresh, empty board where your run doesn't appear. It now opens the board you actually competed on, with your run on it. As soon as you switch class or cadence on that screen, it goes back to showing the current board.
  • Starting a Daily Challenge and then quickly switching to another run can no longer abandon the wrong one.: There was a narrow timing window where starting a ranked run, then immediately leaving and resuming a different run before the server responded, could abandon the run you'd just gone back to and drop you into the ranked one instead. Now, if you've navigated away by the time the ranked run is ready to start, it simply doesn't — your current run is left exactly as it was.
  • Buffed two lagging act-5 builds — Amazon's Valkyrie/Passive summoner and the Assassin's Shadow discipline.: Two under-performing late-game builds get targeted help: Amazon "Valkyrie Vigil" (Passive): the Valkyrie's base strike power is raised (4 → 11), and while Passive Mastery is active your Amazon summons now pierce a little enemy Guard — so the summon-tank plan can actually close out act-5 fights instead of chipping against the Guard wall. Assassin Shadow — Shadow Crisis Guard: once you've played Shade Cloak, dropping to critically low life (or taking a hit that would) caps that incoming hit at 65% of its raw value. Shadow's glass-cannon frame no longer gets deleted outright by the act-5 Summit Wardens' simultaneous burst — it now has a fighting chance in the fights that used to be unwinnable, without softening its normal play.

Balance

  • Druid Shifter Bruiser's Guard over-generation is trimmed so final bosses can pose a real threat: Druid's Shifter Bruiser was piling up too much Guard from sources that never asked you to do anything for it. Werebear no longer grants the party a free 8 Guard on top of its own Guard, Slow, taunt, form-shift, and draw, and Oak Sage's chained Spirit Wolf no longer ticks 3 Guard every hero phase on top of the pack it already summons. Both cards keep everything else they did. A fleet A/B on this trim showed win rate holding steady (non-inferior) while removing the padding that was letting Druid shrug off even the final bosses.

UI

  • Bug reports now include sanitized diagnostics for faster alpha triage: Alpha bug reports now attach a safe snapshot of the current run, screen, build, and recent actions so crashes and stuck states are easier to reproduce without a follow-up.
  • Combat resource chips and the Autopilot controls stay legible when the game is scaled down.: The run resource chips, the combat header, and the Autopilot panel drew their text at sizes that shrank into the low single-digit pixels on a laptop screen. They now hold a readable size no matter how far the game is scaled to fit the window, and the Autopilot speed buttons match the Display Settings speed control they mirror.
  • The Field Log reads clearly — messages and the Close button are legible when scaled.: The open Field Log's messages and its Close button were drawn at a tiny size that shrank further on laptop screens. They now hold a readable size regardless of how far the game is scaled to fit, and the panel sizes to the game canvas instead of leaving a large empty gap below the log.
  • Settings controls are readable — available options no longer look disabled.: The Display Settings choices and toggles were drawn in a barely-visible faint tint, so an available option looked greyed-out until you selected it. They now use a readable label colour that stays clearly a step below the bright selected state, and the text holds a legible size when the game is scaled down to a laptop screen.
  • Inventory item names, stats, and tab labels are legible instead of tiny.: With the inventory's full height recovered, its meaningful text is enlarged to a readable size across every tab — item names and stats in the Pack, skill descriptions, attribute names and effects, and the tab labels themselves no longer shrink into unreadable single-digit pixels on a laptop screen. The Pack grid now scrolls internally so the larger labels never clip, and the hero portrait fills the recovered space.
  • The Inventory (and other overlays) no longer leave a large black gap on laptop screens.: Opening the Inventory on a scaled-down window used to leave a big empty band below the panel — the layout was sizing itself to the shrunken viewport and then getting shrunk again. It now fills the game canvas properly, so Loadout, Pack, Relics, Skill Tree, and Attributes get the full height they were meant to have. The same fix cleans up the gap under the Wiki, Training, Spellbook, and Merchant overlays.
  • A prev/next target strip with a live count when the enemy row is crowded.: When three or more enemies share the battlefield, a compact prev/next target strip now sits under the row with a live "which of how many" count, so switching targets no longer means hunting across a horizontally-scrolling lane — and the same control works by pointer or keyboard. On phones the hand also fades at its edges to show there are more cards to scroll to.
  • Pick and switch enemy targets from the keyboard, with the choice announced.: Combat targeting is now fully keyboard-operable. Tab lands on the current target (or the first enemy), the Left/Right arrows move between enemies, Home/End jump to the ends, and Escape drops the target — each change is announced for screen readers with the enemy's intent and remaining life. Playing a numbered card keeps focus on your target so you can keep acting without reaching for the mouse.
  • Full-screen overlays now fully hide the game behind them from keyboard and screen readers.: When a story, arrival, or boss overlay is open, everything behind it is now removed from the keyboard tab order and the screen-reader tree, so focus and narration stay on the one surface you are meant to be reading. The full-screen cinematics — cold-open, town arrival, boss threshold, act guide — are now proper modal dialogs, and Escape can no longer reach a control hidden behind them, while a dialog's own click-anywhere backdrop still dismisses it. On the hero-select screen, only the visible face of a hero card — portrait or campfire reading — is reachable now, so the hidden side no longer clutters keyboard and screen-reader navigation. The same isolation backs every modal in the game, built on the existing overlay focus system rather than a parallel one.
  • Charm reward cards now spell out pouch capacity instead of an orphaned "Fits" label: Charm reward cards used to show a bare "Fits" label and a plain "N slot(s)" badge with no sense of how full your pouch already was. The fit note and slot badge now say the slot cost, how many slots are free, and your used/capacity count — for example "Fits your pouch · uses 2 slots of 4 free (8/12 filled)" or "Needs 3 slots · 10/12 filled — make room to take it" — matching the numeric language the charm pouch overlay already uses. The onboarding tutorial's charm-intro step was also corrected: charms occupy a pouch slot (per the ROG-906 slot-budget system), so the old "no pouch slot required" line was stale and is now accurate.
  • The cover now tells you which account mode "Begin/New Expedition" will start in.: The cover's main "Begin Expedition" / "New Expedition" button always started a run without asking, but it wasn't clear whether that meant playing as a guest or continuing your signed-in account. A short note under the button now says which one it is, and the "Continue as Guest" option is retitled "Keep playing as a guest" to read as the secondary choice it always was.
  • The first-camp walkthrough no longer appears inside Veyra or tells you to recruit a mercenary you already hired.: The first-run camp walkthrough now begins the moment you enter town and its beats follow one another in order, holding your input until each is dismissed — so town actions can't slip in between them. The walkthrough can no longer pop up inside the Mercenary Captain's window right after you hired someone and insist you still need to recruit. It's also trimmed to what you can actually do on a first visit — recovery, mercenary, and heading out — and the Blacksmith, Vendor, and Stash now introduce themselves the first time you open them, instead of all at once up front.
  • Internal onboarding-engine groundwork (no visible change yet).: Laid the groundwork in the tutorial engine for smarter onboarding: steps can now declare themselves irrelevant for the current run/profile state, a session snapshots its relevant steps up front so it can't desync mid-session, and the engine can notify listeners when a tutorial session ends. No tutorial content uses any of this yet, so nothing changes for players in this release.
  • The ranked result screen no longer claims a rank or a posting it hasn't confirmed.: The run-end ranked panel was occasionally getting ahead of itself. It could show an impossible projected rank (worse than the whole field), call an unverified run "first on the board", say "score posted" before the server had acknowledged the run, and promise "your run is safe" even when it had never reached the server. The score itself was always fine — it's computed locally and final the moment the run ends — but the rank and the "we have your run" messages now wait until the server actually confirms them. A projected rank is always drawn from a field that includes your own run, so it can never read as "#24 of 23"; "first on the board" is reserved for a verified #1; and if verification can't reach the server, the panel says your score is saved locally rather than promising it's safely posted.

Fixes

  • Keep the bug-report launcher visible, separate from the mute badge, and draggable to a saved screen position.: The floating bug-report button now stays available after the report dialog closes, starts above the muted-sound badge, and can be dragged to a preferred position that is restored on the next visit.
  • The first-run walkthrough now blocks keyboard and screen-reader input, not just mouse clicks.: A blocking step in the opening town walkthrough dimmed the screen and refused mouse clicks, but a keyboard user could still tab straight to a town NPC and act mid-walkthrough. Blocking steps are now true modals: the rest of the screen is removed from keyboard and assistive-technology focus while the step is up, and focus returns to where it was once you continue.
  • Fixed overlays like Feedback leaving the game frozen behind them after closing.: Closing an overlay that patches in place (Feedback, and any similar surface that removes itself without a full screen re-render) could leave the game behind it unresponsive to clicks and keyboard input. The background is now correctly un-frozen the moment the overlay closes.
  • Hovering (or tabbing to) an enemy's trait badge now shows what it does.: Enemy trait/affix badges on the battlefield sprite carried a hover tooltip that never actually appeared — you had to open the enemy inspect panel to learn what a trait like Frenzy or Cursed does. Hovering, or tabbing to, the badge now shows its name, "Trait," and a plain description right on the battlefield, matching the inspect panel's tooltip.
  • Front-door copy no longer calls a device-local start "a guest," and the guest button doesn't claim a brand-new visitor is "keeping" a session that never existed.: The signed-out front door said the primary "Begin/New Expedition" button "starts as a guest," but that button never talks to the server at all — it's a device-local start with no account, distinct from the separate "Continue as Guest" button that really does create a server-backed guest account. The note now says what actually happens ("Starts on this device — no account needed."). The guest button itself said "Keep playing as a guest" even for a visitor who had never played anything; it now only says that when there's existing local progress on the device for the new guest session to carry forward, and offers a fresh-start phrasing otherwise.
  • Field Log entries no longer overlap when the panel is full.: Opening the Field Log with a long history no longer squeezes every entry into a sliver and spills its text across neighbouring rows. Each entry now sizes to its own content and the panel scrolls as one clean list, so the log stays readable at laptop and phone widths alike.
  • On phones, the Field Log opens on-screen and the hero status chip stops clipping.: In portrait, the Field Log used to open centered below the bottom of the screen (you had to scroll to find it), and the hero's status chip in the top bar cut off its text. Both are fixed: overlays now anchor to the actual screen on narrow layouts, and the status chip sizes to its content.
  • Cover, character select, rewards, and the world map now fit phones and portrait tablets.: The out-of-combat screens now reflow to the screen you are on instead of clipping or shrinking to an unreadable size. On phones the sign-in row no longer covers the menu, hero selection keeps Back, Builds, and Commit on screen, reward choices and their confirm button stack into one readable column, and the world map fills the height with room to pan rather than crushing every stop into one corner. Portrait tablets that used to snap to a tiny zoomed-out canvas now use the readable phone layout instead, so controls stay large enough to tap across the whole range.

Tech

  • Harden database restores and discard corrupt backup snapshots.: Bumped @andrewpopov/db-backup to v0.13.1. Two fixes land with it: restoreBackup now takes the advisory lock (so a scheduled backup or prune can no longer race a restore mid-rename — rouge's db:backup:restore goes through the package CLI, so it gains this), and a corrupt snapshot is now discarded rather than left in the backup directory under a valid name, where it could occupy a retention slot and evict a good backup.
  • Added a server-issued, signed, single-use ranked seed mint endpoint (no player-visible change yet).: Ranked runs will soon use a seed the server mints and signs rather than one the client picks, so a player can no longer seed-fish or replay a favorable seed. This step adds the minting side only: a new POST /api/ranked/seed endpoint that authenticates the caller, generates a cryptographically random seed and nonce, stamps the current engine version, persists the token, and returns an HMAC-signed, time-limited token. Consuming the token at run submission and wiring the client to request it land in follow-up steps — nothing player-facing changes yet.
  • Added the server-side loader that reassembles and validates a sealed ranked submission's input log (no player-visible change yet).: First step of the ranked replay-verify worker: a new server module reads a sealed ranked submission's stored segments, reassembles them into the full ordered event log, and gates on chain integrity (a recomputed hash chain must match what was sealed), stored-hash agreement between the submission and its seed token, log length, and engine-version parity with the current build. It also extracts the trusted seed/class/mode from the seed token and the claimed run outcome from the terminal event. This step only loads and validates — actually re-simulating the run through the game engine to compare outcomes lands in a follow-up step.
  • Ranked runs are now version-gated on a verifierHash covering the full replay surface, so a re-sim can never be judged against a different engine build (no player-visible change).: The ranked replay-verify version gate previously compared a run's sim comparabilityKey (content + scorer + combat/sim/run/rewards behavior). But a ranked replay dispatches recorded events through the real production action-dispatcher, which also drives app/UI/state/town/items/meta/character/content code — a change there could alter a replayed outcome without forking the key. Ranked seed tokens now carry a verifierHash covering the entire replay surface (all of generated/src + the compiled replay-harness helpers + the seed JSON the harness loads at startup), stamped at mint and cross-checked at seal. The verifier gates on it: a run whose verifierHash doesn't match the current build (including pre-upgrade tokens that lack one) is flagged as version-skew and never silently ranked, instead of being re-simulated against an engine the player never ran. Multi-version pinned re-sim (verifying old runs against their original build) remains deferred infrastructure.
  • Content-manifest startup preflight no longer bricks dev/test/clean-checkout servers (fatal only in production).: The ROG-1060 content-manifest startup preflight used to throw whenever generated/content-manifest.json was missing or stale — but that file is a npm run build artifact that npm test/pretest never generate, so a clean checkout, a fresh worktree, or CI would fail every server-spawning test with "Missing content-manifest.json". The preflight now degrades gracefully: in production a missing or stale manifest is still FATAL (the server refuses to start until npm run build regenerates it), but in dev/test it logs a one-line warning and returns a "manifest unavailable" status instead of throwing. When the manifest is unavailable the shadow-mode profile state validator is simply not wired, so profile saves still work (the shadow validator was logging-only anyway). No player-facing change.
  • Ranked runs now start from a canonical, account-independent state so the server's replay-verifier can reproduce them (foundation for comparable ranked scores).: A ranked run's construction-time state is now a pure function of {classId, seed, mode} with no account-derived input: it uses a fixed canonical mercenary (not the player's selected one), an empty canonical profile view (no account charm/potion unlocks, no tree-access from account progress), and clamps ascension against that canonical view. This is the same view the W4 replay-verifier reconstructs from an empty profile, so honest ranked runs stop false-mismatching in shadow — the foundation for comparable ranked scores (W7e daily/shared seeds) and a real leaderboard. Casual, arena, and puzzle runs are unchanged (the canonicalization is gated on ranked mode). A single production module (ranked-run-canonical) is the one source of the canonical view, used by both the ranked start and the replay driver so they can never diverge. This is Phase 1 (construction-snapshot pools + mercenary + ascension); later phases canonicalize the live per-decision reads (card rewards, economy/loot/town). Part of ROG-1082 / W7.
  • The default-OFF sim focus-fire gradient now brace-gates its kill-proximity bonus under a telegraphed alpha strike, fixing an amazon burst-death regression found in fleet A/B.: Sim-pilot only; no player-facing change (the __focus_fire_gradient__ probe is never set in production, so the shipped pilot stays byte-identical). A fleet A/B of the focus-fire gradient found it reduced Summit-Wardens losses for 5/6 classes but regressed amazon via a rare tail of 4-turn burst deaths — the pilot chased the kill-gradient instead of building guard against a telegraphed alpha strike. The kill_proximity state-delta bonus now attenuates to a brace fraction when a heavy single hit is telegraphed (≥50% of hero maxLife) and incoming is unblocked (guardGap > 0), so a needed guard/heal play outranks it. Reuses the existing heavyIncomingMultiplier/guardGap survival signals; efficacy re-validated via a higher-N fleet A/B. Part of ROG-1086.
  • Arena write endpoints now reject blocked users (not just unsigned requests), closing a balance-data / public-board pollution hole.: The /api/arena/record and /api/arena/run-summary write endpoints previously accepted any request with a valid token signature — they skipped the account block check that run-complete telemetry already does. A blocked user could therefore keep writing arena balance rows and user run-summaries (a public-board source). Both handlers now route through the same unified resolveIdentity path: a blocked account gets a 403 (and an audit log entry), and anonymous visitor cookies / no-identity requests get a 401 — arena writes require a real signed-in account. Part of W7 (ranked ops & anti-cheat second layer).
  • Ranked seed issuance now caps how many live seed tokens one account can hold at once, closing a seed-farming avenue.: The ranked seed-mint endpoint was already rate-limited per IP (velocity), but over a token's 3-hour lifetime an account could still accumulate a large pool of unconsumed seeds and cherry- pick favorable ones (seed farming). Minting now rejects with 429 once an account holds the maximum number of outstanding (unconsumed, unexpired) seed tokens — 16 by default, env-tunable via ROGUE_RANKED_ACTIVE_TOKEN_MAX. Consuming or letting a seed expire frees a slot. A real player holds one or two at a time, so this is invisible in normal play. Part of W7 (ROG-1061).
  • Hardened the run-complete and arena run-summary write endpoints — body cap, rate limit, and idempotent run-summary submits.: Three abuse-surface closures on the telemetry/arena write paths (W7 / ROG-1061): run-complete body cap — the endpoint now caps its request body at 1 MB (was inheriting the 5 MB global default), matching the other authenticated writes. run-complete rate limit — added a per-IP limiter (60/min, env-tunable) so the endpoint can't be flooded; a real finished run posts far below this, and the existing per-visitor DB cap + idempotency already bound the rest. arena run-summary idempotency/api/arena/run-summary now accepts an optional client_summary_id; a replay with the same key on the same profile is deduped to the original row (returns it, idempotent: true) instead of inserting a second public-board entry. Keyless submits behave exactly as before. Backed by a nullable column + a UNIQUE(profile_id, client_summary_id) index on the balance DB.
  • The ranked input log now captures a per-decision timestamp (outside the integrity hash) to feed future human-plausibility checks.: Each recorded ranked input-log entry now carries a capture timestamp (t, ms). It is stamped on the entry itself, deliberately OUTSIDE the hash-chained canonical payload, so it never affects chain integrity or the server's replay/verify byte-parity — it just rides along as advisory metadata. This gives a later anomaly-detection pass the raw timing needed to spot implausibly fast inter-decision deltas (bot/TAS play). Capture only; the statistical detection itself is deferred. The clock is injectable for deterministic tests. Part of W7 (ROG-1061).
  • Rate limiting and IP logging now key on a non-spoofable client IP, closing an X-Forwarded-For bypass.: Per-IP rate limits and visit-IP logging previously trusted the first hop of the X-Forwarded-For header — which is attacker-controlled (a client can send its own XFF and Cloudflare/cloudflared only appends to it), so anyone could forge or rotate their apparent IP and slip past every per-IP limit. Both paths now resolve the client IP from a trusted source in order: Cf-Connecting-Ip (set by Cloudflare's edge, which overwrites any client value, so it can't be forged) → the last X-Forwarded-For hop (edge-appended, not the client's injected leading hops) → the socket peer. The three duplicated IP-resolution helpers (rate limiting, visit logging, feedback logging) are unified into one, and rate limiting only exempts a genuine loopback *socket* with no proxy headers — never a header-derived loopback. Part of W7 (ROG-1061) ranked ops & anti-cheat hardening.
  • The ranked verify worker now pauses between re-simulations so it doesn't starve the game server on shared hardware.: Each ranked verification is a full run replay through the game engine — minutes of CPU. The shadow verify worker ran them back-to-back with no pause, which on a single Raspberry Pi (server + worker on the same core) could spike gameplay latency. The worker now pauses between items (default 250 ms, ROGUE_RANKED_VERIFY_PAUSE_MS) so requests that queued during a replay get served before the next one starts, and scans a smaller default batch (ROGUE_RANKED_VERIFY_MAX_BATCH, default 10). This is the software throttle; running the daemon niced or off-box remains a deploy-side choice. Part of W7 (ROG-1061); found by the fable anti-cheat design review.
  • Arena block-check no longer costs a DB lookup per row, and a blocked client can't amplify audit-log writes.: The blocked-user gate on arena writes did one DB lookup per submission (the highest-volume write path) and logged a "blocked attempt" per request — so a blocked client hammering the endpoint became a DB-write amplifier. Block status is now cached per account for a short TTL: one lookup per user per window instead of per row, and the blocked-attempt audit log fires only on a fresh (uncached) detection — at most once per window. A hard cap keeps the cache bounded. Part of W7 (ROG-1061); found by the fable anti-cheat design review.
  • Balance sim defaults now preserve class-grand identity, reject ambiguous multi-seed arguments, and treat alpha-readiness outputs as disposable current-run evidence.: Internal balance runs now keep a class-signature grand charm in every representative meta-build loadout, reject ambiguous space-separated seed lists instead of silently under-sampling, and require fresh alpha-readiness evidence from the current build. The Arena Training Dummy remains available as an endless build-testing target and is now represented intentionally in the canonical monster list.
  • Surface failed best-effort sim-context DB writes instead of silently swallowing them: Internal (Sim Lab) only, no gameplay impact. The sim-context DB write is best-effort: on failure it logged a console warning and carried on, so the Sim Lab could imply a job's provenance had been durably saved when it silently had not. The write now reports its outcome (durable / skipped / failed), which is recorded on the job metadata, returned by the sim API, and shown as a "provenance not saved" badge in the Sim Lab when the write failed.
  • Full Revalidation is now classified as a remote tool, since launching it with default settings runs the suite over SSH on another machine rather than locally.: The Sim Lab groups tools by blast radius. Full Revalidation was grouped with local jobs even though its default host is a remote machine and its launch command shells out over SSH, the same shape as the other remote suites. It now sits with the remote tools, and a test derives that expectation from the launch plan — any tool whose default command reaches another host must be classified remote — so the grouping can no longer drift away from what the tool actually does. The remote group is renamed from "Remote reads" to "Remote hosts", since several of its tools write on the machine they reach.
  • Sim Lab tool safety metadata is now server-owned so the Launch tab can no longer be blanked by catalog drift, and CLI diagnostics forward their arguments untouched.: The Sim Lab Launch tab grouped tools by blast radius using a hand-maintained client-side severity map, which had drifted nine tools behind the server catalog; because the grouping filter looked up every tool, one missing entry threw and blanked the whole tab. Severity now lives on the tool catalog itself, is projected through the API, and an unclassified tool renders into the production-writes group tagged "Unclassified" rather than throwing. The sim front door also parsed diagnostic arguments into an object and rebuilt them, which silently dropped positional arguments and short flags, collapsed repeated flags, and rewrote digit-bearing flags such as --top-5. Diagnostics now receive their argument tokens exactly as typed. Commands remain argument arrays; nothing passes through a shell.
  • Launching a production-write sim tool now requires an explicit confirmation on the server, so the typed confirmation is a real gate rather than a prompt the interface draws.: The Sim Lab asks you to type PROD before it runs a tool that writes to production, but that prompt lived entirely in the browser: a request sent directly to the run endpoint started the job without it. The endpoint now derives the tool's blast radius from the server's own catalog and refuses to create the job unless the request carries the typed confirmation. The check sits at the single point where every sim job is created, ahead of any file or scheduler work, so a rejected launch leaves nothing behind and any future caller inherits the gate. The confirmation must be a property the request itself carries, not one merely inherited from a prototype, and it is compared exactly — a truthy flag or a differently-cased word will not stand in for it. The token is never stored in the job's values, metadata, or logs.
  • The Sim Lab Runs view reported zero wins for every experiment and the runs report inflated win rates to 99%; both now agree with the dominance report on what a win is.: Three parts of the balance toolchain disagreed about which finished runs count as wins. The Runs detail view looked for an outcome the database never stores, so it showed no wins and a zero win rate for every experiment, even ones with tens of thousands of victories. The Runs list counted through-act checkpoints alongside full clears. The runs report treated a hero's death as an infrastructure failure and dropped it from the denominator, reporting a 99% win rate where the real figure was near 60%. All of them now resolve a win the way the dominance report already did: a full clear only, with through-act checkpoints excluded from both sides of the rate. The Runs view additionally applies the same trusted-loss rule the dominance report uses, so the two now print the same number, and the runs that were set aside — underplayed, timed out, or stopped at a checkpoint — are reported alongside rather than quietly dropped. The list also stopped labelling an eight-class sweep with one arbitrary class.
  • Decision-sliced forced-candidate harvests no longer poison the RG002 canonical when a slow/contended host hits the run wall-clock ceiling.: The forced-candidate EV harvest (ROG-1066/A decision-axis slicing) replays a full act-1→5 run while capturing ~1900–3000 restorable decision snapshots. Under fleet core-contention that harvest could exceed the simulator's 10-minute run wall-clock hang guard, which returned a "successful" empty harvest. That empty manifest (sha256 of the empty kept-list) skipped all rollouts, finished fastest, won RG002's first-writer race, and poisoned the canonical — so every legitimate full harvest of that seed was then RG002-rejected, holing the dataset across all classes. Two fixes: (C) a wall-clock-truncated harvest now FAILS the shard (throws → the daemon retries) instead of emitting an empty manifest, and the harvest's own wall-clock ceiling is raised to 90 minutes (explicit, so a stray ROUGE_SIM_RUN_WALL_MS can't change harvest results) — well above any legitimate harvest, well below the ~3.5h daemon watchdog. (B) RG002 now lets a real (non-empty) manifest atomically UPGRADE an empty canonical (safe — an empty canonical ingested zero rows), while still rejecting a genuinely-divergent full-vs-full mismatch, closing the race the read-then-update version had. No player-facing change.
  • The ranked leaderboard no longer shows a stale board or paints itself over the menu after you leave.: The ranked leaderboard screen had two async races (the same ones the Daily Challenge lobby was already fixed for — the lobby was written by copying this screen). Rapidly switching class back and forth while a slow request was in flight could let an out-of-date response overwrite the current one, and clicking "Back to menu" before the board finished loading could let the late response repaint the board over the menu. Both are now guarded by a request-sequence check, so only the newest load ever commits and a load abandoned by leaving the screen commits nothing.
  • The sim pilot can now route around an optional miniboss it isn't strong enough to win (opt-in miniboss-skip arm), removing the artifact where it auto-walked every class into the act-5 Summit Wardens.: The sim pilot scored every miniboss zone a flat 320, so it always routed into the OPTIONAL act-5 Summit Wardens (the hardest fight in the game — enemy-power ~3241, above the act-5 boss). A human skips it when under-geared; the pilot's exhaustive-clear made it the #1 loss for the weak classes and substantially inflated their measured weakness (excl-Wardens, assassin/necro baseline WR jump 57→81). The fix adds a per-build routing-readiness gate: readiness = scorePartyPower(run) / max enemy-power in the zone — the project's own powerRatio instrument (loss-attribution's 0.7/0.9 cuts), class/build- relative by construction (the build's own power is the numerator). An OPTIONAL miniboss whose readiness is below a floor is FILTERED out of the reachable set (a score penalty can't skip it — the pool rule fights every non-boss before the boss), so the pilot routes on to the boss and the run stays winnable. The hero-power input recipe is extracted into one shared helper (buildRunHeroPowerInput) so routing and loss-attribution read the same numbers. Ships opt-in and default-OFF (floor 0 → byte-identical routing) behind the fleet A/B arm miniboss-skip:<floor> (e.g. miniboss-skip:0.85), for CRN-paired calibration before flipping the default. The default floor lives as a hashed literal in run-progression-simulator.ts so a later flip forks the comparabilityKey (a versioned recalibration, like the ROG-1093 town-topk flip). No player-facing change; no measured-balance change until the default is flipped.
  • Ranked screens no longer hang when the leaderboard is slow to load.: The ranked lobby and the run-end result panel each fetch two things: the board (a nice-to-have) and your own status (which decides whether you can start a run and whether your run is verified). A slow or dead leaderboard request used to be able to hold up the status you actually need — the lobby could sit on "Loading…" with no Begin button, and the result panel's verification could stall. The two are now fetched independently, so status lands as soon as it's ready, and every ranked request gives up after a few seconds instead of waiting forever.
  • Hardened ranked run identity so a stale mint or a restored run can't hijack the wrong lobby or result panel.: Two narrow race/identity fixes in the ranked flow, both invisible in normal play. Starting a Daily Challenge is asynchronous; leaving and reopening the lobby while that request is in flight could let a second attempt begin or let the first request touch the wrong screen — a begin is now bound to the exact lobby it was launched from, and a second begin is blocked until the first settles. Separately, resuming a saved run now tears down any leftover result panel from a previous run, and the ranked result panel/poll now identify a run by its unique attempt key rather than a class-plus-seed id that two different runs could share.
  • The per-encounter sim drivers (run-meta-build-combat-quality / run-alpha-readiness) can now thread a --trait-foresight probe key to the pilot scorer, enabling per-encounter A/B of flag-gated foresight terms.: Sim tooling only; no player-facing change (the probe is default-OFF and never set in production). The winnability runner could already enable a flag-gated pilot-scorer probe (__ROUGE_SIM_TRAIT_PROBE) via its --arms trait-foresight:<key> mechanism, but the per-encounter drivers could not — blocking measurement of per-encounter play-quality effects (e.g. focus-fire at multi-enemy boards) that don't move full-run winnability. This adds a --trait-foresight <key> flag to run-meta-build-combat-quality.js (validated against the same KNOWN_TRAIT_IDS/SYNTHETIC_PROBE_KEYS sets the winnability arm uses) and run-alpha-readiness.js; the key rides the already-serialized options/crafted-spec path (no new cross-worker plumbing, mirroring strength) and analyzeSpec sets the probe on the pilot window for the scoped duration of its encounter loop, restoring after — exactly mirroring the winnability runner's scoped set/restore. Byte-identical when the flag is absent. Part of ROG-1149 (Task 1: the plumbing).
  • Forced-candidate-EV sizing no longer under-shards long-combat classes into watchdog censoring, and the rollout recovers the ~57% of decisions it was silently discarding as "duplicate_identity".: Two fixes to the forced-candidate expected-value pipeline (ROG-1066/A decision-slicing, the ROG-940 dataset that ROG-941's scorer refit consumes): ROG-1150 — cost-model sizing. The decision-shard auto-sizer used a barbarian-calibrated PER_ROLLOUT_MINUTES = 0.55, which is 2–3× low for long-combat classes: warlock D=5 sub-shards ran 82–212 min and the tail exceeded the 3.75h daemon watchdog → SIGKILL survivor-censoring (the exact failure decision-slicing exists to prevent). Bumped to 1.2 (warlock's measured cost), so the sizer now picks a slice size that fits even the expensive classes under the watchdog. A blunt global bump — the real fix is class-aware / measured sizing from live wall-time (deferred). ROG-1151 — duplicate_identity recovery. The rollout keyed candidate identity on (kind, optionId), but optionId is the cardId — target-blind and kicker-blind. So the same card enumerated once per living enemy (different target, different EV) and base-vs-kicked variants all collided on one key and were excluded as "duplicate_identity", which — via the paired-complete rule — zeroed the entire decision's Δ. This silently discarded ~57% of every decision in the dataset. The fix threads the full play identity (targetId + extraEnergySpent) through the harvest candidate summary and the target-verification surface: different-target / kicked arms are now distinct and each rolled + verified independently (recovered as real data), while genuinely-identical copies collapse to one representative (saving the redundant rollout). Rollout-layer + additive summary fields only — snapshot.digest and the harvest manifest are unchanged, so RG002 / harvest determinism are unaffected. No player-facing change.
  • Clear the 23 pre-existing lint errors on master so CI can enforce eslint: Internal only, no player-facing impact. Cleared the 23 pre-existing ESLint errors on master (no-param-reassign, nested ternaries, require-imports, unused vars, prefer-services-bag, a file over the max-lines budget, and a few others) with behavior-preserving edits, so the CI lint step can be flipped from advisory to blocking.
  • Run eslint as part of pretest so lint is enforced locally while CI is disabled: Internal only, no player-facing impact. ROG-1167 cleared the lint backlog and made the CI lint step blocking, but CI is currently disabled (out of Actions minutes), which left lint enforced nowhere. Folding npm run lint into the pretest chain means every npm test now fails on any lint error or warning, so the clean state can't rot while CI is off.
  • Sim-lane parity guard so the pilot's SPEND_ALL_EFFECT_KINDS set and its test-helper mirror can't silently drift: Internal only, no player-facing impact. The sim pilot's spend-all counter-cashout effect kinds were hand-duplicated between the runtime scorer and its test-helper mirror with nothing guarding parity; a new sim-lane test now fails if the two sets drift, so the pilot keeps valuing minSpend counter-payoff cards correctly.

Operations

  • Adopt @andrewpopov/db-backup for the prod DB backup instead of a bespoke script: No player-facing change. The prod game-DB backup now uses the shared @andrewpopov/db-backup package (as bewks/smarthome/sano-os do) via a thin policy wrapper, replacing a ~200-line bespoke script. Gains WAL-safe snapshots, integrity verification, retention, a content-based freshness stamp, rclone offsite to R2, and db-backup restore; runs as the rogue DB owner under a systemd timer.
  • Pi deploy now generates the content manifest before reloading production: Production deploys now run the same content-manifest generation step as local builds before PM2 reloads the app, preventing alpha deploys from starting against a checkout that is missing generated/content-manifest.json.
  • Delete the dead prod-pull/prod-push/run-clone/worker-merge ssh sync layer; guard db-import against the game DB: No player-facing change. Removed the ssh sim-sync tools (prod-pull, prod-push, run-clone, worker-merge) and their runners/aliases — inoperable since the 2026-07-01 host move and superseded by the fleet's Postgres canonical. This also removes the last API-launchable DANGER tool that could ssh-write the prod game DB (skill-balance-promote remains the sole DANGER tool). The surviving db-export/db-import archive primitive now routes its import through the balance-store guard, so it can never write data/rouge.db (ROG-1137).
  • Crafted/meta-build sim loadouts now respect the real ascension-scaled charm-pouch budget instead of a hardcoded 8: No player-facing change (the runtime charm budget itself is unchanged — it never force-drops over-capacity charms, so this was never a live-game bug). The crafted/meta-build sim path (scripts/lib/meta-build/charm-loadout.js, meta-spec-builder.js) hardcoded a flat CHARM_POUCH_CAPACITY = 8 for every ascension, instead of reading the runtime source of truth (ROUGE_CHARM_SYSTEM.getRunCharmBudgetCapacity: base 12, minus 1 slot per 2 ascension tiers, floor 7). At ascension 0-7 this understated the real budget (12/10/9 vs the hardcoded 8); at ascension 10 it overstated it (7 vs 8) — a measurement-fidelity bug, not a balance one. Both the generated (knapsack) loadout and the explicit --charm-loadout CLI path now derive capacity from the runtime per-spec ascension and fail loudly if the runtime harness doesn't expose the budget function, instead of silently falling back to 8. Fleet re-baseline note: charm selection is still deterministic (no new RNG hazard), but bigger/smaller loadouts change combat state, which changes combat RNG draw counts. Existing 8-slot crafted/meta-build fleet baselines and A/B comparisons are no longer directly comparable to results generated after this change — re-baseline before drawing balance conclusions from a mix of pre/post-fix crafted-lane data.
  • Internal-only sim levers to A/B the Summit Wardens' damage split and Unbroken Oath threshold; no player-facing change.: Adds two default-off sim probes so the fleet can A/B whether the Act 5 Summit Wardens (ancients miniboss) fight is overtuned on its damage side or its death-prevention threshold — without touching live play. __wardens_damage_split__ splits each Warden's damage-bearing intent value (attack, sunder_attack, attack_and_guard, charge) by the count of living Ancients members, so 3 bodies deal roughly 1x combined output instead of 3x. Gated at runtime inside resolveEnemyAction (combat-engine-enemy-turns.ts) rather than at content-catalog build time, because the catalog is baked before the fleet arms the probe — a build-time gate would silently never fire on the fleet. summon_minion (War Horn) is excluded: its value derives the summoned unit's HP/attack, not damage. __wardens_oath_threshold__ raises the Unbroken Oath release threshold above the default 0.25 via a single gated getter (getAncientsOathThresholdPct, combat-anchor-constants.ts) that all 3 read sites — the death clamp, its duplicate lookup, and the sim pilot's pickAnchorEqualizationTarget — route through, so focus-fire partially pays off without the pilot aiming at a different peer than the death clamp protects. The threshold is clamped to the open interval (0, 1): a value at or below 0 would make the fight unwinnable (the first Warden could never die), and a value at or above 1 fully disables the Oath. Both probes are byte-identical to today when unset (the real-player default), so there is no gameplay change — they exist solely to fleet-A/B whether the Wardens fight's damage side and Oath threshold are overtuned before deciding whether to bake either change in.
  • Internal sim telemetry for runeword completion cadence; no player-facing change.: Adds per-seed runeword completion-cadence telemetry to the winnability sim (an additive run.progression.runewordCompletionLog recorded at socket-activation time, surfaced through the sim report and the fleet history row behind an opt-in --runewords flag). Byte-identical for normal gameplay — the log is only ever created when the runewords-and-sockets subsystem is enabled (off by default), so there is no gameplay, RNG, or persistence change for players. It exists to let the ROG-779 runeword tuning be validated against real completion-rate curves on the fleet.
  • Internal sim fleet-arm addition for natural-play runeword cadence experiments; no player-facing change.: Adds a runewords:natural arm dimension to the sim's --arms grammar (scripts/lib/sim-arm-dimensions.js). It enables the runewords-and-sockets subsystem for a run WITHOUT forcing any starting gear — distinct from the existing gear:<slot>=..@rw:<id> arm, which also enables the subsystem but pre-equips a specific socketed item (forced-equip delta-EV measurement, not natural pacing). Since the fleet submit path (scripts/fleet/fleetctl-pg.js submit) already forwards --arms verbatim to the runner, this composes with no further plumbing: an experiment like --arms baseline,runewords:natural measures the ROG-779 completion-cadence telemetry (report.summary.runewordCompletions) under free assembly, CRN-paired against baseline. Opt-in and additive — absent from an arm label, behavior is byte-identical to before this change.
  • Sim storage docs reorganized around four planes; bare sim:server-sync / sim:db-transfer aliases removed: No player-facing change. SIM_RUN_DATA_WORKFLOW.md is now organized around the four storage planes the code actually implements — the game DB (data/rouge.db, never a sim target), the local sim store (artifacts/balance/balance-runs.db), the fleet's Postgres canonical, and the file artifacts — replacing guidance that named the game DB as the default sim store. The two bare passthrough aliases sim:server-sync and sim:db-transfer are removed: each forwarded an unlabelled --mode to a runner backing both a safe and a production-writing tool, so sim:server-sync -- --mode push could become a production write while reading like a routine sync. (The remaining ssh sync aliases — sim:prod-pull / sim:prod-push and the clone/merge tools — were then removed entirely in ROG-1140; sim:db-export / sim:db-import is the surviving archive pair.)

Angel Snack 0.1.0-alpha.7 Patch Notes

Release date: 2026-07-09

Stage: alpha

Package version: 0.1.0-alpha.7

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Combat RNG is now seeded deterministically from the run seed and persists its draw cursor across saves.: Runs now keep combat randomness tied to the run seed across save/load boundaries, reducing drift when a run is resumed and making tricky combat outcomes easier to reproduce during alpha debugging.
  • Internal: combat input capture wired for a future run replay/audit log (no player-visible change).: This is internal replay/audit plumbing for future ranked-run verification. Players should not see a behavior change yet, but combat inputs now have a stable capture path for later replay validation work.
  • Softened the Rift ascension top-tier difficulty wall so the highest tiers are hard but winnable, not brick walls.: The upper Rift ascension tiers were an near-unwinnable wall at the top (Tier 10 in particular). This pass eases the act-5 boss scaling tail, lowers the Tier 5 elite encounter rate, reduces the Tier 8 max-life penalty, holds the +2 affix-count bump to the highest tiers, and caps Tier 10 pack-wide affixing to a few enemies instead of the whole pack — keeping the top of the ladder demanding without cliff-ing entire classes to zero.

UI

  • Alpha builds now include a floating bug-report launcher with best-effort screenshot capture for submitted bug reports.: Alpha players can now open a bug report from a floating question-mark button without digging through the game menu. Bug report submissions try to attach a browser-captured screenshot when permission and browser support allow it, while still sending the report normally if capture is unavailable.

Tech

  • Fleet reap now also clears stale "active" attempt rows left behind by uncleanly-killed daemons.: The fleetctl reap command now cleans a second leak in addition to stranded shards: attempt rows left active after their daemon died mid-run (kill -9 / OOM / power loss) when the shard itself has since gone terminal. These orphaned rows accumulated for days and polluted fleet monitoring reads. Only attempts older than a hard 5-hour floor (well past the 3.75h shard watchdog, so a live run can never be touched) are flipped to abandoned. Dry-run by default; reap --apply cleans them.
  • Durable server-side storage for the input-log integrity chain — ranked-run tables plus a verified segment-upload endpoint.: Adds the app-DB storage substrate for ranked-run verification (ROG-1059, epic ROG-1053): the ranked_seed_tokens, ranked_run_submissions, and run_input_log_segments tables (migration 0005), an atomic single-statement seed-token consume, and an authenticated POST /api/input-log/segment endpoint that ingests the client's ordered input-log segments. The server recomputes the canonical hash chain byte-for-byte against the client contract and rejects any gap, reorder, tamper, or cross-user upload, so a stored log is provably the one the player produced. Internal/tech only — no player-facing behavior yet; consumed by the signed-seed (W3) and replay-verification (W4) work.
  • Shadow-mode server-side profile validation: Added a build-time content manifest and a shadow-mode server-side validator that checks saved profiles for unknown ids, out-of-range progression, and debug-flag usage. Logs findings only — no client-visible behavior change yet.
  • Sim fleet can now shard a heavy forced-candidate-EV seed along the DECISION axis so it fits under the watchdog: The forced-candidate-EV runner is combinatorial per seed (~decisions × candidates × replicates rollouts), so a full-fidelity seed (~200min) blows past the 3.75h shard watchdog even at one seed per shard — and a kill→retry silently censors the longest-surviving seeds. Submit can now expand each seed into K decision-range sub-shards (--decision-shard-size D, or the opt-in cost-aware --decision-shard- auto), each seed_count=1 and each rolling out only its slice of the seed's kept decisions after re-harvesting the full seed. The per-seed manifest (Phase 1) plus the cross-host equality guard (Phase 2) keep the reassembled seed trustworthy across a mixed macOS-ARM / Windows-WSL fleet. Non-sliced submits — every other runner and forced-candidate-EV without the new flag — are byte-for-byte unchanged.
  • Sim fleet daemon now clamps its concurrency to a host's real core count, always reserving at least one core: The fleet worker daemon no longer trusts ROUGE_FLEET_CONCURRENCY blindly — it now clamps the effective sim concurrency to logical cpus - ROUGE_FLEET_CORE_HEADROOM, always reserving at least one core, so a misconfigured or copy-pasted concurrency value can never oversubscribe a host (the prior wintop-wsl concurrency=14 incident that slowed the ROG-940 EV shards past the watchdog). Interactive/shared hosts an operator actively uses can reserve more cores via the installer's new --core-headroom flag or the ROUGE_FLEET_CORE_HEADROOM env var. The heartbeat's reported concurrency (and the ROG-1070 oversubscribed flag) now reflect this effective, clamped value.
  • Sim fleet submit now hard-rejects a pin that isn't on origin/master: fleetctl submit/rebaseline --submit/charm-sweep --submit and the admin POST /api/fleet/experiments route now verify a --sha/sha pin is actually an ancestor of origin/master before enqueueing. Previously an unmerged-branch pin enqueued cleanly and every one of its shards was silently quarantined at claim time by the worker's own ancestry gate. A bad pin is now rejected immediately with an actionable "merge it first, or pin to a master sha" message.
  • Sim fleet heartbeats now report real host cores/load/mem, and flag oversubscribed hosts: The fleet worker daemon's heartbeat now carries real host-resource telemetry (cpu count, 1-minute load average, free memory) alongside the pre-existing configured concurrency. fleetctl status and fleetctl doctor (plus the /api/fleet/hosts dashboard data) now surface an oversubscribed flag when a host's configured concurrency exceeds its real core count — previously this was only inferable, never measurable, and slowed the ROG-940 EV shards past the watchdog on a host running concurrency well above its real cores. Old daemons that haven't self-updated yet simply omit the new fields — never a false OVERSUBSCRIBED alarm.
  • Sim fleet daemons can now be drained and restarted gracefully via the DB, with no wasted in-flight work: fleetctl-pg.js drain-restart --host <id|*> signals a fleet worker daemon (or every freshly heartbeating host at once, via --all) to finish its current shard(s), stop claiming new work, and re-exec — through Postgres, no SSH. This replaces the prior hard-restart-only path, which SIGTERMed any in-flight shard and forced a retry, wasting up to hours of watchdog-bounded work. The re-exec also re-triggers the existing startup self-update, so drain-restart is the way to roll out a daemon code change without a hard kill. --concurrency/--core-headroom apply a one-shot override on that restart only, so a host's concurrency can be right-sized remotely with no SSH access.
  • forced-candidate-EV runner supports decision-range slicing + per-seed manifests (fleet-inert): scripts/run-forced-candidate-ev.js (the fleet-backed forced-candidate ΔG EV sweep) can now slice each harvested seed's rollout to a --decision-offset/--decision-count sub-range, laying the groundwork for sharding a heavy seed's rollout matrix across multiple sub-shards. Every run also emits a per-seed manifest (the full ordered list of harvested decision digests) that a future ingest step will use to verify sub-shards agree on which decisions they targeted. The flags default to a no-op, so this ships inert — no fleet or player-facing behavior changes.
  • forced-candidate-EV fleet ingest now rejects cross-host harvest drift instead of landing it silently: The fleet ingest for the forced-candidate ΔG EV sweep now cross-checks every sub-shard of a seed's decision-range harvest against the per-seed manifest ROG-1074 started emitting. Sub-shards of one seed can run on different hosts (macOS/ARM vs. Windows/WSL x86), where floating-point transcendentals aren't always bit-identical, which could previously make two sub-shards target different decision sets and land gappy, mis-attributed EV data with no warning. A mismatch is now rejected loudly and retried (a later attempt, possibly on a different host, can heal it), and any affected seed is flagged so the EV report can exclude it. No player-facing or fleet-operator behavior changes beyond this data-integrity guard.

Operations

  • Compact Discord patch-note announcements: Discord patch-note announcements now stay short and readable by posting a compact release summary, a few highlights, release-area counts, and a link to the full notes instead of flooding the channel with full changelog text.

Angel Snack 0.1.0-alpha.6 Patch Notes

Release date: 2026-07-08

Stage: alpha

Package version: 0.1.0-alpha.6

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Fixes

  • Admin Console now safely returns sessions that lose admin access back to the hall.: If an Admin Console session loses its admin authorization, it now returns safely to the hall instead of leaving the player stranded on an unusable restricted screen.

Angel Snack 0.1.0-alpha.5 Patch Notes

Release date: 2026-07-08

Stage: alpha

Package version: 0.1.0-alpha.5

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Fix: Necromancer curse debuff-stack bonus damage (Soul Eruption) now correctly triggers Soul Leech healing.: Necromancer curse cards that deal bonus damage scaled by debuff stacks (e.g. Soul Eruption) were not triggering Soul Leech lifesteal on that bonus damage, even though their base damage did. Soul Leech now correctly heals off the full hit, including the stack-scaled bonus.
  • Skeleton Mastery now grants a persistent summon-hit aura for the rest of combat, applying to skeletons summoned afterward too.: Necromancer's Skeleton Mastery card no longer grants a one-turn summon-damage bump. Instead, each cast now permanently adds +3 damage to every skeleton's ally-phase strike for the rest of the fight — including skeletons you raise afterward. Repeated casts stack.

UI

  • Admin Console sidebar now groups admin pages into clearer operational sections.: Admin users now see the Admin Console sidebar grouped by Operations, Player Records, and Observability, making Settings, Sim Lab, player data, reports, and audit logs easier to scan as the console grows.
  • Admin Console now includes a Sim Lab tab for launching, monitoring, and reviewing simulation work.: Admin users can now open Sim Lab directly from the Admin Console sidebar to launch simulations, monitor fleet progress, and review completed experiment data without relying on the debug-only hall shortcut.
  • Sim Lab fleet progress now prioritizes attention-needed experiments and preserves authenticated writeup attribution.: Sim Lab fleet monitoring now keeps attention-needed experiments visible ahead of ordinary active runs, including mixed running/failing shard states, and completed experiment notes preserve server-side admin attribution.

Fixes

  • Block signed-out and guest gameplay entry when guest accounts are disabled.: When guest accounts are disabled, signed-out players and existing guest sessions now see a locked front door instead of being able to start, resume, or enter arena gameplay. Registered Google accounts continue to play normally.

Angel Snack 0.1.0-alpha.4 Patch Notes

Release date: 2026-07-08

Stage: alpha

Package version: 0.1.0-alpha.4

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Higher ascension tiers tighten the charm pouch — fewer slots as the difficulty climbs: The charm pouch shrinks as you climb Rift Tiers: you lose a slot every couple of ascension levels (from 12 at the base game down to 7 at the top), so higher-difficulty runs force sharper charm choices. It's a new kind of ascension pressure — on your build assembly, not just on enemy stats and skills.
  • Chain Reaction now shows its fire+lightning trap synergy in the card text: The assassin card Chain Reaction has always dealt bonus Burn and Paralyze to all enemies when you control both a fire and a lightning trap, but that synergy was invisible on the card — the text only read "Volley 16. Burn All 3." Its card text now advertises the build-around: "If you control a fire trap and a lightning trap, apply 3 Burn and 2 Paralyze to all enemies." No mechanical change — this makes an existing assassin trap payoff discoverable (ROG-970).
  • Charms now share a slot budget — pick your loadout instead of hoarding every charm: Charms are no longer unlimited. Your pouch has a 12-slot budget — small charms cost 1 slot, large and grand charms cost 2. When you pick up a charm that won't fit, open the pouch to discard one and make room, or pass on it. It's a real assembly decision: a build-defining grand crowds out a couple of smaller charms, so your loadout is a choice, not a pile. Charm rewards show their slot cost, the pouch shows what you're carrying, and an over-capacity charm's reward card lets you make room on the spot. Higher ascension tiers will tighten the budget further as a difficulty modifier.
  • Arena runs now include a Training Dummy for safe damage testing: The Arena now includes an endless, unkillable Training Dummy that heals to full every turn, so you can test a build's damage output with a live damage-per-turn readout. A debug toggle can make it hit back when you want to stress-test defenses.

Balance

  • Large Charm of Cleaving is now a Rare charm (was Boss-rarity): With Cleaving fixed to actually work, its drop rarity was re-tuned to match its real power: it's now a Rare charm rather than a Boss-tier one, so it turns up a bit more often. (Under the hood, the charm scoring model also now values a few bonus types it previously ignored, so future charms bucket at the right rarity.)
  • Grand Charm Earthshaker toned down — its opening stun no longer gives a free first turn: Earthshaker was over-performing for the Barbarian. Its start-of-combat stun handed you a free opening turn against bosses, so it now triggers on your first kill each combat instead — still a strong crowd-control tool against packs, but no longer a guaranteed free turn against a lone boss. Its execute bonus against the lowest-life enemy is also reduced from +6 to +3.
  • Rift ascension affixes now correctly start in act 3 (were spiking acts 1-2, making Rift Tiers unwinnably hard from Tier 2).: Rift Tier 2's headline modifier — "normal enemies gain +1 random affix" — is meant to kick in from act 3 onward, but it was firing from act 1. That handed act-1 and act-2 normal packs (which normally have no affixes) an extra affix each, spiking the early game right where your build is weakest and making every Rift Tier from 2 up effectively unwinnable. Affix pressure now correctly begins in act 3, so the early acts of a Rift run stay close to Normal and the difficulty builds over the run as intended.
  • Rift ascension affixes now hit only a few enemies per pack (scaling with tier), not the whole pack at once.: Rift Tier 2's "+1 random affix" was landing on *every* enemy in a pack, so an act-4 swarm of five became five affixed enemies at once — a brutal spike that made the low Rift Tiers effectively unwinnable. The affix boost now hits only a capped number of enemies per encounter, and that cap grows as you climb: 1 enemy through the early tiers, 2 in the middle, 3 in the high tiers, and the whole pack only at the very top. The rest of the pack rolls Normal affixes, so the ladder ramps up smoothly instead of spiking.
  • Large Charm of Volley now rains arrows across all enemies (was a focused three-shot): Volley had become nearly identical to the Amazon's Strafe grand. It's now the area-suppression bow charm — every 3rd attack looses an arcing volley for 5 physical damage to all enemies — while Strafe keeps the focused, auto-aiming triple shot into the weakest foe.

UI

  • Sim Lab now presents fleet progress, run review, and launch tools in a cleaner lab workspace.: Sim Lab now shows live fleet progress, worker checkouts, completed experiment review, and risk-grouped launch tools in a cleaner operator workspace.

Fixes

  • Arena autopilot now plays each deck with its own build identity instead of a generic balanced pilot: Arena autopilot previously played every deck as a generic "balanced" character, so a deck built around summons, javelins, curses, or any other specialization was piloted without the priorities that build is meant to reward — and its measured performance reflected that mismatch, not the build. Autopilot now reads each deck's build identity and plays to it, so arena runs show how a build actually performs when played to its strengths.
  • Autoplay and autosuggest now follow your actual build instead of playing every character as a generic balanced archetype: Autoplay and the card-suggestion highlight previously scored every character as a generic "balanced" archetype, so a build committed to summons, demons, curses, traps, or any other specialization never got the play priorities that build is meant to reward. They now read the tree you've actually invested in and weight the recommended plays toward your build's identity — so watching autoplay (or following the suggested card) reflects how your character is supposed to be played, not a one-size-fits-all default.
  • Autoplay/autosuggest now follows assassin-traps and sorceress-cold build identity: Autoplay and card-suggestions for assassin Traps builds and sorceress Cold builds now activate that build's identity instead of playing as the generic class default.
  • Large Charm of Cleaving and the Warform Grips unique now actually work: Two effects that hooked a combat trigger that was never wired up were silently doing nothing, and now fire correctly: Large Charm of Cleaving — "First attack each turn: draw 1 and gain 2 Guard." Warform Grips (unique gloves) — "Every 3rd attack: deal 12 damage and heal 6."
  • Route combat executions and direct DoT through shared death-prevention and stop countdown spillover after combat ends.: Combat executions, Poison, piercing Burn, and countdown detonations now respect the shared death-prevention rules. Training dummies and protected bosses no longer get bypassed by direct combat effects, and queued countdown cards stop resolving once the fight is already over.
  • Audit Game settings wiring, restore inert controls, and align Autopilot speed controls with named pacing presets.: Game settings for Autopilot now update the same backing settings the rest of the game reads, so HUD controls, debug AI Assist, skip-FX, and named speed presets stay in sync. The Game tab also exposes Autoplay and Autosuggest switches even when they are off, and pressing Stop persists both Autopilot entry points as off so a reload cannot quietly bring automated play back.

Tech

  • Adopted the shared release-kit package for patch notes and release tooling: Internal maintainability change — replaced the inline release-note engine (scripts/lib/release-notes-core.js, scripts/release-notes.js, scripts/cut-release.js, scripts/check-release-hygiene.js) with the @andrewpopov/release-kit package, configured to reproduce this repo's exact prior behavior byte-for-byte. No change to patch notes, versioning, or the release-hygiene gate; normal play is unaffected.
  • Internal refactor — split the combat damage engine into two modules under the line-cap (no manual-play change): Internal maintainability split (ROG-1031). The combat damage engine had grown past the project's per-file line cap, which was blocking the test suite. Its incoming-damage / mitigation calculators were moved verbatim into a sibling module, leaving the damage-application logic and every runtime behavior byte-for-byte identical. Pure refactor — combat math, logs, and outcomes are unchanged; normal play is unaffected.
  • Split Sim Lab launch rendering into the launcher module: Internal maintainability change: the Sim Lab Launch tab renderer now lives with the launcher card module, keeping the main Sim Lab shell under the TypeScript line cap without changing player-facing behavior.

Operations

  • Discord deploy announcements load local env files: Production deploys now read the ignored local Discord env files before posting patch-note announcements, so configured release bots announce shipped builds without requiring operators to export the token by hand.

Angel Snack 0.1.0-alpha.3 Patch Notes

Release date: 2026-07-06

Stage: alpha

Package version: 0.1.0-alpha.3

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Gameplay

  • Full charm pouches now pause the reward claim instead of losing the charm, so you can drop one and retry: Internal groundwork only (ships dark — no visible UI change yet): when the charm pouch slot budget is enabled, claiming a charm reward with a full pouch no longer errors or silently drops the charm. The reward now waits so a future update can let you drop a charm and retry, or skip the reward outright.
  • Charm pouch slot budget groundwork (ships dark behind a debug flag): Internal groundwork only (ships dark behind debugMode.charmPouchBudget): runs can now track a charm-pouch slot budget, with small charms and grand charms consuming different amounts of space. The default production experience is unchanged until the flag is enabled, but the saved-run and reward plumbing is in place for the upcoming pouch-capacity UI.
  • Charm Pouch overlay: view your slot budget, discard charms, and make room for a reward that doesn't fit: Internal groundwork only (ships dark — behind the same debug flag as the pouch slot budget): adds the Charm Pouch overlay UI, reachable from combat, reward, and town screens. It shows your slot capacity as pips, lets you discard a charm (locked during combat, since bonuses are baked at fight start), and — when a reward charm won't fit — opens straight into a "make room" view where you can free a slot and take it, or decline the reward outright.
  • Refreshing the page mid-combat now resumes your fight instead of dropping you to the world map: Reloading the game during a fight used to discard the encounter and drop you back on the world map. Your combat is now saved and restored, so a refresh (or coming back later) resumes the fight exactly where you left off. If a saved combat is too old to restore safely, we keep your run and return you to the world map instead of losing the run entirely.

Balance

  • Charm focus pass — grand charms now center on one build-defining effect, themes spread out so a class's grands feel distinct, plus targeted dedup: Grand charms got a focus pass. Each one now centers on a single build-defining effect with at most a couple of reinforcing riders, instead of a pile of unrelated bonuses — so equipping a grand tells you what your run is about. Their themes were also spread out so a class's grands pull toward different playstyles (execute, hard crowd-control, summon-army, traps, curses, guard-walls, energy economy, lifesteal, damage-over-time) rather than several variations of the same "every few cards, hit everything" effect. Grand Charm: Eldritch Hunger (Warlock) no longer overlaps Chaos Debt. It now leans into the void: each card you exhaust drains 4 magic damage from the target and heals you 3, and the first Exhaust each turn still draws a card and banks Energy — a single-target sustain engine. Small Charm of Drumbeat now grants +2 Mercenary Attack and +1 Damage (previously a duplicate +2 Damage). Small Charm of Arcane Battery now grants +1 Spell Damage and +5% Crit (previously a duplicate +2 Spell Damage).
  • Blacksmith Temper (-1 Energy) and Hone (+Draw 1) upgrades are now much pricier (240g / 200g) — premium mods are a rare splurge, not a routine buy.: The Blacksmith's two strongest card upgrades are now premium purchases: Temper (card costs 1 less Energy) rises to 240 gold and Hone (card gains Draw 1) to 200 gold. Energy and card draw are the game's most powerful levers, so these are meant to be a rare, deliberate splurge rather than something you buy on every card. The mild stat upgrades — Sharpen (+3 damage) and Fortify (+3 Guard) — stay cheap at 50 gold.
  • Removed the Blacksmith's Refine service; card upgrades (card+) now come only from skill-tree ranks and the miniboss Forge Scroll, not gold.: The Blacksmith no longer offers Refine, the option that bought a card's upgraded (card+) form for gold. Card upgrades now come from the two intended channels only: investing 5 ranks in a skill, or claiming a Forge Scroll from a miniboss reward. This keeps your skill trees the meaningful path to stronger cards rather than something gold can shortcut. The Blacksmith still offers card Evolutions and generic stat Upgrades.
  • The 8 class-signature attribute charms now cost 1 charm slot instead of 2: The class-signature charms that grant a permanent attribute (Blood Oath, Aegis Pledge, Huntress Mark, Silent Strike, Nature's Blessing, Bone Pact, Arcane Keystone, Demon Pact) are small charms and now cost a single charm slot, matching every other small. They previously charged 2 slots — a leftover from before they were re-tiered — which only mattered once the charm-slot budget is in play.

Content

  • 18 new charms fill the freeze, bow, trap, curse, and defensive gaps — earned from existing achievements: Eighteen new charms join the pool, closing coverage gaps and opening play patterns the roster was thin on: Freeze / crowd-control: Coldiron (pierce status resistance), Winterlock (frost when you're hit), Stillfrost (freeze when you end a turn untouched), and the barbarian grand Earthshaker (an opening stun). Bow / multi-hit: Fletching, Volley (a three-arrow salvo), and the amazon grand Strafe (auto-aims the weakest enemy). Traps / delayed payoff: Slow Fuse (a turn-4 timebomb), the Hourglass (refills Energy every 10 cards), and the assassin grand Tripwire (trap tempo + control). Curses: Afflictor's Edge (each status you land adds damage) and the necromancer grand Soulleech (afflictions heal you). Defensive: Stoneskin (flat damage reduction), Rampart (keep some Guard between turns), Lifeline (a once-per-run emergency heal), and the paladin grand Crown of Thorns (ramping retaliation). Plus the warlock grand Blood Ledger (pay Life for cards) and Wayfarer's Purse (gold + cheaper shops). Each is unlocked from an existing achievement track; the six class grands come from clearing all bosses with that class. Icons for the new charms are coming in a later update.

UI

  • Add an admin feedback inbox for submitted bugs and suggestions.: Admins now have a Bugs & Feedback tab that lists player-submitted bug reports and suggestions newest-first, including contact details and captured run context. This makes in-game feedback actionable after submission instead of disappearing into raw server storage or Discord-only alerts.
  • Full-screen character and run-end surfaces now share the canvas-fit height contract.: Hero selection, expedition setup, and other full-screen cinematic surfaces now use the same canvas-fit height contract, removing the short bottom gap that appeared on the character flow.
  • Keep feedback form input actions covered by the UI dispatcher audit.: Feedback form typing now uses registered input-dispatcher actions covered by the UI action audit. The visible form behaves the same, but future input refactors are less likely to silently break message/contact entry or force unnecessary full-screen rerenders while the player is writing a report.
  • Add in-game bug report and suggestion submissions with Discord bot notifications.: Added a feedback option to the game menu so players can submit bug reports or suggestions without leaving the app.
  • Restyled the Terms and Privacy pages with richer legal-page backdrops and bordered document panels.: The Terms and Privacy pages now use darker scene backdrops, stronger document-panel borders, and clearer legal navigation so the alpha service pages feel more like the rest of Angel Snack.
  • Adds a carved stone door backdrop outside the game frame.: The letterbox space around the game now uses generated carved-stone door art, giving the app shell a darker dungeon-threshold frame instead of a generic warm wash.
  • Adds thematic art backdrops to previously generic screen surfaces.: Combat Puzzles, puzzle results, Training, and Sim Lab now use curated thematic art layers instead of plain shell gradients, so those secondary screens feel anchored in the same carved-door, gothic campaign presentation as the rest of the game.

Fixes

  • Repair review hygiene and boss-readiness scoring: Cleaned up review-blocking lint/type issues and corrected boss-readiness scoring so balance reports judge boss pressure from the intended score terms. This is mostly behind-the-scenes, but it makes the generated balance guidance more trustworthy before tuning changes reach players.
  • Exploration charm rewards gracefully decline instead of stalling when the charm pouch is full (flag-gated): When the charm pouch slot budget is enabled, finding a charm during exploration while your pouch is full no longer gets stuck on a dead choice — the charm is declined and the encounter continues normally. This system is currently flag-off in production.

Tech

  • Added a cross-domain boundary ratchet that freezes private-namespace reach-through (no manual-play change): Internal architecture guardrail (ROG-989). Documented the enforceable module boundary — a domain's __ROUGE_* namespaces are private, and its public read surfaces are the blessed cross-domain entry — and added a pretest ratchet that counts how often UI/sim code reaches into another domain's private internals and fails the build if that number grows. Existing coupling is frozen, not rewritten, so it can only shrink over time. No gameplay impact.
  • Parity-guard several hand-mirrored tables/sets so silent drift between duplicate copies fails the build: Internal maintainability (ROG-943 drift-sweep). Several constants exist as hand-mirrored copies across the sim, UI, and runtime layers with only weak (or no) tests, so the copies could silently diverge. Added guards so drift fails the build: full-table equality for the runtime vs canonical PROFICIENCY_SCALING_ATTRIBUTE (ROG-979); an intersection parity guard between the player-facing armed-glow counter thresholds and the sim threshold specs (ROG-977); and structural invariants plus provenance breadcrumbs for the arena recommended-level-by-act table vs the XP schedule (ROG-978). No player-facing change.
  • Internal maintainability pass — single-sourced duplicated constants and hardened combat-save restore (no manual-play change): Maintainability hardening (ROG-943/980). Several values that were hand-copied across files are now defined once and shared (joint-status counter IDs, the Barbarian discipline stances, the combat-log tone set, the fnv1a32 seed hash, and the XP curve), so they can no longer silently drift apart. Achievement-unlock evaluation used during profile migration was aligned to the canonical rule, and resumed combats now backfill any fields that a save predates, so older saves restore cleanly. These are internal correctness/robustness changes; normal play is unaffected.
  • Server ignores + self-removes a stale read-only maintenance flag so a crashed deploy can't wedge the host: Internal ops hardening (ROG-1006). The server's read-only maintenance guard now ignores and self-removes a maintenance.flag older than 30 minutes (configurable via ROUGE_MAINTENANCE_MAX_AGE_MS). Previously a flag left behind by a crashed or killed deploy would keep every write returning 503 on that host until someone manually cleared it. The threshold stays well beyond the real deploy read-only window (~1–3 min) so it never fires mid-deploy. No player-facing change.
  • Autoplay/sim now value a mercenary's aura and behavior fit when hiring (no manual-play change): The in-game autoplay and the balance sim now judge a mercenary contract by how well its aura and behavior fit the current deck, not by raw attack and life alone — so a merc whose aura is live for your build is preferred over one whose aura is dead for it. Manual play is unaffected.
  • Faster autoplay/sim decisions: memoized card-tree and base-card-id lookups (no gameplay change): Internal performance pass for autoplay and simulation: repeated card-tree and base-card-id lookups are cached and reused during decision scoring. Gameplay decisions remain the same, but larger sim and planner runs spend less time recomputing static card metadata.
  • Sim diagnostic to measure whether the pilot needs foresight terms for enemy traits (no gameplay change): Adds an internal balance-sim diagnostic (trait-injection-ab) that measures, per enemy trait, whether giving the auto-pilot a foresight term for it would change its decisions — via per-decision divergence plus a positive control — so we only add pilot logic where it demonstrably matters. All new scoring terms are diagnostic-only and off by default; manual and normal auto-play are unchanged.

Operations

  • Deploy Discord announcements: Deploys now attempt a once-per-version Discord patch-note announcement after the live server passes health checks, with a retry-safe ledger to avoid duplicate posts.
  • Add a dry-run workspace cleanup helper for local clutter.: Maintainers can now dry-run and apply safe local workspace cleanup for ignored scratch folders, empty agent worktree leftovers, and the stray :memory: SQLite file without hand-written deletion commands.

Angel Snack 0.1.0-alpha.2 Patch Notes

Release date: 2026-07-04

Stage: alpha

Package version: 0.1.0-alpha.2

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

UI

  • Added Terms, Privacy, and License pages to the front door.: Added front-door links to dedicated Terms of Service, Privacy Policy, and License pages so players can review alpha access terms, Discord bot terms and data-use notes, privacy choices, and the ISC source license from the shipped build.

Operations

  • Discord release bot: Added Discord bot tooling for patch-note announcements, slash-command registration, signed interaction handling, and allowlisted release/API status checks.
  • Discord bot help command: Added a /help slash command for RougeBot and documented why legacy !help prefix messages need a separate Gateway listener.

Angel Snack 0.1.0-alpha.1 Patch Notes

Release date: 2026-07-04

Stage: alpha

Package version: 0.1.0-alpha.1

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Fixes

  • Small charm cleanup: Removed duplicate small charms from the reward pool and made removed-charm rewards skip safely so old pending rewards cannot block a claim.

Operations

  • Agent release hygiene enforcement: Added an agent-facing release hygiene gate so release-relevant changes must include a patch-note artifact before test and deploy checks pass.
  • Release page and cut command: Added a generated public patch-notes page plus a one-command alpha release cut flow for publishing fragments and bumping the game version together.

Angel Snack 0.1.0-alpha.0 Patch Notes

Release date: 2026-07-04

Stage: alpha

Package version: 0.1.0-alpha.0

These notes are gathered from the release fragments in docs/patch-notes/unreleased/.

Operations

  • Patch notes and alpha versioning: Introduced package-level alpha semver, a repeatable fragment-based patch-note workflow, release publication commands, and a first published patch-note index for future alpha builds.