May 04, 9-10 AM (43)
May 04, 10-11 AM (36)
May 04, 11-12 PM (61)
May 04, 12-1 PM (34)
May 04, 1-2 PM (49)
May 04, 2-3 PM (64)
May 04, 3-4 PM (33)
May 04, 4-5 PM (64)
May 04, 5-6 PM (49)
May 04, 6-7 PM (13)
May 04, 7-8 PM (32)
May 04, 8-9 PM (45)
May 04, 9-10 PM (9)
May 04, 10-11 PM (54)
May 04, 11-12 AM (24)
May 05, 12-1 AM (4)
May 05, 1-2 AM (5)
May 05, 2-3 AM (5)
May 05, 3-4 AM (11)
May 05, 4-5 AM (11)
May 05, 5-6 AM (50)
May 05, 6-7 AM (16)
May 05, 7-8 AM (37)
May 05, 8-9 AM (81)
May 05, 9-10 AM (68)
May 05, 10-11 AM (34)
May 05, 11-12 PM (72)
May 05, 12-1 PM (115)
May 05, 1-2 PM (118)
May 05, 2-3 PM (66)
May 05, 3-4 PM (91)
May 05, 4-5 PM (41)
May 05, 5-6 PM (26)
May 05, 6-7 PM (28)
May 05, 7-8 PM (73)
May 05, 8-9 PM (31)
May 05, 9-10 PM (18)
May 05, 10-11 PM (25)
May 05, 11-12 AM (17)
May 06, 12-1 AM (10)
May 06, 1-2 AM (5)
May 06, 2-3 AM (9)
May 06, 3-4 AM (23)
May 06, 4-5 AM (7)
May 06, 5-6 AM (13)
May 06, 6-7 AM (30)
May 06, 7-8 AM (11)
May 06, 8-9 AM (106)
May 06, 9-10 AM (27)
May 06, 10-11 AM (41)
May 06, 11-12 PM (46)
May 06, 12-1 PM (86)
May 06, 1-2 PM (53)
May 06, 2-3 PM (43)
May 06, 3-4 PM (33)
May 06, 4-5 PM (18)
May 06, 5-6 PM (8)
May 06, 6-7 PM (12)
May 06, 7-8 PM (26)
May 06, 8-9 PM (13)
May 06, 9-10 PM (9)
May 06, 10-11 PM (30)
May 06, 11-12 AM (23)
May 07, 12-1 AM (7)
May 07, 1-2 AM (2)
May 07, 2-3 AM (1)
May 07, 3-4 AM (10)
May 07, 4-5 AM (4)
May 07, 5-6 AM (33)
May 07, 6-7 AM (97)
May 07, 7-8 AM (235)
May 07, 8-9 AM (42)
May 07, 9-10 AM (29)
May 07, 10-11 AM (55)
May 07, 11-12 PM (39)
May 07, 12-1 PM (59)
May 07, 1-2 PM (48)
May 07, 2-3 PM (47)
May 07, 3-4 PM (44)
May 07, 4-5 PM (58)
May 07, 5-6 PM (10)
May 07, 6-7 PM (24)
May 07, 7-8 PM (30)
May 07, 8-9 PM (12)
May 07, 9-10 PM (18)
May 07, 10-11 PM (65)
May 07, 11-12 AM (20)
May 08, 12-1 AM (6)
May 08, 1-2 AM (19)
May 08, 2-3 AM (19)
May 08, 3-4 AM (8)
May 08, 4-5 AM (3)
May 08, 5-6 AM (20)
May 08, 6-7 AM (19)
May 08, 7-8 AM (53)
May 08, 8-9 AM (34)
May 08, 9-10 AM (12)
May 08, 10-11 AM (32)
May 08, 11-12 PM (40)
May 08, 12-1 PM (30)
May 08, 1-2 PM (45)
May 08, 2-3 PM (46)
May 08, 3-4 PM (26)
May 08, 4-5 PM (23)
May 08, 5-6 PM (29)
May 08, 6-7 PM (15)
May 08, 7-8 PM (10)
May 08, 8-9 PM (14)
May 08, 9-10 PM (16)
May 08, 10-11 PM (23)
May 08, 11-12 AM (12)
May 09, 12-1 AM (4)
May 09, 1-2 AM (1)
May 09, 2-3 AM (0)
May 09, 3-4 AM (6)
May 09, 4-5 AM (6)
May 09, 5-6 AM (2)
May 09, 6-7 AM (6)
May 09, 7-8 AM (4)
May 09, 8-9 AM (4)
May 09, 9-10 AM (3)
May 09, 10-11 AM (9)
May 09, 11-12 PM (6)
May 09, 12-1 PM (21)
May 09, 1-2 PM (24)
May 09, 2-3 PM (12)
May 09, 3-4 PM (14)
May 09, 4-5 PM (7)
May 09, 5-6 PM (0)
May 09, 6-7 PM (2)
May 09, 7-8 PM (3)
May 09, 8-9 PM (1)
May 09, 9-10 PM (8)
May 09, 10-11 PM (33)
May 09, 11-12 AM (16)
May 10, 12-1 AM (15)
May 10, 1-2 AM (0)
May 10, 2-3 AM (0)
May 10, 3-4 AM (5)
May 10, 4-5 AM (0)
May 10, 5-6 AM (4)
May 10, 6-7 AM (0)
May 10, 7-8 AM (17)
May 10, 8-9 AM (8)
May 10, 9-10 AM (1)
May 10, 10-11 AM (26)
May 10, 11-12 PM (4)
May 10, 12-1 PM (49)
May 10, 1-2 PM (18)
May 10, 2-3 PM (8)
May 10, 3-4 PM (13)
May 10, 4-5 PM (26)
May 10, 5-6 PM (10)
May 10, 6-7 PM (7)
May 10, 7-8 PM (23)
May 10, 8-9 PM (12)
May 10, 9-10 PM (10)
May 10, 10-11 PM (29)
May 10, 11-12 AM (19)
May 11, 12-1 AM (12)
May 11, 1-2 AM (5)
May 11, 2-3 AM (5)
May 11, 3-4 AM (7)
May 11, 4-5 AM (3)
May 11, 5-6 AM (12)
May 11, 6-7 AM (28)
May 11, 7-8 AM (60)
May 11, 8-9 AM (32)
May 11, 9-10 AM (8)
4,531 commits this week May 04, 2026 - May 11, 2026
fix(release): require manual publish for real releases
Stop auto-promoting nightly/test runs to GitHub's "Latest" pointer and
stop auto-undrafting real releases before notes are reviewed.

release.yml changes:
- gh release create passes --prerelease for nightly/test, so the GitHub
  API "Latest" lookup keeps following the most recent semver release
  instead of switching to nightly every night.
- publish-release auto-un-drafts only for nightly/test. For real
  releases it logs a notice and leaves the draft in place; the
  maintainer edits notes (Docker link, changelog, signatures) and
  clicks Publish in the GitHub UI.
- push-docker is skipped on the release path; the new
  publish-release.yml handles the version + latest docker push.
- update-docs is removed from release.yml; same new workflow handles
  the gh-pages redirect on release.published.

New .github/workflows/publish-release.yml:
- Triggered on release.published (filter: not prerelease).
- Downloads the docker-image asset from the release, pushes
  cardanofoundation/cardano-wallet:<tag> and :latest to Docker Hub.
- Runs releases/make_redirects.sh on gh-pages with the release tag.
chore(asteria-game): rename composer/stub β†’ composer/asteria-game (drop stale label)
Closes #144.

The directory was lifted verbatim from components/asteria-stub/ in
fbb8982 ("asteria-game: testnet split + lift PR #67 source +
idempotent bootstrap (#100)") when the real asteria-game implementation
arrived. The "stub" label stuck despite the scripts inside no longer
being placeholders β€” they are the canonical drivers for heartbeat,
alive probes, asteria bootstrap / player / consistency / admin
singleton, plus their SDK observability.

The rest of the repo follows <component>/composer/<purpose>/:
  components/adversary/composer/chain-sync-client/  ← descriptive
  components/tx-generator/composer/tx-generator/    ← descriptive
  components/asteria-game/composer/stub/            ← stale (was)

This PR fixes that. The label was leaking into the Antithesis
report β€” every finding showed up as `stub/parallel_driver_X.sh` and
every assertion as `stub heartbeat ticked` etc. β€” which read as
"placeholder code being flaky" rather than "real driver". That
misreading actually happened during triage of #142.

Changes:
- git mv components/asteria-game/composer/stub
       components/asteria-game/composer/asteria-game
- All SDK assertion IDs in the renamed scripts: drop the "stub "
  prefix β†’ "asteria_game " (matching tx-generator's snake_case
  component-prefix convention). 21 assertion IDs across 7 scripts.
- Prose comments in the renamed scripts: "stub script" / "sibling
  stubs" β†’ plain wording, since the rename makes the original
  framing wrong.
- Path references in:
    docs/components/asteria-player.md
    docs/testnets/cardano-node-master.md
    testnets/cardano_node_master/docker-compose.yaml
    testnets/cardano_node_adversary/docker-compose.yaml
    testnets/asteria_game/docker-compose.yaml
  all updated for /opt/antithesis/test/v1/asteria-game/ and the
  source dir.

components/asteria-stub/ (the legacy component with the un-bounded
socat reference baseline) is left untouched.

Antithesis identity reset:
- composer commands: now identified as
  asteria-game/parallel_driver_heartbeat.sh etc., distinct from the
  archived stub/* identities. History bar restarts for these.
- SDK assertions: same β€” asteria_game heartbeat ticked is a fresh
  identity vs the archived stub heartbeat ticked.
- One-time cost; the payoff is permanently readable triage output.

Local smoke (renamed paths):
- 10 concurrent shells Γ— 5 emits β†’ 50 valid JSON lines
- SIGTERM mid-sleep β†’ exit 0 with trap-emitted observation
- timeout --kill-after=2 escalation β†’ exit 137 β†’ absorbed
fix(asteria-game): add --kill-after=2 to all stub timeout-wrapped binaries
Closes #145.

After #143 landed, six of seven previously-failing stubs went green
on the first post-merge cron of 8690faa, but
stub/parallel_driver_asteria_player.sh still tripped the
Always:zero-exit-code property with one new finding (3h 19m run,
faults on). Decoded examples:

  example 1  fail  rc=1  runtime 27.27 s
  example 2  fail  rc=1  runtime 28.65 s
  example 3  fail  rc=1  runtime 47.31 s
  example 4  pass  rc=0  runtime  3.02 s

The wrapper is `sdk_run_signal_safe ... timeout 12 /bin/asteria-game`.
Plain `timeout 12` sends SIGTERM at the 12 s deadline but does not
escalate to SIGKILL β€” that requires --kill-after. The Haskell
binary catches SIGTERM, runs slow N2C cleanup that fails on a
torn socket, then exits rc=1 (Haskell default unhandled-exception
code). sdk_run_signal_safe deliberately propagates non-signal
exits so the property fires.

Adding --kill-after=2 escalates to SIGKILL 2 s after SIGTERM. The
kernel-killed exit (137) is in sdk_run_signal_safe's absorb set
along with 124/129/143/255, so the script terminates deterministically
inside (deadline + 2) seconds and the property stays green.

Same shape on three sibling stubs that haven't tripped yet but
have the same wrapper pattern; fixed all four together to match
the failure mode rather than the run-by-run symptom:

  parallel_driver_asteria_player.sh   timeout 12 β†’ --kill-after=2 12
  anytime_asteria_admin_singleton.sh  timeout 12 β†’ --kill-after=2 12
  finally_asteria_consistency.sh      timeout 30 β†’ --kill-after=2 30
  serial_driver_asteria_bootstrap.sh  timeout 25 β†’ --kill-after=2 25

Local smoke (process that catches SIGTERM and runs slow cleanup):
  - plain timeout 1   β†’ exit 124 sometimes, child rc otherwise (leaky)
  - --kill-after=2 1  β†’ exit 137 reliably

No semantic change for healthy runs; failure path now terminates
predictably and is absorbed.
Merge commit from fork
* Add test that demonstrates issue

* Final fixes

* Further bugs identified and fixes applied

* Further fixes

* Last fixes

* Last last fixes

* Abstract away ST token name

* Re-word some code-comments, test names

* Trace HeadOutputNotFound (D08) on missing head continuation

  Replace `expect Some(head_output) = list.find(outputs, has_ST(head_id))`
  inside `deposit_value_flows_to_head` with a `when … is` match. A tx that
  consumes a deposit without producing a head continuation (e.g. a Fanout-
  shape, or any malformed Increment) now logs an explicit `D08 /
  HeadOutputNotFound` followed by the wrapping `D07 /
  DepositValueNotInHead`, instead of aborting the script with an opaque
  `expect` failure trace.

  No behavioural change for honest Increments: a legitimate Increment
  always produces a head output, so the new `Some(head_output)` branch
  is the only one taken in the happy path.

* Use builtin.un_constr_data instead of mirror type

  Drop the HeadStateMarker type from deposit.ak and replace the
  `expect head_state: HeadStateMarker = d` decode + match in
  `head_output_is_open` with a direct
  `builtin.un_constr_data(d).1st == 0` check.

  The marker type only existed so the `expect` would succeed for any of
  the three legitimate State variants (Open / Closed / Final); we never
  constructed values of the Closed/Final variants ourselves, which is why
  Aiken kept warning that they were unused. Reading the constructor index
  directly captures the only thing we actually care about (variant 0 ==
  Open) and makes the positional-encoding dependency explicit at the call
  site instead of hiding it in a fake type.

  No behavioural change: a head_output whose datum is Closed or Final
  still returns False (and the wrapping D07 trace fires); a non-Constr
  inline datum still aborts the script (rare in practice and identical to
  the previous behaviour).

* Squash head_is_spent into deposit_value_flows_to_head

  `head_is_spent` and `deposit_value_flows_to_head`'s `head_input` lookup
  both walked the input list searching for the head's ST UTxO. The
  former returned a Bool used solely to gate the D06 trace; the latter
  re-found the same input via `expect Some(...)`. Collapse them: a single
  `when list.find(inputs, has_ST) is None -> trace D06 + False / Some(h)
  -> ...` lookup inside `deposit_value_flows_to_head` does both jobs.

  D06 still fires when the head ST input is missing (now from inside the
  function instead of from a standalone clause); D07 still wraps the
  whole check; D08 still fires on a missing head output. Behaviour is
  unchanged for honest and adversarial txs alike.

* Refresh plutus.json + script goldens, drop stale head_is_spent comments

* Hoist deposit value-flow check into checkIncrement

  The value equation -- "head_in + Ξ£ deposit values == head_out" -- used
  to live in the deposit validator's deposit_value_flows_to_head. Each
  spending v_deposit input ran it independently. Now the head validator's
  checkIncrement runs it once, parameterised by the v_deposit script hash
  so it can identify deposit-script inputs by address credential.

  Motivation: stop running the same equation N times in a multi-deposit
  tx, and lay groundwork for off-chain batch deposits.

* Tidy deposit-security comments; drop before/after-fix framing

* Add mutation tests

* Drop redundant module header, rename attacker

* Tighten exception checks in SecurityScenarios

* Assemble a mutation for ingesting a wrong deposit input

* PR review

* Additional deposit-stealing increment test

* Enforce that all script inputs contribute to head value in Increment

  Every script input's value must be absorbed into the head output, so an attacker
  cannot smuggle an extra deposit input and redirect its value.

* Further fixes and PR feedback

* Check the redeemer in the deposit script

Now you can only claim a deposit during increment.

* Update scripts

* Changelog

---------

Co-authored-by: Sasha Bogicevic <[email protected]>