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 (49)
Apr 28, 1-2 PM (53)
Apr 28, 2-3 PM (68)
Apr 28, 3-4 PM (31)
Apr 28, 4-5 PM (14)
Apr 28, 5-6 PM (47)
Apr 28, 6-7 PM (9)
Apr 28, 7-8 PM (9)
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 (39)
Apr 29, 1-2 PM (21)
Apr 29, 2-3 PM (66)
Apr 29, 3-4 PM (25)
Apr 29, 4-5 PM (36)
Apr 29, 5-6 PM (16)
Apr 29, 6-7 PM (10)
Apr 29, 7-8 PM (14)
Apr 29, 8-9 PM (13)
Apr 29, 9-10 PM (17)
Apr 29, 10-11 PM (25)
Apr 29, 11-12 AM (29)
Apr 30, 12-1 AM (6)
Apr 30, 1-2 AM (8)
Apr 30, 2-3 AM (1)
Apr 30, 3-4 AM (6)
Apr 30, 4-5 AM (2)
Apr 30, 5-6 AM (8)
Apr 30, 6-7 AM (14)
Apr 30, 7-8 AM (5)
3,745 commits this week Apr 23, 2026 - Apr 30, 2026
chore(tx-generator): bump pin to upstream 4fca187 (CI-green)
* Bump cardano-node-clients flake input from 2714a2f
  (pre-lint-fix) to 4fca187, the current green head of
  https://github.com/lambdasistemi/cardano-node-clients/pull/94.
* nix flake update cardano-node-clients regenerated the
  lockfile.
* docker-compose tag bumped to match the freshly-built
  image: 9f91d6f-dirty.

Locally re-validated end-to-end on the cluster:
* Refill landed (txId 5a9bef34..., 5000 ADA at addr_0,
  awaited=false due to chain-sync catch-up race).
* After 30 s of chain-sync settle: snapshot shows
  populationSize=1, p50=5000 ADA.
* Next transact succeeded (src=0, fresh_count=3,
  dsts=[1,2,0,3], values_lovelace summing to ~2.7 ADA).

The transient "no-pickable-source" responses while the
indexer catches up to a freshly-submitted tx are the
documented eventual-consistency behavior; the composer's
exit-1-on-not-applicable pattern absorbs them.
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.
ci(smoke): chain smoke-test inside publish-images
Move the compose smoke-test from a `workflow_run`-
triggered side workflow to a `needs: publish-images` job
inside publish-images.yaml. The previous wiring fired in
its own check suite, decoupled from the PR's check suite,
so a PR could merge "all green" while the smoke-test was
still queued, in-flight, or had just failed silently.

With the smoke-test as a downstream job in the same
workflow, its conclusion rolls up to the PR's required
checks: a smoke-test failure now blocks merge.

The standalone smoke-test.yaml is kept as the manual
re-run escape hatch via workflow_dispatch (against an
arbitrary ref, without rebuilding images), with the
duplicate workflow_run trigger removed.
test(smoke): cover tx-generator end-to-end in CI
Extend scripts/smoke-test.sh past the cardano-cli ping +
sidecar-convergence checks to drive the tx-generator
daemon through its core contract:

* Wait for the control socket to bind under
  /state/tx-generator-control.sock.
* Probe `{"ready":null}` until the indexer + faucet
  detection both flip true.
* Drive one parallel_driver_refill via docker exec.
* Poll `{"snapshot":null}` until the indexer observes the
  refill (populationSize > 0).
* Drive 5 parallel_driver_transact bursts; tolerate
  no-pickable-source / index-not-ready exits as the
  composer does.
* Final snapshot must show populationSize >= 2 and at
  least one transact landed.

The same scripts are what the Antithesis composer drives
at much heavier load on the cluster; this gives us a CI
gate that catches breakage before the Antithesis-side run.

Triggered via .github/workflows/smoke-test.yaml after
publish-images succeeds.
fix(tx-generator): use netcat-openbsd, not netcat-gnu
netcat-gnu does not support `-U` (unix domain socket connect)
which is what the composer driver scripts use to talk to the
daemon's control socket. netcat-openbsd is the standard `nc`
implementation used by the asteria-player composer scripts and
elsewhere.

Smoke-tested: `docker run --rm --entrypoint /bin/parallel_driver_transact
<image>` now reaches the connect step (failing only on the
missing socket, which is expected without a daemon).
chore(tx-generator): repoint pin to upstream main (post-#94)
cardano-node-clients pull/94 merged at
0581418362 (T022 starvation E2E commit). Per the
*pins-main-only* rule, downstream pins on the main path
must point at a commit on upstream main, never at a
feature-branch tip.

The narHash on 0581418362 matches 4fca187eac (the previous
branch-tip pin) — the merge was a fast-forward of the
already-CI-green head, no source delta. No rebuild needed
on the Cachix path.
feat(tx-generator): wire compose to new image + TextEnvelope-aware entrypoint
* entrypoint.sh: convert the cluster's TextEnvelope-shaped
  faucet skey (genesis.N.skey) to the 32-byte raw seed the
  daemon expects, then exec the binary. Reads cborHex,
  strips the 5820 prefix, decodes hex via xxd. Writes to
  /state/faucet-raw.skey (the daemon's rw mount); /tmp is
  not pre-created in dockerTools.buildImage rootfs.

* nix/docker-image.nix: add the wrapper as ENTRYPOINT,
  switch to netcat-openbsd (netcat-gnu has no -U), include
  unixtools.xxd for hex decoding.

* docker-compose.yaml: replace the python tx-generator
  with the new daemon image, switch /state mount from :ro
  to rw (daemon writes its control socket there), pass
  CLI flags via command:, point --faucet-skey-file at
  /utxo-keys/genesis.1.skey (configurator's output).
  Add depends_on configurator: service_completed_successfully
  so the keys exist before the daemon reads them.

Locally verified end-to-end on the cluster:
* Refill: 0 → 1 population, 5000 ADA at addr_0.
* 10 K=6 transacts: 36 addresses, p50 dropped 5000 → 20 ADA.
* 51 K=8 transacts: 250 addresses, p90 14 ADA, p50 3.47 ADA.
* Starvation contract: when fragmentation crossed the
  viability floor, daemon returned
  {"ok":false,"reason":"no-pickable-source"} and
  stayed alive — verified ready=true after the dust drain.

Refs: cardano-foundation/cardano-node-antithesis#78
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.
feat(tx-generator): replace python with nix-built haskell daemon image
Replaces components/tx-generator/{Dockerfile,requirements.txt,
tx_generator.py} (the per-submission `cardano-cli query utxo
--address` self-saturating Python — see
cardano-foundation/cardano-node-antithesis#69) with a thin
Nix-built docker image around the Haskell cardano-tx-generator
daemon from lambdasistemi/cardano-node-clients#94.

Layout mirrors components/asteria-player:

- flake.nix pulls cardano-node-clients as input and exposes
  packages.docker-image + packages.tx-generator-bin + version.
- nix/docker-image.nix builds an OCI image with the binary's
  full nix closure plus the composer scripts baked under
  /opt/antithesis/test/v1/tx-generator/.
- composer/tx-generator/{parallel_driver_transact,
  parallel_driver_refill,eventually_population_grew,
  finally_pressure_summary}.sh — driver scripts that speak the
  daemon's NDJSON wire over its control socket via nc -U.
- helper_sdk_lib.sh copied verbatim from
  components/asteria-player/composer/asteria.

Compose update (testnets/cardano_node_master/docker-compose.yaml)
lands in a follow-up commit once publish-images.yaml has resolved
a real tag for the new image.

Refs: cardano-foundation/cardano-node-antithesis#78
Refs: cardano-foundation/cardano-node-antithesis#69
chore(tx-generator): bump compose tag to cd750e8
Replace the local-build :9f91d6f-dirty placeholder with the
real commit SHA cd750e8. publish-images.yaml resolves the
tag via `git rev-list -n 1`, so the tag must be a real
commit on the branch — `-dirty` tags can't be resolved and
were only ever valid on developer workstations.

cd750e8 is the pin-bump commit that wires the cluster to
upstream cardano-node-clients @ 4fca187 (CI-green head of
PR #94). publish-images will check out cd750e8 and build
components/tx-generator/.#docker-image at that source.