Apr 19, 7-8 AM (2)
Apr 19, 8-9 AM (1)
Apr 19, 9-10 AM (1)
Apr 19, 10-11 AM (4)
Apr 19, 11-12 PM (7)
Apr 19, 12-1 PM (6)
Apr 19, 1-2 PM (8)
Apr 19, 2-3 PM (23)
Apr 19, 3-4 PM (7)
Apr 19, 4-5 PM (4)
Apr 19, 5-6 PM (3)
Apr 19, 6-7 PM (8)
Apr 19, 7-8 PM (3)
Apr 19, 8-9 PM (8)
Apr 19, 9-10 PM (6)
Apr 19, 10-11 PM (25)
Apr 19, 11-12 AM (23)
Apr 20, 12-1 AM (4)
Apr 20, 1-2 AM (5)
Apr 20, 2-3 AM (2)
Apr 20, 3-4 AM (7)
Apr 20, 4-5 AM (1)
Apr 20, 5-6 AM (8)
Apr 20, 6-7 AM (12)
Apr 20, 7-8 AM (29)
Apr 20, 8-9 AM (42)
Apr 20, 9-10 AM (37)
Apr 20, 10-11 AM (95)
Apr 20, 11-12 PM (42)
Apr 20, 12-1 PM (39)
Apr 20, 1-2 PM (53)
Apr 20, 2-3 PM (68)
Apr 20, 3-4 PM (47)
Apr 20, 4-5 PM (41)
Apr 20, 5-6 PM (31)
Apr 20, 6-7 PM (24)
Apr 20, 7-8 PM (10)
Apr 20, 8-9 PM (7)
Apr 20, 9-10 PM (16)
Apr 20, 10-11 PM (28)
Apr 20, 11-12 AM (18)
Apr 21, 12-1 AM (24)
Apr 21, 1-2 AM (5)
Apr 21, 2-3 AM (13)
Apr 21, 3-4 AM (4)
Apr 21, 4-5 AM (3)
Apr 21, 5-6 AM (8)
Apr 21, 6-7 AM (15)
Apr 21, 7-8 AM (44)
Apr 21, 8-9 AM (119)
Apr 21, 9-10 AM (36)
Apr 21, 10-11 AM (35)
Apr 21, 11-12 PM (98)
Apr 21, 12-1 PM (57)
Apr 21, 1-2 PM (71)
Apr 21, 2-3 PM (60)
Apr 21, 3-4 PM (33)
Apr 21, 4-5 PM (31)
Apr 21, 5-6 PM (27)
Apr 21, 6-7 PM (38)
Apr 21, 7-8 PM (35)
Apr 21, 8-9 PM (37)
Apr 21, 9-10 PM (14)
Apr 21, 10-11 PM (34)
Apr 21, 11-12 AM (12)
Apr 22, 12-1 AM (2)
Apr 22, 1-2 AM (3)
Apr 22, 2-3 AM (3)
Apr 22, 3-4 AM (4)
Apr 22, 4-5 AM (3)
Apr 22, 5-6 AM (17)
Apr 22, 6-7 AM (34)
Apr 22, 7-8 AM (21)
Apr 22, 8-9 AM (37)
Apr 22, 9-10 AM (18)
Apr 22, 10-11 AM (47)
Apr 22, 11-12 PM (45)
Apr 22, 12-1 PM (56)
Apr 22, 1-2 PM (64)
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 (65)
Apr 23, 3-4 PM (26)
Apr 23, 4-5 PM (21)
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 (71)
Apr 24, 11-12 PM (57)
Apr 24, 12-1 PM (37)
Apr 24, 1-2 PM (53)
Apr 24, 2-3 PM (34)
Apr 24, 3-4 PM (19)
Apr 24, 4-5 PM (16)
Apr 24, 5-6 PM (38)
Apr 24, 6-7 PM (26)
Apr 24, 7-8 PM (12)
Apr 24, 8-9 PM (41)
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 (12)
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 (12)
Apr 25, 7-8 PM (30)
Apr 25, 8-9 PM (55)
Apr 25, 9-10 PM (13)
Apr 25, 10-11 PM (20)
Apr 25, 11-12 AM (21)
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 (3)
3,801 commits this week Apr 19, 2026 - Apr 26, 2026
feat(asteria-player): player observes asteria + plans random moves (#56)
Iteration 6.

- src/Asteria/RandomSource.hs: pluggable randomness as a record-of-
  functions. newSystemSource seeds System.Random from the player's
  ASTERIA_PLAYER_ID hash so each replica has a distinct deterministic
  stream. randomInRange wraps getU64 with a modulo-based range draw.
  Iteration 7 will add a sibling implementation that subprocesses to
  Python's antithesis.random.get_random() so the hypervisor controls
  every decision; the consuming code is already abstracted over the
  RandomSource interface.

- app/PlayerMain.hs: replaces the pp-query loop with the asteria
  observation loop:
    1. queryUTxOs at the asteria spend address.
    2. emit asteria_player_asteria_observed_<id> sometimes(true/false)
       depending on whether the bootstrap-created UTxO is visible.
    3. decode the inline AsteriaDatum and emit
       asteria_player_ship_counter_<id> with the current ship_counter.
    4. draw a random (delta_x, delta_y) in [-5, 5] via randomInRange,
       emit asteria_player_move_planned_<id> with the deltas.
    5. sleep a random 1..5 seconds.

This proves discovery + decode + RandomSource end-to-end against the
running cluster. Iter 6b will replace step 4's plan with actually
building and submitting the mintShip / moveShip txs.

Verified:
  asteria_player_ship_counter_1 {"ship_counter": 0}
  asteria_player_move_planned_1 {"delta_x": 3, "delta_y": 4}
  asteria_player_ship_counter_2 {"ship_counter": 0}
  asteria_player_move_planned_2 {"delta_x": 0, "delta_y": -4}

Distinct deltas per replica per iteration confirm the seed-by-id
strategy is producing independent streams.
feat(asteria-player): player observes asteria + plans random moves (#56)
Iteration 6.

- src/Asteria/RandomSource.hs: pluggable randomness as a record-of-
  functions. newSystemSource seeds System.Random from the player's
  ASTERIA_PLAYER_ID hash so each replica has a distinct deterministic
  stream. randomInRange wraps getU64 with a modulo-based range draw.
  Iteration 7 will add a sibling implementation that subprocesses to
  Python's antithesis.random.get_random() so the hypervisor controls
  every decision; the consuming code is already abstracted over the
  RandomSource interface.

- app/PlayerMain.hs: replaces the pp-query loop with the asteria
  observation loop:
    1. queryUTxOs at the asteria spend address.
    2. emit asteria_player_asteria_observed_<id> sometimes(true/false)
       depending on whether the bootstrap-created UTxO is visible.
    3. decode the inline AsteriaDatum and emit
       asteria_player_ship_counter_<id> with the current ship_counter.
    4. draw a random (delta_x, delta_y) in [-5, 5] via randomInRange,
       emit asteria_player_move_planned_<id> with the deltas.
    5. sleep a random 1..5 seconds.

This proves discovery + decode + RandomSource end-to-end against the
running cluster. Iter 6b will replace step 4's plan with actually
building and submitting the mintShip / moveShip txs.

Verified:
  asteria_player_ship_counter_1 {"ship_counter": 0}
  asteria_player_move_planned_1 {"delta_x": 3, "delta_y": 4}
  asteria_player_ship_counter_2 {"ship_counter": 0}
  asteria_player_move_planned_2 {"delta_x": 0, "delta_y": -4}

Distinct deltas per replica per iteration confirm the seed-by-id
strategy is producing independent streams.
feat(asteria-player): bootstrap creates the asteria UTxO (#56)
Iteration 5b. The bootstrap binary now mints the asteria admin
NFT and locks it at the asteria spend address with the initial
inline AsteriaDatum — the on-chain "asteria UTxO" that the
move_ship / mine_asteria / consume_asteria validators reference.

- aiken/validators/admin_mint.ak: new always-true mint policy.
  Its hash is baked into admin_token by apply-params.sh so the
  four parameterized validators can reference it.
- aiken/apply-params.sh: computes admin_mint hash from the
  freshly-built plutus.json and uses it as admin_token's
  policy_id (was 28 zero bytes, now the real hash).
- aiken/plutus-applied.json: regenerated with the corrected
  admin_token. New hashes:
    pellet:     009080306c62ac5db9c4c04ca4eed6e6b567405c69c34049381824dc
    deploy:     4e2021af9fd97e24d9c0ae06c616ebcaa5f947b2ea5b643733467d3d
    asteria:    0824601a437559eb07d613f2cfb74bb87b2825b2f9b30e7a2ecb88e5
    spacetime:  dd1a2baf950b225d26208acc981dbdb93f7891e3d933c4a20590e31e
    admin_mint: def68337867cb4f1f95b6b811fedbfcdd7780d10a95cc072077088ea
- src/Asteria/Validators.hs: expose adminMintScript.
- src/Asteria/Crypto.hs: tiny helper that bridges
  cardano-crypto-class hashes to PlutusTx BuiltinByteString.
- src/Asteria/Datums.hs: AsteriaDatum, ShipDatum, PelletDatum,
  AsteriaRedeemer, ShipRedeemer, PelletRedeemer with ToData /
  FromData matching Aiken's encoding.
- app/BootstrapMain.hs: replace the no-op self-pay with the
  asteria-creation tx — spend genesis UTxO, attach admin_mint,
  mint 1 admin NFT, lock 5 ADA + admin NFT at the asteria spend
  address with inline AsteriaDatum {ship_counter=0,
  shipyard_policy=spacetime_hash}. Bumped wait timeout to 180s
  to cover cluster cold-start block-propagation latency.

Verified locally: docker compose up -d → asteria-bootstrap
exits 0, on-chain query confirms a UTxO at addr_test1wq...
with inline datum {ship_counter=0, shipyard_policy=dd1a2baf...}.
feat(asteria-player): bootstrap creates the asteria UTxO (#56)
Iteration 5b. The bootstrap binary now mints the asteria admin
NFT and locks it at the asteria spend address with the initial
inline AsteriaDatum — the on-chain "asteria UTxO" that the
move_ship / mine_asteria / consume_asteria validators reference.

- aiken/validators/admin_mint.ak: new always-true mint policy.
  Its hash is baked into admin_token by apply-params.sh so the
  four parameterized validators can reference it.
- aiken/apply-params.sh: computes admin_mint hash from the
  freshly-built plutus.json and uses it as admin_token's
  policy_id (was 28 zero bytes, now the real hash).
- aiken/plutus-applied.json: regenerated with the corrected
  admin_token. New hashes:
    pellet:     009080306c62ac5db9c4c04ca4eed6e6b567405c69c34049381824dc
    deploy:     4e2021af9fd97e24d9c0ae06c616ebcaa5f947b2ea5b643733467d3d
    asteria:    0824601a437559eb07d613f2cfb74bb87b2825b2f9b30e7a2ecb88e5
    spacetime:  dd1a2baf950b225d26208acc981dbdb93f7891e3d933c4a20590e31e
    admin_mint: def68337867cb4f1f95b6b811fedbfcdd7780d10a95cc072077088ea
- src/Asteria/Validators.hs: expose adminMintScript.
- src/Asteria/Crypto.hs: tiny helper that bridges
  cardano-crypto-class hashes to PlutusTx BuiltinByteString.
- src/Asteria/Datums.hs: AsteriaDatum, ShipDatum, PelletDatum,
  AsteriaRedeemer, ShipRedeemer, PelletRedeemer with ToData /
  FromData matching Aiken's encoding.
- app/BootstrapMain.hs: replace the no-op self-pay with the
  asteria-creation tx — spend genesis UTxO, attach admin_mint,
  mint 1 admin NFT, lock 5 ADA + admin NFT at the asteria spend
  address with inline AsteriaDatum {ship_counter=0,
  shipyard_policy=spacetime_hash}. Bumped wait timeout to 180s
  to cover cluster cold-start block-propagation latency.

Verified locally: docker compose up -d → asteria-bootstrap
exits 0, on-chain query confirms a UTxO at addr_test1wq...
with inline datum {ship_counter=0, shipyard_policy=dd1a2baf...}.
chore(nix): update `flake.lock`
Flake lock file updates:

• Updated input 'advisory-db':
    'github:rustsec/advisory-db/f9b2158' (2026-04-17)
  → 'github:rustsec/advisory-db/930c3aa' (2026-04-25)
• Updated input 'blockfrost-tests':
    'github:blockfrost/blockfrost-tests/3bedc5f' (2026-04-14)
  → 'github:blockfrost/blockfrost-tests/ee42a8a' (2026-04-24)
• Updated input 'crane':
    'github:ipetkov/crane/e24d86e' (2026-04-18)
  → 'github:ipetkov/crane/60c8293' (2026-04-25)
• Updated input 'fenix':
    'github:nix-community/fenix/df22953' (2026-04-18)
  → 'github:nix-community/fenix/f374034' (2026-04-25)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/251df51' (2026-04-17)
  → 'github:rust-lang/rust-analyzer/8954b66' (2026-04-21)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/e07580d' (2026-04-19)
  → 'github:nixos/nixpkgs/10e7ad5' (2026-04-21)
fix(mithril): correct snapshot-converter args and finalizing diagnostics
Fix snapshot-converter invocation to properly replace the in-memory ledger
snapshot with an LSM one: move the in-memory snapshot out of ledger/ to a
temp location, then run converter with --input-mem pointing to the temp path
and --output-lsm-snapshot as a full path back into ledger/<slot>, so
cardano-node finds an LSM-format snapshot at the expected location.

Also fix --output-lsm-database (was pointing into a non-existent tmp/snapshots
subdir, now uses dbDirectory/lsm) and --config (was constructing a path that
doesn't exist, now uses launcherConfig.nodeConfig.network.configFile).

Add stdinInput support to runBinary and diagnostic logger.info calls around
each async step in the finalizing phase to pinpoint any future hangs.
fix(darwin): bundle .so files into binary-lib subdirs alongside .dylib
moveDylibsToSubdir was only handling *.dylib, causing liblmdb.so
(introduced by cardano-node's UTxO-HD LSM support) to be left in
Contents/MacOS/ root while its install name was already patched to
@executable_path/cardano-node-lib/liblmdb.so, resulting in a dyld
load failure at runtime.
flake.lock: Update
Flake lock file updates:

• Updated input 'haskell-nix':
    'github:input-output-hk/haskell.nix/cad2645' (2026-01-03)
  → 'github:input-output-hk/haskell.nix/3328b9a' (2026-04-25)
• Removed input 'haskell-nix/cabal-32'
• Updated input 'haskell-nix/hackage':
    'github:input-output-hk/hackage.nix/05797dd' (2026-01-03)
  → 'github:input-output-hk/hackage.nix/39467ed' (2026-04-25)
• Updated input 'haskell-nix/hackage-for-stackage':
    'github:input-output-hk/hackage.nix/fba3874' (2026-01-03)
  → 'github:input-output-hk/hackage.nix/c32368d' (2026-04-25)
• Added input 'haskell-nix/hls-2.12':
    'github:haskell/haskell-language-server/7d983de' (2025-09-24)
• Updated input 'haskell-nix/iserv-proxy':
    'github:stable-haskell/iserv-proxy/1506051' (2025-08-15)
  → 'github:stable-haskell/iserv-proxy/3f7b281' (2026-04-08)
• Updated input 'haskell-nix/nixpkgs-2511':
    'github:NixOS/nixpkgs/b0924ea' (2025-12-01)
  → 'github:NixOS/nixpkgs/74b8795' (2026-04-09)
• Updated input 'haskell-nix/nixpkgs-unstable':
    'github:NixOS/nixpkgs/c1cb7d0' (2025-12-01)
  → 'github:NixOS/nixpkgs/1304392' (2026-04-11)
• Updated input 'haskell-nix/stackage':
    'github:input-output-hk/stackage.nix/8a7333a' (2026-01-03)
  → 'github:input-output-hk/stackage.nix/422f169' (2026-04-25)
flake.lock: Update
Flake lock file updates:

• Updated input 'haskellNix':
    'github:input-output-hk/haskell.nix/cc939d0' (2026-02-23)
  → 'github:input-output-hk/haskell.nix/3328b9a' (2026-04-25)
• Removed input 'haskellNix/cabal-32'
• Updated input 'haskellNix/hackage':
    'github:input-output-hk/hackage.nix/06f38c7' (2026-02-23)
  → 'github:input-output-hk/hackage.nix/39467ed' (2026-04-25)
• Updated input 'haskellNix/hackage-for-stackage':
    'github:input-output-hk/hackage.nix/2d5bbb1' (2026-02-23)
  → 'github:input-output-hk/hackage.nix/c32368d' (2026-04-25)
• Updated input 'haskellNix/iserv-proxy':
    'github:stable-haskell/iserv-proxy/91ef7ff' (2026-02-04)
  → 'github:stable-haskell/iserv-proxy/3f7b281' (2026-04-08)
• Updated input 'haskellNix/nixpkgs-2511':
    'github:NixOS/nixpkgs/b0924ea' (2025-12-01)
  → 'github:NixOS/nixpkgs/74b8795' (2026-04-09)
• Updated input 'haskellNix/nixpkgs-unstable':
    'github:NixOS/nixpkgs/c1cb7d0' (2025-12-01)
  → 'github:NixOS/nixpkgs/1304392' (2026-04-11)
• Updated input 'haskellNix/stackage':
    'github:input-output-hk/stackage.nix/862226e' (2026-02-23)
  → 'github:input-output-hk/stackage.nix/422f169' (2026-04-25)
• Updated input 'iohk-nix':
    'github:input-output-hk/iohk-nix/a704b93' (2025-11-12)
  → 'github:input-output-hk/iohk-nix/fdfc53b' (2026-04-17)
• Updated input 'iohk-nix/blst':
    'github:supranational/blst/8c7db7f' (2025-02-12)
  → 'github:supranational/blst/6d960cd' (2025-02-12)