Skip to content

fix: rework cli for consistency and UX#636

Merged
jeluard merged 2 commits into
mainfrom
command-line-consistency
Jan 16, 2026
Merged

fix: rework cli for consistency and UX#636
jeluard merged 2 commits into
mainfrom
command-line-consistency

Conversation

@KtorZ

@KtorZ KtorZ commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

Mainly:

  • Align env vars across all command options, and make sure that every option consistently comes with one.

  • Align metavar / 'value_names' across all command options

  • Allow users to run fine-grained commands with their own options. This is the case in particular for import_headers, fetach_chain_headers and import_nonces. Some people may run on fully custom networks, therefore requiring fine-grained control over the holistic "bootstrap" method.

  • Order commands and options alphabetically. Less messy.

  • Fix, complete, and make more consistent the initial log event of all command.

Summary by CodeRabbit

  • New Features

    • Reintroduced commands (fetch/import/run) and new/expanded CLI options: force flag, network selection, ledger/chain/headers/target directories, multi-file snapshot/header imports, and optional nonces file.
  • Improvements

    • Consistent environment-variable configuration and CLI value naming across commands.
    • More predictable defaults and clearer, structured runtime logging.
  • Documentation

    • Added CLI guidelines ADR describing conventions and best practices.

✏️ Tip: You can customize this high-level summary in your review settings.

@KtorZ KtorZ requested a review from jeluard January 15, 2026 12:39
@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Refactors multiple CLI commands to centralize CLI value-name/env constants, reshape Args structs (adding ledger_dir, chain_dir, network, force, etc.), replace file-based nonce/snapshot imports with embedded/defaults, update bootstrap signature and logging, and thread explicit directories (e.g., headers_dir) through fetch/import flows.

Changes

Cohort / File(s) Summary
Core CLI constants & defaults
crates/amaru/src/lib.rs
Added value_names and env_vars modules and default_initial_nonces(network) to centralize CLI value names, env var names and provide default initial nonces loader.
Bootstrap command
crates/amaru/src/bin/amaru/cmd/bootstrap.rs
Args reworked: added force: bool, ledger_dir: Option<PathBuf>, network: NetworkName; removed snapshots_dir. Structured logging added; ledger-exists handling honors force. Calls updated to new bootstrap signature.
Bootstrap core
crates/amaru/src/bootstrap.rs
Removed external snapshots_dir param (computes internally via default), replaced disk-based nonces import with default_initial_nonces(network), and made import_nonces public.
Fetch-chain-headers flow
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
Added headers_dir: PathBuf and parent: Vec<String> to Args; threaded headers_dir through fetch functions and chain-sync routines; explicitly create/write header files to provided headers_dir; updated logging and error handling.
Import headers & convert ledger
crates/amaru/src/bin/amaru/cmd/import_headers.rs, .../convert_ledger_state.rs
import_headers: added header_file: Vec<PathBuf>, reinstated network, branch to load bootstrap headers vs listed files. convert_ledger_state: Args now network, snapshot: PathBuf, target_dir: PathBuf and uses structured logging/env bindings.
Import ledger state & nonces
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs, .../import_nonces.rs
import_ledger_state: added ledger_dir, network, multi-snapshot support and snapshot_dir. import_nonces: added nonces_file: Option<PathBuf> and now uses either supplied file or default_initial_nonces(network); logging updated.
Storage / chain utilities
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs, .../migrate_chain_db.rs, .../reset_to_epoch.rs
Added/updated chain_dir/ledger_dir and network Args to use centralized constants; switched to structured logging and minor arg attribute changes.
Run command
crates/amaru/src/bin/amaru/cmd/run.rs
Restructured Args (added chain_dir, ledger_dir, preserved peer_address, pid_file), pub async fn run(args, meter_provider: Option<SdkMeterProvider>) with boxed error return; logging and env/value_name mappings updated.
CLI surface / main
crates/amaru/src/bin/amaru/main.rs
Reintroduced/reordered Command enum variants: FetchChainHeaders, ImportHeaders, ImportLedgerState, ImportNonces, Run (alias daemon); expanded docs for bootstrap and dump-chain-db.
Docs / ADR
engineering-decision-records/019-guidelines-for-writing-cli.md
Added ADR specifying CLI conventions: env vars, naming, logging, flags, docs and consequences for centralized CLI constants.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as CLI (fetch-chain-headers)
  participant Peer as ChainSyncPeer
  participant FS as Filesystem (headers_dir)
  CLI->>FS: ensure headers_dir exists
  CLI->>Peer: connect and request headers starting from points
  Peer-->>CLI: send header chunk
  CLI->>FS: write header file into headers_dir
  CLI->>Peer: request next block/point
  Peer-->>CLI: send header chunk
  CLI->>FS: write header file (repeat until done)
  CLI->>FS: finalize/rotate files
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • KtorZ
  • abailly

Poem

Ah, the CLI got a tidy glow, mate,
Flags lined up like badges in a row.
Defaults snug as a game-save slot,
Logs now speak with structure — neat plot.
Ship sails steady, ready to go. 🎮🍀

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 24.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: rework cli for consistency and UX' directly addresses the main objective: standardizing CLI arguments, environment variables, and user experience across commands.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.



📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c171af and e5a8010.

📒 Files selected for processing (1)
  • engineering-decision-records/019-guidelines-for-writing-cli.md
🧰 Additional context used
🪛 LanguageTool
engineering-decision-records/019-guidelines-for-writing-cli.md

[style] ~14-~14: To elevate your writing, try using a synonym here.
Context: ... key to build good interface; and it is hard to get consistency unless guidelines an...

(HARD_TO)


[style] ~26-~26: To elevate your writing, try using a synonym here.
Context: ...ts. However, environment variables are hard to document. Command-line options, on t...

(HARD_TO)


[style] ~52-~52: To elevate your writing, try using a synonym here.
Context: ... command. It can be hard to figure out what exactly gets used as...

(HARD_TO)

🪛 markdownlint-cli2 (0.18.1)
engineering-decision-records/019-guidelines-for-writing-cli.md

109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: clippy
  • GitHub Check: Build x86_64/linux
  • GitHub Check: Build aarch64/linux
  • GitHub Check: Build aarch64/macos
  • GitHub Check: Build x86_64/windows
  • GitHub Check: Test coverage
  • GitHub Check: Build riscv32
  • GitHub Check: Test the CLI
  • GitHub Check: Benches
  • GitHub Check: Analyze (rust)
🔇 Additional comments (1)
engineering-decision-records/019-guidelines-for-writing-cli.md (1)

1-180: Solid guidelines, mate! This ADR is top-notch.

Really dig how comprehensive and practical these CLI guidelines are – like a proper walkthrough for keeping the codebase tidy. The examples are chef's kiss, especially that structured logging snippet showing alphabetical ordering. Makes it dead easy for anyone to follow the conventions.

The reasoning behind each guideline is crystal clear too, from the env var strategy to the alphabetical ordering principle. No ambiguity, just good ol' consistency. This'll save future devs a heap of headaches!

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (2)

383-392: Critical: Test won't compile - target_dir is now PathBuf, not Option<PathBuf>.

Oi, mate! The pipeline's throwing a wobbly here. The Args struct got refactored to use target_dir: PathBuf (with a default of "."), but this test is still wrapping it in Some(...). It's like trying to fit a square peg in a round hole - the compiler's not having it!

🐛 Proposed fix
         for snapshot in snapshots {
             let args = super::Args {
+                network,
                 snapshot,
-                target_dir: Some(tempdir.path().to_path_buf()),
-                network,
+                target_dir: tempdir.path().to_path_buf(),
             };

             run(args)

434-444: Same compilation error here - needs the same fix.

Déjà vu! Same story, different test. The target_dir field needs to drop the Some(...) wrapper.

🐛 Proposed fix
         for snapshot in snapshots {
             let args = super::Args {
+                network,
                 snapshot,
-                target_dir: Some(target_dir.clone()),
-                network,
+                target_dir: target_dir.clone(),
             };

             run(args)
🤖 Fix all issues with AI agents
In `@crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs`:
- Around line 227-236: The call to std::fs::create_dir_all is passing a needless
borrow of headers_dir (headers_dir is already a &Path); remove the ampersand so
call std::fs::create_dir_all(headers_dir) instead, keeping the same
inspect_err/error handling and map_err( |_| WorkerError::Panic ) surrounding it
to preserve behavior.

In `@crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs`:
- Around line 65-74: The doc for the snapshot_dir field is inaccurate: it claims
a default per-network directory when in fact run() returns IncorrectUsage if
both snapshot and snapshot_dir are omitted; update the doc comment on
snapshot_dir to state that omitting both snapshot and snapshot_dir will cause an
IncorrectUsage error (refer to the snapshot_dir struct field and the run()
function which performs the check/returns IncorrectUsage), or alternatively
implement the intended default behavior inside run() by deriving the per-network
snapshots directory when snapshot_dir is None before validating and proceeding.

In `@crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs`:
- Around line 31-37: The doc comment above the ledger_dir field mistakenly says
"chain database"; update that comment to accurately reference the ledger
database (e.g., "The path to the ledger database to reset") so the documentation
matches the field name ledger_dir in reset_to_epoch.rs and avoids the
chain/ledger terminology mix-up.

In `@crates/amaru/src/bin/amaru/cmd/run.rs`:
- Around line 35-40: The chain_dir CLI arg is bound to the wrong environment
variable constant; update the arg definition for chain_dir (the struct field
chain_dir) to use amaru::env_vars::CHAIN_DIR instead of amaru::env_vars::NETWORK
so the AMARU_CHAIN_DIR env var is honored; locate the arg attributes on
chain_dir in the run.rs file and change the env = amaru::env_vars::NETWORK to
env = amaru::env_vars::CHAIN_DIR.

In `@crates/amaru/src/lib.rs`:
- Around line 95-102: The module-level doc comment for value_names is truncated
("aligned with:"); update the comment for pub mod value_names to complete the
thought by either specifying the intended reference (e.g., "aligned with clap's
naming conventions" or your project's CLI style guide) or by removing the
dangling fragment and finishing the sentence so the doc reads as a complete
convention description.

In `@engineering-decision-records/019-guidelines-for-writing-cli.md`:
- Line 85: Replace the misspelled word "objets" with "objects" in the ADR text
(the occurrence currently reads "informative as possible, and identical for
options that refer to objets of the"); update that token to "objects" so the
sentence reads correctly.
- Around line 175-176: Update the markdown link for the PR so GitHub resolves
correctly: change the URL in the text "Various command-line changes introduced
via [amaru#636](https://github.com/pragma-org/amaru/pulls/636) to comply with
these guidelines." to use /pull/ instead of /pulls/ (i.e.,
https://github.com/pragma-org/amaru/pull/636), keeping the link text "amaru#636"
unchanged.
🧹 Nitpick comments (3)
crates/amaru/src/bin/amaru/main.rs (1)

141-152: Minor consistency nit: match arms aren't alphabetically ordered.

The PR mentions ordering commands alphabetically for consistency - the enum variants above nail it, but these match arms are vibin' to their own beat. It's like having your vinyl collection sorted on the shelf but playing tracks in shuffle mode!

Not a deal-breaker by any means, just a wee polish opportunity if you're keen.

💅 Proposed alphabetical ordering
     let result = match args.command {
-        Command::Run(args) => cmd::run::run(args, metrics).await,
-        Command::ImportLedgerState(args) => cmd::import_ledger_state::run(args).await,
-        Command::ImportHeaders(args) => cmd::import_headers::run(args).await,
-        Command::ImportNonces(args) => cmd::import_nonces::run(args).await,
         Command::Bootstrap(args) => cmd::bootstrap::run(args).await,
-        Command::FetchChainHeaders(args) => cmd::fetch_chain_headers::run(args).await,
         Command::ConvertLedgerState(args) => cmd::convert_ledger_state::run(args).await,
         Command::DumpChainDB(args) => cmd::dump_chain_db::run(args).await,
+        Command::FetchChainHeaders(args) => cmd::fetch_chain_headers::run(args).await,
+        Command::ImportHeaders(args) => cmd::import_headers::run(args).await,
+        Command::ImportLedgerState(args) => cmd::import_ledger_state::run(args).await,
+        Command::ImportNonces(args) => cmd::import_nonces::run(args).await,
         Command::MigrateChainDB(args) => cmd::migrate_chain_db::run(args).await,
         Command::ResetToEpoch(args) => cmd::reset_to_epoch::run(args).await,
+        Command::Run(args) => cmd::run::run(args, metrics).await,
     };
crates/amaru/src/bin/amaru/cmd/import_nonces.rs (1)

66-70: Optional: Consider async file read for consistency.

The logic here is spot on, mate! However, you're using std::fs::read (synchronous) in an async function, while other commands like convert_ledger_state.rs use tokio::fs. It's a small file so it won't block the runtime for long, but if you're keen on consistency, async would be the way to go.

Not a biggie for a wee JSON file - totally your call!

🔧 Async alternative
     let initial_nonces = if let Some(manually_specified_file) = args.nonces_file {
-        serde_json::from_slice(std::fs::read(manually_specified_file)?.as_slice())?
+        serde_json::from_slice(tokio::fs::read(manually_specified_file).await?.as_slice())?
     } else {
         default_initial_nonces(network)?
     };
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)

83-90: Consider adding file context to read errors.

When fs::read fails, the error won't tell you which file caused the drama – bit like getting a "something went wrong" without knowing what. Not a huge deal since there's usually only a few files, but it'd be nice for debugging.

♻️ Optional improvement
     let headers = if args.header_file.is_empty() {
         get_bootstrap_headers(network)?.collect::<Vec<_>>()
     } else {
         args.header_file
             .iter()
-            .map(fs::read)
+            .map(|path| {
+                fs::read(path).map_err(|e| {
+                    format!("failed to read header file '{}': {}", path.display(), e)
+                })
+            })
             .collect::<Result<_, _>>()?
     };
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6b476a1 and e4e26db.

📒 Files selected for processing (14)
  • crates/amaru/src/bin/amaru/cmd/bootstrap.rs
  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/import_nonces.rs
  • crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bootstrap.rs
  • crates/amaru/src/lib.rs
  • engineering-decision-records/019-guidelines-for-writing-cli.md
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-16T21:32:37.668Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 584
File: crates/amaru-network/src/handshake/tests.rs:40-47
Timestamp: 2025-12-16T21:32:37.668Z
Learning: In Rust, shadowing a binding with a new let does not drop the previous binding until the end of the scope. All shadowed bindings in a scope are dropped in reverse-declaration order when the scope ends. Therefore, multiple let _guard = register_*() calls will keep all guards alive until the end of the function (or the surrounding scope). When reviewing code, be mindful that resources tied to shadowed bindings persist longer than the most recent binding; to release early, constrain the lifetime in an inner block or explicitly drop guards when appropriate.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bin/amaru/cmd/bootstrap.rs
  • crates/amaru/src/bootstrap.rs
  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/import_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
  • crates/amaru/src/lib.rs
  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_nonces.rs
📚 Learning: 2025-08-20T13:02:25.763Z
Learnt from: jeluard
Repo: pragma-org/amaru PR: 387
File: crates/amaru-stores/src/lib.rs:40-40
Timestamp: 2025-08-20T13:02:25.763Z
Learning: In the amaru-stores crate, amaru_slot_arithmetic types like Epoch and EraHistory are used throughout the main crate code in modules like in_memory/mod.rs, rocksdb/consensus.rs, and rocksdb/ledger/columns/, not just in tests. This means amaru-slot-arithmetic should be a regular dependency, not a dev-dependency.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
📚 Learning: 2025-08-12T12:28:24.027Z
Learnt from: etorreborre
Repo: pragma-org/amaru PR: 372
File: simulation/amaru-sim/src/simulator/mod.rs:410-412
Timestamp: 2025-08-12T12:28:24.027Z
Learning: In the Amaru project, panic statements are acceptable in simulation/test code (like amaru-sim crate) as they help identify configuration issues quickly during development, rather than needing proper error handling like production code.

Applied to files:

  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
📚 Learning: 2025-05-21T18:58:48.631Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 228
File: crates/amaru-stores/src/rocksdb/consensus.rs:89-128
Timestamp: 2025-05-21T18:58:48.631Z
Learning: The InMemConsensusStore implementation in crates/amaru-stores/src/rocksdb/consensus.rs will be fleshed out incrementally on a by-need basis, driven by test requirements rather than implementing all functionality upfront.

Applied to files:

  • crates/amaru/src/bootstrap.rs
📚 Learning: 2025-09-29T16:44:14.807Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 471
File: crates/amaru-network/src/protocol.rs:94-106
Timestamp: 2025-09-29T16:44:14.807Z
Learning: In the amaru-network crate protocol.rs file, the correct Cardano mini-protocol ID assignments are: PROTO_N2N_KEEP_ALIVE = 8 and PROTO_N2N_PEER_SHARE = 10, as verified against the network specification by the maintainer.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
📚 Learning: 2025-06-24T06:36:05.931Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 295
File: crates/amaru-consensus/src/consensus/store_header.rs:52-53
Timestamp: 2025-06-24T06:36:05.931Z
Learning: In crates/amaru-consensus, flood prevention for duplicate invalid headers should be implemented in the validate_header stage or database layer, not in the store_header stage, since store_header runs before validation and cannot determine header validity.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-09-05T17:30:55.869Z
Learnt from: etorreborre
Repo: pragma-org/amaru PR: 432
File: crates/amaru/src/stages/consensus/clients_block_fetcher.rs:0-0
Timestamp: 2025-09-05T17:30:55.869Z
Learning: In crates/amaru/src/stages/consensus/clients_block_fetcher.rs, the fetch method currently holds a mutex lock across an await operation and lacks timeout handling. The author etorreborre has acknowledged this should be improved later by releasing the lock before awaiting and adding a bounded timeout around the network fetch operation.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2026-01-11T20:05:19.348Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 612
File: crates/amaru-protocols/src/chainsync/responder.rs:191-213
Timestamp: 2026-01-11T20:05:19.348Z
Learning: In crates/amaru-protocols/src/chainsync/responder.rs, the chainsync responder intentionally does not support serving headers when the tip is Origin. Amaru is not designed to cold-start a new Cardano blockchain, so the intersect() function correctly fails when tip is Origin without needing special handling. This is a conscious design decision.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-12-28T19:26:35.354Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 612
File: crates/amaru-protocols/src/blockfetch/mod.rs:151-173
Timestamp: 2025-12-28T19:26:35.354Z
Learning: In crates/amaru-protocols/src/blockfetch/mod.rs, the blockfetch initiator uses .expect() when popping from the request queue on NoBlocks and Done results. These are intentional fail-fast assertions: the protocol state machine guarantees the queue is non-empty when these messages arrive, so an empty queue indicates a protocol violation. A misbehaving peer triggers an erroneous protocol transition that will close the connection (supervision to be implemented in a future PR). This follows the project's fail-fast philosophy for protocol invariants.
<!--

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
🧬 Code graph analysis (10)
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs (3)
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (1)
  • run (84-108)
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (1)
  • run (77-101)
crates/amaru/src/lib.rs (1)
  • default_chain_dir (47-49)
crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (1)
crates/amaru/src/lib.rs (1)
  • default_ledger_dir (43-45)
crates/amaru/src/bin/amaru/main.rs (9)
crates/amaru/src/observability.rs (1)
  • setup_observability (320-349)
crates/amaru/src/bin/amaru/cmd/bootstrap.rs (1)
  • run (58-95)
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (1)
  • run (68-80)
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (1)
  • run (84-108)
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)
  • run (64-93)
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (1)
  • run (77-101)
crates/amaru/src/bin/amaru/cmd/import_nonces.rs (1)
  • run (52-77)
crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs (1)
  • run (46-80)
crates/amaru/src/bin/amaru/cmd/run.rs (1)
  • run (129-155)
crates/amaru/src/bin/amaru/cmd/bootstrap.rs (2)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/lib.rs (2)
  • default_chain_dir (47-49)
  • default_ledger_dir (43-45)
crates/amaru/src/bootstrap.rs (1)
crates/amaru/src/lib.rs (3)
  • default_initial_nonces (67-75)
  • default_snapshots_dir (55-57)
  • get_bootstrap_file (77-83)
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (1)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)
crates/amaru/src/lib.rs (1)
  • default_chain_dir (47-49)
crates/amaru/src/bin/amaru/cmd/run.rs (2)
crates/amaru/src/metrics.rs (1)
  • track_system_metrics (26-63)
crates/amaru/src/lib.rs (2)
  • default_ledger_dir (43-45)
  • default_chain_dir (47-49)
crates/amaru/src/lib.rs (1)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (2)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/lib.rs (1)
  • get_bootstrap_file (77-83)
🪛 GitHub Actions: Coding Practices
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs

[error] 385-385: mismatched types: expected PathBuf, found Option for target_dir: Some(tempdir.path().to_path_buf())


[error] 437-437: mismatched types: expected PathBuf, found Option for target_dir: Some(target_dir.clone())

crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs

[error] 228-228: clippy: needless borrow for generic args. The call to std::fs::create_dir_all(&headers_dir) may be better as std::fs::create_dir_all(headers_dir).

🪛 LanguageTool
engineering-decision-records/019-guidelines-for-writing-cli.md

[style] ~14-~14: To elevate your writing, try using a synonym here.
Context: ... key to build good interface; and it is hard to get consistency unless guidelines an...

(HARD_TO)


[style] ~26-~26: To elevate your writing, try using a synonym here.
Context: ...ts. However, environment variables are hard to document. Command-line options, on t...

(HARD_TO)


[style] ~52-~52: To elevate your writing, try using a synonym here.
Context: ... command. It can be hard to figure out what exactly gets used as...

(HARD_TO)


[grammar] ~85-~85: Ensure spelling is correct
Context: ...and identical for options that refer to objets of the same nature.

<detail...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
engineering-decision-records/019-guidelines-for-writing-cli.md

109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: End-to-end snapshot tests (preview, 2, 680, true, 15, 60, 10.5.3)
  • GitHub Check: End-to-end snapshot tests (preprod, 1, 182, 15, 60, 10.5.3)
  • GitHub Check: Benches
  • GitHub Check: Build x86_64/windows
  • GitHub Check: Build aarch64/linux
  • GitHub Check: Build riscv32
  • GitHub Check: Build aarch64/macos
  • GitHub Check: Test coverage
  • GitHub Check: Test the CLI
  • GitHub Check: Analyze (rust)
🔇 Additional comments (31)
engineering-decision-records/019-guidelines-for-writing-cli.md (1)

1-180: Ripper of a doc, love the structure!

This EDR is a solid piece of work – like having a proper game manual instead of figuring things out as you go. The guidelines are clear, well-organized with the collapsible sections, and the code examples really drive the points home. Following these conventions will make the CLI experience way more consistent for users. Good on ya!

crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs (2)

28-46: Args struct looking fresh!

The new chain_dir option with proper value_name and env attributes, plus the centralized constants for network – this is exactly what the EDR ordered. Consistent as a metronome, mate!


48-58: Structured logging done right

Love the new logging format with _command, chain_dir, and network fields – follows the EDR guidelines to a T. The unwrap_or_else pattern for deriving defaults from network is clean and consistent with the other commands. Like a well-choreographed scene in a Tarantino flick!

crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs (2)

26-44: Args struct nicely aligned with the new conventions

Switched over to the centralized value_names and env_vars constants – this is the way, as the Mandalorian would say. The added doc comment for network is a nice touch too.


53-58: Logging format is spot on

The structured log with _command = "migrate-chain-db" and the relevant fields before the "running" message – chef's kiss! Matches the EDR conventions perfectly.

crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (3)

24-29: Env var on a positional argument – intentional?

The epoch is a positional argument (no long attribute), but it has an env binding. Per the EDR guideline 7, positional args are typically for mandatory values that users must always provide explicitly. Having an env var fallback here might let users accidentally run this destructive reset operation without realizing they've got AMARU_EPOCH set in their environment.

Given this command deletes epoch data, you might want to reconsider whether the env var is appropriate here, or if it's intentional to allow this workflow.


49-60: Structured logging and default derivation – noice!

The ledger_dir derivation from network and the structured logging format are both consistent with the other commands. Clean implementation, mate!


120-122: Redundant .clone() on the string

Minor thing – title.to_lowercase() already returns a new String, so the .clone() is unnecessary. Like carrying a spare key when you've already got one in your hand!

-    let mut lower = title.to_lowercase().clone();
+    let mut lower = title.to_lowercase();

Wait, this is in dump_chain_db.rs not this file – ignore me, wrong file context! This line doesn't exist in reset_to_epoch.rs.

crates/amaru/src/bootstrap.rs (3)

152-172: Bootstrap API simplification – sweet as!

Removing snapshots_dir from the public API and computing it internally via default_snapshots_dir(network) is a solid move. Less for users to worry about, more "it just works" vibes – like when a game auto-configures graphics settings correctly!


200-230: import_nonces visibility bump to pub – makes sense

Changing from pub(crate) to pub enables the fine-grained command usage mentioned in the PR objectives. Users can now run import_nonces independently with custom networks. The signature taking InitialNonces directly instead of a file path is cleaner – no more filesystem coupling for the core logic.


164-164: The conversion looks solid—no worries here

The network.into() call at line 164 is properly converting NetworkName to &EraHistory via a well-implemented From trait. Each network (Mainnet, Preprod, Preview) gets its own static EraHistory constant, and custom testnets all use a shared TESTNET_ERA_HISTORY—which is the right design choice. No dodgy lifetime shenanigans here; it's all safe as houses since you're grabbing references to constants, not temporaries. Like nailing a perfect combo in a fighting game, the conversion is crispy and correct.

crates/amaru/src/bin/amaru/main.rs (1)

39-107: Lookin' good, mate! The Command enum is properly structured.

The expanded command surface with FetchChainHeaders, ImportHeaders, ImportLedgerState, ImportNonces, and Run aligns nicely with the PR's goal of fine-grained control. Like unlocking all the side quests in an RPG instead of just having the main storyline!

The variants are alphabetically ordered (Bootstrap → ConvertLedgerState → DumpChainDB → ... → Run), which is spot on for the consistency goals.

crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (2)

25-58: Args struct refactor looks solid.

The streamlined Args with centralized constants from amaru::value_names and amaru::env_vars is exactly what the PR was aiming for. Clean and consistent, like a well-organized inventory system in Skyrim!

The snapshot being required (no default) makes perfect sense - ya can't convert thin air.


68-80: run() function is lookin' crisp.

The structured logging with _command = "convert-ledger-state" is consistent with other commands in the PR. No more unwrap_or_else dance since target_dir has a sensible default now. Chef's kiss! 🤌

crates/amaru/src/bin/amaru/cmd/import_nonces.rs (2)

21-50: Args struct is well-structured with the new nonces_file option.

Nice addition of the optional nonces_file parameter! This gives users fine-grained control to supply their own nonces JSON when needed - exactly what the PR set out to achieve. Like unlocking a secret character in a fighting game!

The centralized value_names and env_vars constants keep everything consistent across the CLI.


59-64: Structured logging is consistent with other commands.

The _command = "import-nonces" pattern matches the other subcommands nicely. Consistency is key, like following the same art style across a game trilogy!

crates/amaru/src/bin/amaru/cmd/bootstrap.rs (3)

21-56: Args struct is clean with the new --force flag.

The --force/-f flag is a great UX addition! Prevents accidental data loss while still giving power users the control they need. Like having a "Are you sure?" prompt before deleting a save file, but with an option to skip it.

Args fields are alphabetically ordered (chain_dir → force → ledger_dir → network) which aligns with PR goals. Noice!


78-92: Force logic is solid - nice safeguard!

This is a proper "Confirm delete?" pattern. The warning when ledger_dir exists (without --force) is helpful for users who might accidentally try to re-bootstrap. And when they do mean it, the --force path handles cleanup gracefully.

One tiny thing: remove_dir_all is sync but you're in an async context. Not a drama for a bootstrap operation, just noting it for consistency's sake.


69-76: Structured logging is chef's kiss!

Alphabetically ordered log fields (chain_dir → force → ledger_dir → network), consistent _command prefix, and the "running" message. It's all coming together like the final piece of a puzzle!

crates/amaru/src/lib.rs (3)

67-75: default_initial_nonces() is a tidy helper!

Centralizing the nonces loading logic here is smart - DRY principle in action! Other modules can just call this without duplicating the file-reading and JSON parsing logic. It's like having a shared loot chest in a co-op game.

The error handling with BootstrapError::MissingConfigFile is consistent with how other bootstrap files are handled.


103-124: value_names constants are well-organized.

Clear, descriptive constants that tell users exactly what format to expect. NETWORK = "mainnet|preprod|preview|testnet_<U32>" is particularly helpful - shows all valid options at a glance. Like a good character select screen!


126-178: env_vars module is beautifully organized!

Alphabetically ordered, consistent AMARU_ prefix, and each constant has a doc comment showing its corresponding CLI flag. This is exactly what the PR aimed for - every option now has a matching env var. It's like having a proper settings menu instead of scattered config files!

This centralizes what was probably scattered across multiple files before. Solid refactor, mate!

crates/amaru/src/bin/amaru/cmd/run.rs (3)

42-127: Args struct looking sharp, mate!

The CLI argument definitions are nicely consistent – using centralized value_names and env_vars constants throughout, proper defaults, and the multi-value peer_address handling with ArgAction::Append is spot on. Like a well-oiled machine, this is.


129-155: Meter provider integration – smooth as a flat white!

The optional metrics tracking setup is clean – conditionally spawning the tracker and properly aborting it on exit. This is proper resource management, no leaks here. Good stuff!


168-180: Structured logging looking grand!

The structured log fields are comprehensive and the _command tag for consistency across commands is a nice touch – makes log aggregation way easier. One tiny thing: the pid_file field will show an empty string when None, which is fine but could potentially be "<none>" or similar for clarity. Not a blocker though, just a thought!

crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)

24-62: Args struct is solid – like finding a rare loot drop!

The multi-file header_file support with ArgAction::Append and value_delimiter is well-designed. Users can pass multiple --header-file flags or comma-separate them – flexible as a yoga instructor. The defaults and env var bindings are consistent with the PR's goals.

crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (2)

25-75: Args struct is well-designed – like a good RPG skill tree!

The mutually exclusive snapshot vs snapshot_dir options using conflicts_with is proper CLI hygiene. The multi-snapshot support with num_args(0..) and the centralized env/value naming conventions are consistent. Clean separation of concerns here.


77-101: Run function logic is clean and clear!

The three-way branching is easy to follow – snapshot files take priority, then snapshot directory, then error out if neither is provided. The structured logging with all the relevant fields upfront is proper observability practice. Good job!

crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (3)

35-82: Args struct is looking good – proper adventurer's loadout!

The headers_dir with a sensible default, multi-value parent support, and consistent env/value naming conventions. The docstrings are helpful too – explaining why you need the parent point to fetch headers is like getting a proper quest briefing before heading out.


84-108: Run function is well-structured!

The fallback to bootstrap headers.json when no parent is provided is smart – keeps the command usable out of the box while allowing power users to specify custom starting points. The structured logging is comprehensive. This is like having both auto-aim and manual controls in a shooter – best of both worlds!


139-175: Header fetching pipeline is solid!

The headers_dir is properly threaded through all the helper functions – nice clean refactor. The progress bar integration and the fetch loop with proper Continue/Stop signaling is like a well-designed game loop. Tidy work!

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
Comment thread crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs
Comment thread crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs Outdated
Comment thread crates/amaru/src/bin/amaru/cmd/run.rs
Comment thread crates/amaru/src/lib.rs
Comment thread engineering-decision-records/019-guidelines-for-writing-cli.md Outdated
Comment thread engineering-decision-records/019-guidelines-for-writing-cli.md Outdated
Mainly:

- Align env vars across all command options, and make sure that every
  option consistently comes with one.

- Align metavar / 'value_names' across all command options

- Allow users to run fine-grained commands with their own options. This
  is the case in particular for import_headers, fetach_chain_headers and
  import_nonces. Some people may run on fully custom networks, therefore
  requiring fine-grained control over the holistic "bootstrap" method.

- Order commands and options alphabetically. Less messy.

- Fix, complete, and make more consistent the initial log event of all
  command.

Signed-off-by: KtorZ <matthias.benkort@gmail.com>
@KtorZ KtorZ force-pushed the command-line-consistency branch from e4e26db to 5c171af Compare January 15, 2026 12:51

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@engineering-decision-records/019-guidelines-for-writing-cli.md`:
- Line 35: Fix the typo in the heading text that reads "Use a common prefix for
envionment variables (e.g. AMARU_)" by changing "envionment" to "environment" so
the heading becomes "Use a common prefix for environment variables (e.g.
AMARU_)"; update the exact string in the markdown (the heading line containing
"Use a common prefix for envionment variables") and keep the example prefix
"AMARU_" unchanged.
♻️ Duplicate comments (2)
engineering-decision-records/019-guidelines-for-writing-cli.md (1)

181-181: Still got that URL glitch, mate!

This one slipped through the net – the link's still using /pulls/ instead of /pull/. GitHub won't be able to resolve it properly, like trying to load a save file from the wrong directory!

🔗 Proposed fix
-- [amaru#636](https://github.com/pragma-org/amaru/pulls/636)
+- [amaru#636](https://github.com/pragma-org/amaru/pull/636)
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (1)

65-75: Doc comment is a bit misleading, mate.

The doc says "When omitted, defaults to a per-network snapshots directory based on the network name" but checking the run() function (lines 94-100), if both snapshot and snapshot_dir are omitted, it returns IncorrectUsage rather than using any default. It's like the quest description promising treasure but the chest is actually empty!

Either update the doc to reflect reality, or implement the default behavior.

📝 Suggested doc fix if no default is intended
     /// Path to a directory containing multiple CBOR snapshots to import.
-    ///
-    /// When omitted, defaults to a per-network snapshots directory based on the network name.
+    ///
+    /// Either this or --snapshot must be provided.
     #[arg(
🧹 Nitpick comments (6)
engineering-decision-records/019-guidelines-for-writing-cli.md (1)

14-14: Optional style polish for the completionists out there

Static analysis flagged a few minor style suggestions if you're keen on that extra level of polish:

  • Lines 14, 26, 52: Could swap "hard to" for fancier synonyms like "difficult to" or "challenging to" (though honestly, "hard to" reads perfectly fine for tech docs)
  • Line 109: Markdown emphasis uses asterisks when the linter prefers underscores for consistency

These are purely optional nitpicks – the doc's already solid as-is, mate!

Also applies to: 26-26, 52-52, 109-109

crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (1)

120-121: Minor style nit: Consider using &Path instead of &PathBuf in function signatures.

Hey mate, just a wee suggestion – functions like get_ledger_db_snapshots and copy_dir_recursive take &PathBuf but idiomatically Rust prefers &Path for borrowed paths. It's like the difference between borrowing someone's whole backpack vs just the map inside – you only need what you need!

This isn't blocking at all, just a "nice to have" for future reference.

♻️ Optional refactor
 fn get_ledger_db_snapshots(
-    ledger_dir: &PathBuf,
+    ledger_dir: &Path,
 ) -> Result<Vec<Folder>, Box<dyn std::error::Error>> {
-fn copy_dir_recursive(src: &PathBuf, dst: &PathBuf) -> io::Result<()> {
+fn copy_dir_recursive(src: &Path, dst: &Path) -> io::Result<()> {
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (1)

82-92: Structured logging is grand, but there's a wee gotcha!

The logging looks good with all the fields, but using .unwrap_or_default() on snapshot_dir will log an empty string when it's None. Might be clearer to log "<not set>" or similar, or use the Option debug format. It's like a loading screen that just shows blank – technically works but could be more informative!

Not a blocker, just something to consider for debugging clarity.

♻️ Optional: More explicit None handling
     info!(
         _command = "import-ledger-state",
         ledger_dir = %ledger_dir.to_string_lossy(),
         network = %args.network,
         snapshot = ?args.snapshot,
-        snapshot_dir = %args.snapshot_dir
-            .clone()
-            .unwrap_or_default()
-            .to_string_lossy(),
+        snapshot_dir = ?args.snapshot_dir,
         "running",
     );
crates/amaru/src/bootstrap.rs (1)

283-283: Minor style nit: &Vec<PathBuf> could be &[PathBuf].

Hey mate, small suggestion – taking &Vec<PathBuf> is fine, but idiomatic Rust prefers &[PathBuf] (a slice) for borrowed collections. It's more flexible and doesn't tie you to Vec specifically. Like accepting any controller input rather than just one specific brand!

Not blocking at all, just a wee polish opportunity.

♻️ Optional refactor
 pub async fn import_snapshots(
     network: NetworkName,
-    snapshots: &Vec<PathBuf>,
+    snapshots: &[PathBuf],
     ledger_dir: &PathBuf,
 ) -> Result<(), Box<dyn std::error::Error>> {
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (1)

383-392: Tests updated correctly for the new Args shape.

The test now uses a concrete target_dir: tempdir.path().to_path_buf() instead of an optional value. The field ordering in the test struct construction (snapshot, target_dir, network) doesn't match the struct definition order (network, snapshot, target_dir), but Rust handles named fields in any order, so this is purely stylistic.

🔧 Optional: Match struct field order for consistency
         for snapshot in snapshots {
             let args = super::Args {
+                network,
                 snapshot,
                 target_dir: tempdir.path().to_path_buf(),
-                network,
             };
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)

64-70: Minor inconsistency: args.network used after binding network variable.

On line 65, you bind let network = args.network;, but on line 69 you use args.network in the unwrap_or_else closure. Not a bug since both refer to the same value (and NetworkName is Copy), but using network would be more consistent with the pattern used in other commands like import_nonces.rs and bootstrap.rs.

🔧 Optional: Use the local `network` binding consistently
     let chain_dir = args
         .chain_dir
-        .unwrap_or_else(|| default_chain_dir(args.network).into());
+        .unwrap_or_else(|| default_chain_dir(network).into());
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e4e26db and 5c171af.

📒 Files selected for processing (14)
  • crates/amaru/src/bin/amaru/cmd/bootstrap.rs
  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_headers.rs
  • crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/import_nonces.rs
  • crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs
  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bootstrap.rs
  • crates/amaru/src/lib.rs
  • engineering-decision-records/019-guidelines-for-writing-cli.md
🧰 Additional context used
🧠 Learnings (12)
📚 Learning: 2025-09-29T16:44:14.807Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 471
File: crates/amaru-network/src/protocol.rs:94-106
Timestamp: 2025-09-29T16:44:14.807Z
Learning: In the amaru-network crate protocol.rs file, the correct Cardano mini-protocol ID assignments are: PROTO_N2N_KEEP_ALIVE = 8 and PROTO_N2N_PEER_SHARE = 10, as verified against the network specification by the maintainer.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
📚 Learning: 2025-12-16T21:32:37.668Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 584
File: crates/amaru-network/src/handshake/tests.rs:40-47
Timestamp: 2025-12-16T21:32:37.668Z
Learning: In Rust, shadowing a binding with a new let does not drop the previous binding until the end of the scope. All shadowed bindings in a scope are dropped in reverse-declaration order when the scope ends. Therefore, multiple let _guard = register_*() calls will keep all guards alive until the end of the function (or the surrounding scope). When reviewing code, be mindful that resources tied to shadowed bindings persist longer than the most recent binding; to release early, constrain the lifetime in an inner block or explicitly drop guards when appropriate.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/import_nonces.rs
  • crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs
  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs
  • crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs
  • crates/amaru/src/lib.rs
  • crates/amaru/src/bin/amaru/cmd/import_headers.rs
  • crates/amaru/src/bin/amaru/cmd/bootstrap.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
  • crates/amaru/src/bootstrap.rs
📚 Learning: 2025-08-12T12:28:24.027Z
Learnt from: etorreborre
Repo: pragma-org/amaru PR: 372
File: simulation/amaru-sim/src/simulator/mod.rs:410-412
Timestamp: 2025-08-12T12:28:24.027Z
Learning: In the Amaru project, panic statements are acceptable in simulation/test code (like amaru-sim crate) as they help identify configuration issues quickly during development, rather than needing proper error handling like production code.

Applied to files:

  • crates/amaru/src/bin/amaru/main.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
📚 Learning: 2025-09-05T17:30:55.869Z
Learnt from: etorreborre
Repo: pragma-org/amaru PR: 432
File: crates/amaru/src/stages/consensus/clients_block_fetcher.rs:0-0
Timestamp: 2025-09-05T17:30:55.869Z
Learning: In crates/amaru/src/stages/consensus/clients_block_fetcher.rs, the fetch method currently holds a mutex lock across an await operation and lacks timeout handling. The author etorreborre has acknowledged this should be improved later by releasing the lock before awaiting and adding a bounded timeout around the network fetch operation.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-06-24T06:36:05.931Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 295
File: crates/amaru-consensus/src/consensus/store_header.rs:52-53
Timestamp: 2025-06-24T06:36:05.931Z
Learning: In crates/amaru-consensus, flood prevention for duplicate invalid headers should be implemented in the validate_header stage or database layer, not in the store_header stage, since store_header runs before validation and cannot determine header validity.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-06-24T06:36:05.931Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 295
File: crates/amaru-consensus/src/consensus/store_header.rs:52-53
Timestamp: 2025-06-24T06:36:05.931Z
Learning: In the amaru consensus pipeline, headers are now stored before validation (store_header stage runs before validate_header stage). The validity state of headers should be tracked in the database to avoid revalidating already-valid headers and to prevent flood attacks with duplicate invalid headers.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2026-01-11T20:05:19.348Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 612
File: crates/amaru-protocols/src/chainsync/responder.rs:191-213
Timestamp: 2026-01-11T20:05:19.348Z
Learning: In crates/amaru-protocols/src/chainsync/responder.rs, the chainsync responder intentionally does not support serving headers when the tip is Origin. Amaru is not designed to cold-start a new Cardano blockchain, so the intersect() function correctly fails when tip is Origin without needing special handling. This is a conscious design decision.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-08-23T15:44:44.318Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 392
File: crates/ouroboros-traits/src/is_header/fake.rs:52-88
Timestamp: 2025-08-23T15:44:44.318Z
Learning: In the Amaru project, FakeHeader in crates/ouroboros-traits/src/is_header/fake.rs is specifically designed for testing purposes, and panic behavior (like copy_from_slice() panicking on malformed hex) is the preferred approach rather than graceful error handling, as it helps identify test data issues quickly during development.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-12-28T19:26:35.354Z
Learnt from: rkuhn
Repo: pragma-org/amaru PR: 612
File: crates/amaru-protocols/src/blockfetch/mod.rs:151-173
Timestamp: 2025-12-28T19:26:35.354Z
Learning: In crates/amaru-protocols/src/blockfetch/mod.rs, the blockfetch initiator uses .expect() when popping from the request queue on NoBlocks and Done results. These are intentional fail-fast assertions: the protocol state machine guarantees the queue is non-empty when these messages arrive, so an empty queue indicates a protocol violation. A misbehaving peer triggers an erroneous protocol transition that will close the connection (supervision to be implemented in a future PR). This follows the project's fail-fast philosophy for protocol invariants.
<!--

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs
📚 Learning: 2025-08-20T13:02:25.763Z
Learnt from: jeluard
Repo: pragma-org/amaru PR: 387
File: crates/amaru-stores/src/lib.rs:40-40
Timestamp: 2025-08-20T13:02:25.763Z
Learning: In the amaru-stores crate, amaru_slot_arithmetic types like Epoch and EraHistory are used throughout the main crate code in modules like in_memory/mod.rs, rocksdb/consensus.rs, and rocksdb/ledger/columns/, not just in tests. This means amaru-slot-arithmetic should be a regular dependency, not a dev-dependency.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
  • crates/amaru/src/bin/amaru/cmd/run.rs
📚 Learning: 2025-09-06T09:16:25.025Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 435
File: crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs:113-116
Timestamp: 2025-09-06T09:16:25.025Z
Learning: In cardano-node serialized ledger state CBOR encoding, indefinite-length structures may be terminated with 0xFF "break" markers. The current code in convert_ledger_state.rs unconditionally strips the last byte (bytes[p..bytes.len() - 1]), which could corrupt data if the trailing byte is not actually a CBOR break marker.

Applied to files:

  • crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs
📚 Learning: 2025-05-21T18:58:48.631Z
Learnt from: abailly
Repo: pragma-org/amaru PR: 228
File: crates/amaru-stores/src/rocksdb/consensus.rs:89-128
Timestamp: 2025-05-21T18:58:48.631Z
Learning: The InMemConsensusStore implementation in crates/amaru-stores/src/rocksdb/consensus.rs will be fleshed out incrementally on a by-need basis, driven by test requirements rather than implementing all functionality upfront.

Applied to files:

  • crates/amaru/src/bootstrap.rs
🧬 Code graph analysis (11)
crates/amaru/src/bin/amaru/cmd/import_nonces.rs (2)
crates/amaru/src/bootstrap.rs (2)
  • bootstrap (153-172)
  • import_nonces (200-230)
crates/amaru/src/lib.rs (2)
  • default_chain_dir (47-49)
  • default_initial_nonces (67-75)
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs (1)
crates/amaru/src/lib.rs (1)
  • default_chain_dir (47-49)
crates/amaru/src/bin/amaru/main.rs (11)
crates/amaru/src/bootstrap.rs (1)
  • import_nonces (200-230)
crates/amaru/src/bin/amaru/cmd/bootstrap.rs (1)
  • run (58-95)
crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (1)
  • run (68-80)
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs (1)
  • run (48-88)
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (1)
  • run (84-108)
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)
  • run (64-93)
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (1)
  • run (77-101)
crates/amaru/src/bin/amaru/cmd/import_nonces.rs (1)
  • run (52-77)
crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs (1)
  • run (46-80)
crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (1)
  • run (49-97)
crates/amaru/src/bin/amaru/cmd/run.rs (1)
  • run (129-155)
crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (2)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/lib.rs (1)
  • get_bootstrap_file (77-83)
crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (1)
crates/amaru/src/lib.rs (1)
  • default_ledger_dir (43-45)
crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (3)
crates/amaru/src/bootstrap.rs (1)
  • std (260-263)
crates/amaru/src/lib.rs (1)
  • default_ledger_dir (43-45)
crates/amaru/tests/summary.rs (1)
  • default_ledger_dir (36-38)
crates/amaru/src/lib.rs (1)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/bin/amaru/cmd/import_headers.rs (1)
crates/amaru/src/lib.rs (1)
  • default_chain_dir (47-49)
crates/amaru/src/bin/amaru/cmd/bootstrap.rs (2)
crates/amaru/src/bootstrap.rs (1)
  • bootstrap (153-172)
crates/amaru/src/lib.rs (2)
  • default_chain_dir (47-49)
  • default_ledger_dir (43-45)
crates/amaru/src/bin/amaru/cmd/run.rs (1)
crates/amaru/src/lib.rs (2)
  • default_ledger_dir (43-45)
  • default_chain_dir (47-49)
crates/amaru/src/bootstrap.rs (1)
crates/amaru/src/lib.rs (3)
  • default_initial_nonces (67-75)
  • default_snapshots_dir (55-57)
  • get_bootstrap_file (77-83)
🪛 LanguageTool
engineering-decision-records/019-guidelines-for-writing-cli.md

[style] ~14-~14: To elevate your writing, try using a synonym here.
Context: ... key to build good interface; and it is hard to get consistency unless guidelines an...

(HARD_TO)


[style] ~26-~26: To elevate your writing, try using a synonym here.
Context: ...ts. However, environment variables are hard to document. Command-line options, on t...

(HARD_TO)


[style] ~52-~52: To elevate your writing, try using a synonym here.
Context: ... command. It can be hard to figure out what exactly gets used as...

(HARD_TO)

🪛 markdownlint-cli2 (0.18.1)
engineering-decision-records/019-guidelines-for-writing-cli.md

109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)


109-109: Emphasis style
Expected: underscore; Actual: asterisk

(MD049, emphasis-style)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: End-to-end snapshot tests (preprod, 1, 182, 15, 60, 10.5.3)
  • GitHub Check: End-to-end snapshot tests (preview, 2, 680, true, 15, 60, 10.5.3)
  • GitHub Check: clippy
  • GitHub Check: Build aarch64/macos
  • GitHub Check: Build riscv32
  • GitHub Check: Build x86_64/linux
  • GitHub Check: Build x86_64/windows
  • GitHub Check: Build aarch64/linux
  • GitHub Check: Benches
  • GitHub Check: Test the CLI
  • GitHub Check: Test coverage
  • GitHub Check: Analyze (rust)
🔇 Additional comments (37)
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs (3)

17-25: LGTM on the import reorganization!

The imports are nicely consolidated and grouped. Clean as a whistle, mate – like organizing your inventory before a boss fight.


28-46: Solid CLI argument standardization!

G'day! The new chain_dir option with centralized value_names::DIRECTORY and env_vars::CHAIN_DIR is spot on. The pattern of making it optional with a network-derived default is consistent with the other commands in this PR – like unlocking fast travel once you've discovered all the locations.


53-58: Structured logging looks grand!

The new structured log format with _command, chain_dir, and network fields is mint. Consistent with the other command modules and makes log aggregation way easier – like having proper quest markers instead of just "go find it somewhere."

crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs (2)

22-47: CLI arguments are looking proper now!

The Args struct is nicely aligned with the centralized constants. The epoch positional arg, optional ledger_dir, and network with default – all using the standardized value_names and env_vars. It's like finally getting all your gear sets to match in an RPG!


49-62: Run function setup is clean!

The pattern of computing ledger_dir from args or falling back to default_ledger_dir(args.network) is consistent with the other commands. The structured logging with _command = "reset-to-epoch" fits the bill perfectly. Fair dinkum work, mate!

crates/amaru/src/bin/amaru/cmd/import_ledger_state.rs (3)

27-42: CLI standardization is looking ace!

The ledger_dir and network arguments with centralized constants are consistent with the other commands. Nice one!


44-63: Multi-snapshot support is a beaut!

Changing snapshot to Vec<PathBuf> with num_args(0..) gives users flexibility to import multiple snapshots in one go. The verbatim_doc_comment preserves that nicely formatted example – like having a proper tutorial level before the main game.


94-100: Control flow is crystal clear!

The branching logic is straightforward – check snapshot first, then snapshot_dir, else error. Easy to follow, like a dialogue tree with only three options.

crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs (2)

26-44: Args struct is mint!

The centralized value_names::DIRECTORY, env_vars::CHAIN_DIR, value_names::NETWORK, and env_vars::NETWORK constants are all in place. The new doc comment for network adds clarity. Consistent as a speed-runner's route!


53-58: Structured logging follows the pattern nicely!

The _command = "migrate-chain-db" with chain_dir and network fields matches the other commands. Good stuff – like having all your HUD elements in the same spot across different games in a series.

crates/amaru/src/bootstrap.rs (3)

15-15: New internal defaults imported!

Using default_initial_nonces and default_snapshots_dir from crate root keeps the bootstrap logic clean and centralized. Like having your loadout presets saved!


152-172: Bootstrap function streamlined nicely!

The function now internally derives snapshots_dir via default_snapshots_dir(network) and sources nonces from default_initial_nonces(network) instead of reading from disk. This simplifies the public API while maintaining flexibility through the standalone commands. It's like the game offering both "Quick Play" and "Custom Match" options!

One thing to verify – since default_initial_nonces can return an Err, and you're using ? on line 164, any error will bubble up. That's probably fine, but worth noting for callers.


200-230: import_nonces is now public – spot on!

Bumping the visibility from pub(crate) to pub is the right move here. The standalone import_nonces command over in crates/amaru/src/bin/amaru/cmd/import_nonces.rs needs direct access to this function, and it was always gonna be a bit dodgy trying to work around that. The function itself is clean as a whistle – opens the chain DB, computes the epoch from the era history, builds the Nonces struct, and persists it. No drama there, mate!

The usage pattern checks out: you've got the internal call during bootstrap (line 164) and the external command hook (line 76), so this is legit intentional. Good call making it part of the public API surface.

crates/amaru/src/bin/amaru/cmd/convert_ledger_state.rs (2)

25-58: Nice one, mate! The Args struct is looking clean and consistent.

The centralized value_names and env_vars usage is spot on — like finding all the loot in one chest instead of scattered across the map. Default for target_dir to "." is a sensible UX choice too.

One small observation: per the PR objectives about alphabetical ordering, the fields here are network, snapshot, target_dir which is alphabetically ordered. Good stuff!


69-75: Structured logging is looking sharp!

The _command field pattern for identifying which command is running is consistent with the other commands in the PR. Like a well-organized inventory system in an RPG — everything's where you'd expect it to be.

crates/amaru/src/bin/amaru/main.rs (2)

39-107: Command enum is lookin' deadly, mate!

The alphabetical ordering of variants is on point — Bootstrap through Run, like a perfectly sorted game menu. The verbatim_doc_comment on Bootstrap is a nice touch for preserving that formatted documentation. The aliases (import-chain-db for ImportHeaders, import for ImportLedgerState, daemon for Run) are solid for backward compatibility and user convenience.

Like the saying goes: "It's dangerous to go alone!" — but with these clear command docs, users won't be lost.


141-152: All command dispatch paths are wired up correctly.

Every variant in the Command enum has a corresponding arm in the match statement. The flow is clean and each command module's run function is invoked properly.

crates/amaru/src/bin/amaru/cmd/bootstrap.rs (2)

21-56: Args struct is well organized with alphabetical field ordering.

The centralized value_names and env_vars constants are consistently applied. The force flag with short -f is a nice UX touch for power users — like having a quick-save shortcut in a game.


78-92: The --force flag logic is clear, but the silent success on existing dir might surprise some users.

When ledger_dir exists and --force isn't set, the command logs a warning and returns Ok(()). This is a valid idempotent design choice (like how some installers say "already installed, skipping"), but it might be worth considering whether this should be more explicit in the help text or return a non-zero exit in strict modes.

That said, for scripting and automation, this "no-op on existing" behavior is actually quite handy. Like respawning at a checkpoint instead of starting the whole level over.

crates/amaru/src/bin/amaru/cmd/import_nonces.rs (3)

21-50: Args struct looks good with the new nonces_file option.

Giving users the ability to specify a custom nonces file is a solid addition for custom network support. The doc comment explaining the fallback behavior is helpful — users will know what to expect when they don't provide the flag.


66-70: The nonces loading logic is straightforward.

The branching is clean: manual file takes precedence, otherwise fall back to network defaults. One small note — std::fs::read is synchronous I/O within an async function. For small config files like nonces JSON, this is generally fine and won't block the event loop noticeably. If this ever needed to handle larger files, you'd want to reach for tokio::fs::read, but for now, she'll be right.


72-76: Heads up: The FIXME comment documents a known design limitation with testnet EraHistory handling.

The conversion args.network.into() is type-safe and works exactly as intended—it leverages a From<NetworkName> for &EraHistory implementation that directly returns a reference to the appropriate static constant (&MAINNET_ERA_HISTORY, &PREPROD_ERA_HISTORY, &PREVIEW_ERA_HISTORY, or &TESTNET_ERA_HISTORY). This matches the import_nonces function signature perfectly, so there's no borrowed/owned mismatch here—like a well-oiled speedboat engine, the types align beautifully.

The FIXME itself is solid documentation of a separate architectural concern: relying on a statically-defined testnet EraHistory can be problematic depending on your use case. That's worth keeping an eye on, but the code as written here is doing its job without issue.

crates/amaru/src/bin/amaru/cmd/import_headers.rs (2)

40-52: The header_file argument configuration is flexible and user-friendly.

Using ArgAction::Append with value_delimiter = ',' gives users multiple ways to specify files:

  • --header-file a.cbor --header-file b.cbor
  • --header-file a.cbor,b.cbor

That's like having both keyboard and controller support — everyone's happy! The num_args(0..) allows zero or more values, which works well with the fallback to bootstrap headers.


83-92: Header loading logic is clean and follows the established pattern.

The branching mirrors the approach in import_nonces.rs: if no files specified, fall back to bootstrap defaults; otherwise, load from provided files. The collect::<Result<_, _>>()? pattern for propagating I/O errors from multiple file reads is idiomatic Rust.

Like finding all the collectibles in one go — efficient and satisfying!

crates/amaru/src/lib.rs (4)

15-15: LGTM!

Import cleanly pulls in the types needed for the new default_initial_nonces function. No worries here, mate!


67-75: LGTM!

Nice one! This function follows the same patterns as other bootstrap file helpers in the crate. The error handling is clean and the Box<dyn Error> return type keeps things flexible for callers – like choosing your loadout before a boss fight, you've got options!


95-123: LGTM!

This is cleaner than a freshly waxed surfboard! The value_names module provides a single source of truth for CLI metavars – no more hunting through files like trying to find that one save point in Dark Souls. The conventions are clearly documented and consistently applied.


125-177: LGTM!

Top shelf work here! Centralizing env vars like this is the CLI equivalent of a well-organized inventory system – you always know where to find what you need. The AMARU_ prefix keeps everything namespaced nicely, and those doc comments linking back to CLI options are chef's kiss. It's giving "I actually care about maintainability" energy.

crates/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs (6)

34-82: LGTM!

The Args struct is looking proper tidy! Using the centralized value_names and env_vars constants keeps things DRY – like having a shared stash box in a co-op game. The parent field configuration with ArgAction::Append and comma delimiter gives users flexibility to specify multiple points, which is a nice UX touch.


84-108: LGTM!

Sweet implementation! The fallback logic for parent is like having an auto-save – users get sensible defaults but can override when they need control. The structured logging at the start makes debugging a breeze. It's giving "I've played enough games to know good UX when I see it" vibes.


110-137: LGTM!

Parameter threading done right – headers_dir flows through cleanly. Using &Path as the parameter type is the idiomatic choice here.


139-175: LGTM!

The headers_dir parameter flows through to the inner functions nicely. No drama here!


183-210: LGTM!

Both helper functions properly thread the headers_dir parameter through to handle_response. Clean pass-through with no surprises – like a well-executed relay race.


212-281: LGTM!

The handle_response function is looking solid! The error handling with inspect_err for logging before mapping to WorkerError::Panic is a nice pattern – you get visibility into failures without losing the error flow. I see the past review's needless borrow note was sorted out too. Good stuff!

The unwrap() on line 222 for CBOR deserialization has the appropriate #[allow(clippy::unwrap_used)] attribute – per project conventions, fail-fast on malformed protocol data is the preferred approach here.

crates/amaru/src/bin/amaru/cmd/run.rs (3)

30-127: LGTM!

The Args struct is now properly kitted out! All the env vars are pointing to the right constants (I see that chain_dirCHAIN_DIR fix went through – no more accidental crouch-jumping!). The alphabetical ordering makes this read like a well-organized game settings menu. Using ArgAction::Append with comma delimiter for peer_address gives users the flexibility to connect to multiple upstream peers in whatever way suits them.


129-155: LGTM!

The run function is structured like a proper game loop – setup, main execution, and cleanup on exit. The metrics handle abort on shutdown is a nice touch for resource cleanup.


157-194: LGTM!

The parse_args function nails the defaults pattern – when users don't specify ledger_dir or chain_dir, they get sensible network-based defaults like ./ledger.preprod.db. The structured logging gives operators full visibility into the config at startup, which is clutch for debugging – like having a "show all stats" screen before starting a new run.

The Config construction cleanly maps all the args fields, and using ..Config::default() for any remaining fields keeps things future-proof.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread engineering-decision-records/019-guidelines-for-writing-cli.md Outdated
Comment thread engineering-decision-records/019-guidelines-for-writing-cli.md
Comment thread engineering-decision-records/019-guidelines-for-writing-cli.md
@codecov

codecov Bot commented Jan 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 3.84615% with 100 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...tes/amaru/src/bin/amaru/cmd/fetch_chain_headers.rs 0.00% 36 Missing ⚠️
crates/amaru/src/bin/amaru/cmd/import_headers.rs 0.00% 13 Missing ⚠️
crates/amaru/src/bin/amaru/cmd/bootstrap.rs 0.00% 11 Missing ⚠️
crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs 0.00% 7 Missing ⚠️
crates/amaru/src/lib.rs 0.00% 7 Missing ⚠️
...tes/amaru/src/bin/amaru/cmd/import_ledger_state.rs 0.00% 6 Missing ⚠️
crates/amaru/src/bin/amaru/cmd/import_nonces.rs 0.00% 6 Missing ⚠️
crates/amaru/src/bin/amaru/cmd/run.rs 0.00% 5 Missing ⚠️
crates/amaru/src/bootstrap.rs 0.00% 3 Missing ⚠️
...es/amaru/src/bin/amaru/cmd/convert_ledger_state.rs 66.66% 2 Missing ⚠️
... and 2 more
Files with missing lines Coverage Δ
crates/amaru/src/bin/amaru/main.rs 0.00% <ø> (ø)
...es/amaru/src/bin/amaru/cmd/convert_ledger_state.rs 91.04% <66.66%> (-0.72%) ⬇️
crates/amaru/src/bin/amaru/cmd/dump_chain_db.rs 0.00% <0.00%> (ø)
crates/amaru/src/bin/amaru/cmd/migrate_chain_db.rs 0.00% <0.00%> (ø)
crates/amaru/src/bootstrap.rs 48.68% <0.00%> (+2.43%) ⬆️
crates/amaru/src/bin/amaru/cmd/run.rs 0.00% <0.00%> (ø)
...tes/amaru/src/bin/amaru/cmd/import_ledger_state.rs 0.00% <0.00%> (ø)
crates/amaru/src/bin/amaru/cmd/import_nonces.rs 0.00% <0.00%> (ø)
crates/amaru/src/bin/amaru/cmd/reset_to_epoch.rs 0.00% <0.00%> (ø)
crates/amaru/src/lib.rs 0.00% <0.00%> (ø)
... and 3 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Signed-off-by: jeluard <jeluard@users.noreply.github.com>
@jeluard jeluard force-pushed the command-line-consistency branch from 11b170e to e5a8010 Compare January 16, 2026 13:36
@jeluard jeluard merged commit 915b944 into main Jan 16, 2026
22 checks passed
@jeluard jeluard deleted the command-line-consistency branch January 16, 2026 14:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants