From 8aaf0facce2df44ba69d25e3226b2335ebb7225e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 09:07:44 +0000 Subject: [PATCH 1/2] share: Show the master fingerprint after the threshold `ms32 secret` shows the master fingerprint with the recovered secret, but `ms32 share` never did, so the operator couldn't compare it with the wallet record before writing a new card. Print it above the derived share on a terminal, whether every input is a share or one of them is the secret. `--plain` and redirected output stay unchanged. Closes #86 Claude-Session: https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa --- src/codex32/cli.py | 4 ++++ tests/test_cli.py | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/codex32/cli.py b/src/codex32/cli.py index 6e81e43..a23c3a5 100644 --- a/src/codex32/cli.py +++ b/src/codex32/cli.py @@ -189,6 +189,10 @@ def _share_command(index: str, plain: bool, context: _CliContext, core: BitcoinC derived = derive_share(artifacts, index) except CodexError as error: raise _CommandError(str(error)) from error + if core is not None and sys.stdout.isatty() and not plain: + given = [artifact for artifact in artifacts if isinstance(artifact, Secret)] + seed = cast(MasterSeed, given[0] if given else _secret(artifacts)) + _print(f"Master fingerprint: {core.fingerprint(seed).hex().upper()}\n") _emit(derived, plain) if sys.stdin.isatty() and sys.stdout.isatty() and not plain: try: diff --git a/tests/test_cli.py b/tests/test_cli.py index 889b175..e2b6198 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1693,13 +1693,15 @@ def test_create_rejects_bip39_partial_basis_and_selector_conflicts() -> None: assert result.exit_code != 0 -def test_terminal_secret_has_fingerprint_but_share_does_not() -> None: - secret = _invoke_terminal(["secret"], VECTOR_1["secret_s"]) +def test_terminal_secret_and_share_show_the_master_fingerprint() -> None: + secret = _invoke_terminal(["secret"], VECTOR_2["share_A"], VECTOR_2["share_C"]) share = _invoke_terminal(["share", "d"], VECTOR_2["share_A"], VECTOR_2["share_C"]) + from_secret = _invoke_terminal(["share", "d"], VECTOR_2["secret_S"], VECTOR_2["share_C"]) + fingerprint = _FakeBitcoinCore().fingerprint(cast(MasterSeed, parse_codex32(VECTOR_2["secret_S"]))) + line = f"Master fingerprint: {fingerprint.hex().upper()}" - assert secret.exit_code == share.exit_code == 0 - assert "Master fingerprint:" in secret.stdout - assert "Master fingerprint:" not in share.stdout + assert secret.exit_code == share.exit_code == from_secret.exit_code == 0 + assert line in secret.stdout and line in share.stdout and line in from_secret.stdout assert "Backup identifier:" in secret.stdout and "Backup identifier:" in share.stdout From a3a27b02d87cd06c7655d0d1bc4fbdb9c2370118 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 1 Oct 2026 09:34:05 +0000 Subject: [PATCH 2/2] test: Raise the size budget to 5,250 lines Ben authorized raising the budget so #91 fits. The stack tip with the open fix PRs was at 5,197 of 5,200, and #91 adds 26 lines. Update the enforcing test and both places that document the number. Claude-Session: https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa --- AGENTS.md | 2 +- docs/developer/api.md | 2 +- tests/test_cli.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fd47d95..cf7df8c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -61,7 +61,7 @@ avoid comments or tests that restate the implementation. Add or update concise docstrings when changing public behavior. Write codex32 in lowercase except when referring to the Codex32 Book. -Keep the installed package below 5,200 logical review lines, as enforced by the +Keep the installed package below 5,250 logical review lines, as enforced by the existing test. New dependencies, public API signature or return-shape changes, and lint suppressions require user authorization; an explicit request can already provide that authorization. diff --git a/docs/developer/api.md b/docs/developer/api.md index 4e6cd06..dadf99f 100644 --- a/docs/developer/api.md +++ b/docs/developer/api.md @@ -105,7 +105,7 @@ unsupported but remains in the review scope. ### Size budget -V1 keeps the installed package below 5,200 logical review lines, excluding +V1 keeps the installed package below 5,250 logical review lines, excluding blank and comment-only lines while counting subpackages recursively. Changing the budget requires explicit review and authorization together with the matching documentation and enforcement update. diff --git a/tests/test_cli.py b/tests/test_cli.py index e2b6198..1aabfc4 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -2195,7 +2195,7 @@ def test_production_size_budgets_are_enforced() -> None: for path in package.rglob("*.py") } - assert sum(counts.values()) < 5200, counts + assert sum(counts.values()) < 5250, counts @pytest.mark.parametrize(