Apr 22, 2-3 PM (44)
Apr 22, 3-4 PM (86)
Apr 22, 4-5 PM (46)
Apr 22, 5-6 PM (17)
Apr 22, 6-7 PM (10)
Apr 22, 7-8 PM (18)
Apr 22, 8-9 PM (15)
Apr 22, 9-10 PM (23)
Apr 22, 10-11 PM (31)
Apr 22, 11-12 AM (17)
Apr 23, 12-1 AM (7)
Apr 23, 1-2 AM (4)
Apr 23, 2-3 AM (4)
Apr 23, 3-4 AM (6)
Apr 23, 4-5 AM (3)
Apr 23, 5-6 AM (8)
Apr 23, 6-7 AM (17)
Apr 23, 7-8 AM (26)
Apr 23, 8-9 AM (33)
Apr 23, 9-10 AM (33)
Apr 23, 10-11 AM (29)
Apr 23, 11-12 PM (30)
Apr 23, 12-1 PM (51)
Apr 23, 1-2 PM (69)
Apr 23, 2-3 PM (74)
Apr 23, 3-4 PM (26)
Apr 23, 4-5 PM (22)
Apr 23, 5-6 PM (7)
Apr 23, 6-7 PM (7)
Apr 23, 7-8 PM (11)
Apr 23, 8-9 PM (14)
Apr 23, 9-10 PM (6)
Apr 23, 10-11 PM (28)
Apr 23, 11-12 AM (18)
Apr 24, 12-1 AM (7)
Apr 24, 1-2 AM (4)
Apr 24, 2-3 AM (7)
Apr 24, 3-4 AM (5)
Apr 24, 4-5 AM (8)
Apr 24, 5-6 AM (13)
Apr 24, 6-7 AM (12)
Apr 24, 7-8 AM (33)
Apr 24, 8-9 AM (40)
Apr 24, 9-10 AM (41)
Apr 24, 10-11 AM (72)
Apr 24, 11-12 PM (57)
Apr 24, 12-1 PM (100)
Apr 24, 1-2 PM (57)
Apr 24, 2-3 PM (35)
Apr 24, 3-4 PM (19)
Apr 24, 4-5 PM (16)
Apr 24, 5-6 PM (38)
Apr 24, 6-7 PM (27)
Apr 24, 7-8 PM (12)
Apr 24, 8-9 PM (42)
Apr 24, 9-10 PM (17)
Apr 24, 10-11 PM (30)
Apr 24, 11-12 AM (16)
Apr 25, 12-1 AM (8)
Apr 25, 1-2 AM (1)
Apr 25, 2-3 AM (10)
Apr 25, 3-4 AM (5)
Apr 25, 4-5 AM (3)
Apr 25, 5-6 AM (13)
Apr 25, 6-7 AM (1)
Apr 25, 7-8 AM (4)
Apr 25, 8-9 AM (24)
Apr 25, 9-10 AM (17)
Apr 25, 10-11 AM (4)
Apr 25, 11-12 PM (4)
Apr 25, 12-1 PM (13)
Apr 25, 1-2 PM (3)
Apr 25, 2-3 PM (10)
Apr 25, 3-4 PM (6)
Apr 25, 4-5 PM (10)
Apr 25, 5-6 PM (16)
Apr 25, 6-7 PM (13)
Apr 25, 7-8 PM (30)
Apr 25, 8-9 PM (55)
Apr 25, 9-10 PM (13)
Apr 25, 10-11 PM (21)
Apr 25, 11-12 AM (22)
Apr 26, 12-1 AM (5)
Apr 26, 1-2 AM (0)
Apr 26, 2-3 AM (2)
Apr 26, 3-4 AM (5)
Apr 26, 4-5 AM (2)
Apr 26, 5-6 AM (2)
Apr 26, 6-7 AM (3)
Apr 26, 7-8 AM (8)
Apr 26, 8-9 AM (3)
Apr 26, 9-10 AM (0)
Apr 26, 10-11 AM (2)
Apr 26, 11-12 PM (1)
Apr 26, 12-1 PM (6)
Apr 26, 1-2 PM (4)
Apr 26, 2-3 PM (14)
Apr 26, 3-4 PM (14)
Apr 26, 4-5 PM (0)
Apr 26, 5-6 PM (13)
Apr 26, 6-7 PM (13)
Apr 26, 7-8 PM (7)
Apr 26, 8-9 PM (7)
Apr 26, 9-10 PM (5)
Apr 26, 10-11 PM (27)
Apr 26, 11-12 AM (21)
Apr 27, 12-1 AM (7)
Apr 27, 1-2 AM (7)
Apr 27, 2-3 AM (9)
Apr 27, 3-4 AM (9)
Apr 27, 4-5 AM (5)
Apr 27, 5-6 AM (13)
Apr 27, 6-7 AM (7)
Apr 27, 7-8 AM (82)
Apr 27, 8-9 AM (47)
Apr 27, 9-10 AM (33)
Apr 27, 10-11 AM (62)
Apr 27, 11-12 PM (80)
Apr 27, 12-1 PM (66)
Apr 27, 1-2 PM (44)
Apr 27, 2-3 PM (52)
Apr 27, 3-4 PM (42)
Apr 27, 4-5 PM (36)
Apr 27, 5-6 PM (26)
Apr 27, 6-7 PM (13)
Apr 27, 7-8 PM (26)
Apr 27, 8-9 PM (13)
Apr 27, 9-10 PM (15)
Apr 27, 10-11 PM (42)
Apr 27, 11-12 AM (28)
Apr 28, 12-1 AM (17)
Apr 28, 1-2 AM (8)
Apr 28, 2-3 AM (4)
Apr 28, 3-4 AM (5)
Apr 28, 4-5 AM (5)
Apr 28, 5-6 AM (8)
Apr 28, 6-7 AM (8)
Apr 28, 7-8 AM (37)
Apr 28, 8-9 AM (54)
Apr 28, 9-10 AM (59)
Apr 28, 10-11 AM (53)
Apr 28, 11-12 PM (56)
Apr 28, 12-1 PM (48)
Apr 28, 1-2 PM (53)
Apr 28, 2-3 PM (68)
Apr 28, 3-4 PM (31)
Apr 28, 4-5 PM (13)
Apr 28, 5-6 PM (47)
Apr 28, 6-7 PM (9)
Apr 28, 7-8 PM (8)
Apr 28, 8-9 PM (14)
Apr 28, 9-10 PM (20)
Apr 28, 10-11 PM (34)
Apr 28, 11-12 AM (29)
Apr 29, 12-1 AM (13)
Apr 29, 1-2 AM (1)
Apr 29, 2-3 AM (1)
Apr 29, 3-4 AM (6)
Apr 29, 4-5 AM (1)
Apr 29, 5-6 AM (4)
Apr 29, 6-7 AM (12)
Apr 29, 7-8 AM (45)
Apr 29, 8-9 AM (70)
Apr 29, 9-10 AM (49)
Apr 29, 10-11 AM (25)
Apr 29, 11-12 PM (50)
Apr 29, 12-1 PM (38)
Apr 29, 1-2 PM (21)
Apr 29, 2-3 PM (9)
3,789 commits this week Apr 22, 2026 - Apr 29, 2026
test(smoke): fail on jq stderr from composer drivers
Two strictness fixes after a CI run revealed the previous
gate would pass even when the composer driver emitted
"jq: invalid JSON text passed to --argjson" stderr noise:

* Wait for `p50_lovelace != null` instead of
  `populationSize > 0`. populationSize is the count of
  HD-derived addresses, which the refill code bumps on
  disk before the UTxO actually lands, so the previous
  check could green-light transacts before the indexer
  saw any UTxO. p50_lovelace stays null until the
  indexer observes a real UTxO.
* Capture stderr from each `parallel_driver_transact`
  invocation and grep for `^jq:`. The composer-side
  semantics treat exit 1 as "not applicable, retry next
  tick", so we keep tolerating non-zero exits — but a jq
  error on stderr means the driver itself crashed, and
  the smoke-test must surface that distinct from a
  legitimate not-applicable response.
fix(composer): build SDK details JSON via jq -n --arg
Both parallel_driver_transact.sh and parallel_driver_refill.sh
were piping the daemon's REASON field straight into
`printf '{"reason":"%s"}' "$REASON"` to construct the
Antithesis SDK assertion details. The daemon's
SubmitRejected reason carries the raw ledger error string
(see cardano-node-clients
lib/Cardano/Node/Client/TxGenerator/Types.hs:135), which
can contain `"` and `\\` characters. Injecting those raw
into a JSON literal produced malformed JSON, and
`helper_sdk_lib.sh:_sdk_emit` then tripped on
`jq --argjson details <broken>` and dumped
"jq: invalid JSON text passed to --argjson" on stderr.

The script's terminating `exit 1` still ran (intended
"not-applicable, retry next tick" semantics), so the
composer kept advancing — but the SDK telemetry event was
silently dropped and the stderr noise polluted CI logs.

Switch to `jq -nc --arg r "$REASON" '{reason:$r}'` for the
reason path and `jq -nc --arg r "$RSP" '{raw:$r}'` for the
unknown-failure path. jq handles the JSON escaping, so any
quote/backslash/control char inside the daemon response
survives the round-trip without breaking the SDK emitter.
asteria-stub: long-lived utxo-indexer + indexer-driven composer scripts
The asteria-stub container becomes the long-running chain-following
indexer. Its main process is upstream `utxo-indexer` from
lambdasistemi/cardano-node-clients (PR #94, branch
034-cardano-tx-generator at d80ab59f), pinned via a flake input and
baked into the image by `nix build .#docker-image`. The indexer
follows relay1's chain over N2C, persists state to RocksDB at
/idx-db, and exposes ready/utxos_at/await on /tmp/idx.sock.

Replaces the per-component Dockerfile + apt + cardano-cli setup
with a pure-nix build (flake.nix + nix/docker-image.nix). cardano-cli
is no longer needed in this image because composer scripts now query
the indexer's socket directly.

Composer scripts (kept in their stub shape):
  - parallel_driver_heartbeat.sh — pings indexer's `ready`,
    Sometimes-true on processedSlot==tipSlot
  - eventually_alive.sh — post-fault: same probe with retries
  - finally_alive.sh — post-workload: same probe with retries

Compose updates:
  - mount relay1-state:/state:ro so the indexer can reach
    relay1's N2C socket
  - add asteria-stub-db named volume for RocksDB persistence
  - restart: always — workaround for upstream issue
    https://github.com/lambdasistemi/cardano-node-clients/issues/97
    (indexer crashes when relay1 closes the N2C socket; resume
    from RocksDB on auto-restart). Will revert this hack once
    upstream auto-reconnect lands.
asteria-stub: long-lived utxo-indexer + indexer-driven composer scripts
The asteria-stub container becomes the long-running chain-following
indexer. Its main process is upstream `utxo-indexer` from
lambdasistemi/cardano-node-clients (PR #94, branch
034-cardano-tx-generator at d80ab59f), pinned via a flake input and
baked into the image by `nix build .#docker-image`. The indexer
follows relay1's chain over N2C, persists state to RocksDB at
/idx-db, and exposes ready/utxos_at/await on /tmp/idx.sock.

Replaces the per-component Dockerfile + apt + cardano-cli setup
with a pure-nix build (flake.nix + nix/docker-image.nix). cardano-cli
is no longer needed in this image because composer scripts now query
the indexer's socket directly.

Composer scripts (kept in their stub shape):
  - parallel_driver_heartbeat.sh — pings indexer's `ready`,
    Sometimes-true on processedSlot==tipSlot
  - eventually_alive.sh — post-fault: same probe with retries
  - finally_alive.sh — post-workload: same probe with retries

Compose updates:
  - mount relay1-state:/state:ro so the indexer can reach
    relay1's N2C socket
  - add asteria-stub-db named volume for RocksDB persistence
  - restart: always — workaround for upstream issue
    https://github.com/lambdasistemi/cardano-node-clients/issues/97
    (indexer crashes when relay1 closes the N2C socket; resume
    from RocksDB on auto-restart). Will revert this hack once
    upstream auto-reconnect lands.
feat(release-cli): add drt newsfeed subcommands
Adds three subcommands under `drt newsfeed`:

- `release` — fetches installer metadata from a URL, builds a
  software-update + announcement pair with pre-filled hashes/URLs and
  localised text, opens \$EDITOR for review, then writes the newsfeed
  JSON and verification file.  Release notes URL defaults to the GitHub
  release tag derived from the fetched version.
- `publish` — uploads the current newsfeed JSON and verification file
  to an S3 bucket for end-to-end testing (--dry-run supported).
- `message` — adds a standalone announcement item with a configurable
  version target.

Common repo/env args (--env, --newsfeed-repo, --verification-repo) are
shared via a flattened NewsfeedRepoArgs struct and read from NEWSFEED_*
environment variables.
feat(wal): version on-disk schema and force-reset on incompatibility
Adds a WAL_METADATA table to the redb WAL DB tracking a schema version,
checked at open(). Older or missing versions trigger a wipe-and-stamp;
newer versions return WalError::IncompatibleVersion to prevent an old
binary from destroying newer data. After a wipe, check_wal_in_sync_with_state
auto-reseeds the WAL from the state cursor (when fully defined) instead of
erroring, eliminating the manual `dolos doctor reset-wal` step.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>