{
 "number": 35713,
 "input_hash": "74417967b23ef8df",
 "model": "openrouter/google/gemini-3.8-flash",
 "batch": false,
 "created": "2026-09-17T21:37:43+00:00",
 "provider": "Google",
 "stop_reason": "end_turn",
 "usage": {
  "input_tokens": 56046,
  "cache_creation_input_tokens": 0,
  "cache_read_input_tokens": 0,
  "output_tokens": 14179
 },
 "cost_usd": 0.09520575,
 "error": null,
 "result": {
  "display": {
   "goal": [
    "Replace Boost.Test with an in-house header-only unit test runner to simplify test macros and remove the Boost.Test dependency.",
    "Enable better failure diagnostics via expression decomposition and unblock future test concurrency improvements."
   ],
   "reviewability": [
    "Ready to review.",
    "All major bugs raised in the previous review round have been addressed in recent pushes."
   ],
   "agreement": [
    "Strong conceptual support for replacing Boost.Test with an in-house runner (josibake, jeanpablojp).",
    "Detailed review feedback on failure diagnostics, null handling, output buffering, and seed randomization has been addressed (maflcko, jeanpablojp)."
   ],
   "categories": [
    {
     "name": "tests",
     "why": [
      "P3 because it overhauls test runner infrastructure and assertion syntax across the entire unit test suite.",
      "It improves failure diagnostics and removes an external dependency, though it does not resolve an active CI failure."
     ]
    },
    {
     "name": "build",
     "why": [
      "P4 because it only removes the boost-test package from depends and vcpkg.",
      "Boost remains a dependency for multi_index, making this a minor build-cleanup change."
     ]
    }
   ]
  },
  "summary": "This pull request replaces the Boost.Test unit test framework with an in-house, header-only test runner in `src/test/util/framework.h`. It migrates all unit test files to the new framework headers while providing backwards-compatible macro aliases, introduces assertion expression decomposition for improved failure diagnostics, and removes the Boost.Test library from depends and vcpkg.",
  "problem": "Boost.Test requires managing an external dependency with awkward workarounds, exhibits inconsistent failure diagnostics across different assertion macros (`BOOST_CHECK`, `BOOST_CHECK_EQUAL`, `BOOST_TEST`), and lacks tailoring for Bitcoin Core-specific testing requirements such as concurrency.",
  "discussion": {
   "open_concerns": [],
   "resolved_concerns": [
    "maflcko noted that comparing unsupported types should remain a compile-time static assertion rather than falling back to printing runtime type names; resolved by adding a static assertion and a `CHECK_NO_DISPLAY` opt-out macro.",
    "jeanpablojp identified several regressions including segfaults on null C-strings, lost test output during crashes due to missing `std::cout` flushes, non-reproducible test ordering with `BOOST_TEST_RANDOM`, and dropping `-Wl,--fatal-warnings` from Linux Guix builds; resolved by author pushes on 2026-09-10."
   ],
   "author_status": "active, addressed reviewer feedback and force-pushed updates"
  },
  "reviewability": {
   "state": "Ready",
   "label": "Ready",
   "reason": "The PR is rebased and mergeable, CI is passing, and the author addressed all concrete issues raised in the latest review."
  },
  "agreement": {
   "participants": [
    {
     "login": "josibake",
     "stance": "support",
     "note": "Concept ACK highlighting customization and enabling future test concurrency improvements"
    },
    {
     "login": "maflcko",
     "stance": "objection",
     "note": "raised objections against fallback type names and linker issues, and helped shape the static_assert approach"
    },
    {
     "login": "fanquake",
     "stance": "neutral",
     "note": "inquired about header-only Boost usage and suggested constexpr updates"
    },
    {
     "login": "jeanpablojp",
     "stance": "objection",
     "note": "Concept ACK with detailed code review pointing out regressions in stdout flushing, null handling, random seeds, and Guix flags"
    }
   ],
   "objections": [
    {
     "reviewer": "maflcko",
     "kind": "approach",
     "harm": "silently printing mangled type names instead of failing compilation when formatting is missing",
     "blocking": false,
     "author_replied": true,
     "fix_pushed": true,
     "status": "resolved",
     "evidence": "2026-07-13: 'This should remain a compile failure, like it is on current master.'",
     "resolution_evidence": "2026-07-20: Author pushed commit adding static_assert: '05397f7c0881265f1b108e8e2544c889d7c8b830 moves to a static_assert'",
     "sources": [
      "dossier",
      "thread"
     ]
    },
    {
     "reviewer": "jeanpablojp",
     "kind": "correctness",
     "harm": "segfaulting if either side of a string comparison is null",
     "blocking": false,
     "author_replied": true,
     "fix_pushed": true,
     "status": "resolved",
     "evidence": "2026-08-30: 'With either side null this segfaults instead of reporting the failure.'",
     "resolution_evidence": "2026-09-10: 'Added a check if either side is null so it does not go through strcmp'",
     "sources": [
      "dossier",
      "dossier",
      "dossier",
      "dossier",
      "thread",
      "thread",
      "thread",
      "thread",
      "thread",
      "thread"
     ]
    }
   ],
   "support": [
    {
     "reviewer": "josibake",
     "reason": "Having our own simple, in house test framework gives us the ability to customise it for exactly our needs, removing barriers to writing tests and unblocking concurrency improvements",
     "substantive": true
    },
    {
     "reviewer": "jeanpablojp",
     "reason": "Confirmed test suite passes and scripted-diff reproduces correctly",
     "substantive": true
    }
   ],
   "state": "Strong",
   "summary": "Strong concept agreement from multiple reviewers; all technical review objections have been addressed.",
   "reason": "There is substantive Concept ACK support from josibake and jeanpablojp. Technical concerns raised by maflcko and jeanpablojp regarding string formatting, null checks, buffering, and random seeds were promptly addressed by the author.",
   "evidence": [
    "josibake provided a Strong Concept ACK endorsing in-house test framework customization.",
    "jeanpablojp gave a Concept ACK while providing rigorous technical feedback.",
    "Author resolved all identified behavior gaps in subsequent pushes."
   ],
   "model_state": "Strong",
   "derivation": "substantive support, no open objection (josibake, jeanpablojp)",
   "corrections": [],
   "thread_read": {
    "state": "Strong",
    "derived": "Strong",
    "objections": [
     {
      "reviewer": "maflcko",
      "kind": "correctness",
      "harm": "printing type name fallback instead of failing compilation when formatting is missing",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-07-13: \"As explained in https://github.com/bitcoin/bitcoin/pull/35625#issuecomment-4845221857, I still don't think this makes sense. The only change is that some compile-time type name may be printed for both sides. This should remain a compile failure, like it is on current master.\"",
      "resolution_evidence": "2026-07-20: \"05397f7c0881265f1b108e8e2544c889d7c8b830 moves to a `static_assert`.\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "comparing null cstrings causes a segfault instead of reporting a test failure",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"With either side null this segfaults instead of reporting the failure. On master two nulls pass and one null reports a failure.\"",
      "resolution_evidence": "2026-09-10: \"Added a check if either side is null so it does not go through strcmp\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "stdout is not flushed, hiding crash outputs and duplicating output across process forks",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"This never flushes. With a crash inside a test case and output redirected, master keeps the preceding lines and here the file comes back empty... The same buffer causes a second, smaller thing. test_LockDirectory forks and the child exits with exit(0), reprinting what it inherited\"",
      "resolution_evidence": "2026-09-10: \"I think a cout flush should solve these. Updated in latest push.\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "interface",
      "harm": "runner flags and BOOST_TEST_RUN_FILTERS are ignored, breaking test coverage and libmultiprocess CI scripts",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"BOOST_TEST_RUN_FILTERS is no longer read, so deterministic-unittest-coverage runs the whole binary instead of the suite it was given. bitcoin_core_ci.sh in the libmultiprocess subtree still passes three Boost.Test flags, and any one of them now makes it exit with code 2\"",
      "resolution_evidence": "2026-09-10: \"I added a catch_system_error flag for compatibility as well as a separation between the summary and log level.\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "BOOST_TEST_RANDOM value is ignored and seed is not reported, preventing reproduction of order-dependent failures",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"Here the value is only checked for presence, never read, so 0 and an empty string both turn shuffling on and a fixed seed no longer reproduces... Boost also prints the seed it used, which here doesn't come out at any level, so there's no way to reproduce an order-dependent failure.\"",
      "resolution_evidence": "2026-09-10: \"Fixed by using a random seed and printing it if equal to 1, and setting the seed directly if > 1. 0 and null do nothing, thanks.\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "dropping the Guix workaround removed -Wl,--fatal-warnings for all Linux builds",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"Dropping the whole block means no Linux host links with -Wl,--fatal-warnings any more, while build_win.sh and build_win_gui.sh keep it... Would it make sense to keep the flag for every host now that riscv64 is clean?\"",
      "resolution_evidence": "2026-09-10: \"Added Wl, --fatal-warnings on head commit, lmk if thats what you mean\""
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "TEST_CASE does not execute the suite fixture constructor",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: \"TEST_SUITE_BEGIN(suite, Fixture) sets btc_suite_fixture, but TEST_CASE registers a plain function and never uses it.\"",
      "resolution_evidence": "2026-09-10: \"Seems fine. I would think it very strange to update a global as part of a test fixture, but this is a code reduction and should hopefully simplify review.\""
     }
    ],
    "support": [
     {
      "reviewer": "josibake",
      "reason": "An in-house test framework gives complete control to tailor testing to Bitcoin Core's needs, lowers barriers for test authoring, and facilitates future concurrency work to speed up CI",
      "substantive": true
     },
     {
      "reviewer": "jeanpablojp",
      "reason": "Concept ACK; confirmed the test suite passes and scripted-diff reproduces",
      "substantive": false
     }
    ],
    "participants": [
     {
      "login": "josibake",
      "stance": "support",
      "note": "Strong Concept ACK highlighting custom framework flexibility and concurrency improvements"
     },
     {
      "login": "maflcko",
      "stance": "objection",
      "note": "objected to fallback stringification without compile-time failure and suggested static asserts"
     },
     {
      "login": "fanquake",
      "stance": "neutral",
      "note": "asked about boost instrumentation and discussed converting static const to inline constexpr"
     },
     {
      "login": "jeanpablojp",
      "stance": "objection",
      "note": "Concept ACK but identified bugs including null cstring segfaults, missing output flushing, and test script incompatibilities"
     }
    ],
    "corrections": [],
    "summary": "Strong: josibake strongly supports an in-house test framework; criticisms from maflcko and jeanpablojp regarding stringification, null checks, buffering, and compatibility were resolved",
    "usage": {
     "input_tokens": 11472,
     "cache_creation_input_tokens": 0,
     "cache_read_input_tokens": 0,
     "output_tokens": 7476
    }
   },
   "first_read": {
    "state": "Strong",
    "model_state": "Strong",
    "objections": [
     {
      "reviewer": "maflcko",
      "kind": "approach",
      "harm": "silently printing mangled type names instead of failing compilation when formatting is missing",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-07-13: 'This should remain a compile failure, like it is on current master.'",
      "resolution_evidence": "2026-07-20: Author pushed commit adding static_assert: '05397f7c0881265f1b108e8e2544c889d7c8b830 moves to a static_assert'"
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "segfaulting if either side of a string comparison is null",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: 'With either side null this segfaults instead of reporting the failure.'",
      "resolution_evidence": "2026-09-10: 'Added a check if either side is null so it does not go through strcmp'"
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "leaving output files completely empty on test crashes due to unbuffered stdout",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: 'This never flushes. With a crash inside a test case and output redirected... the file comes back empty.'",
      "resolution_evidence": "2026-09-10: 'I think a cout flush should solve these. Updated in latest push.'"
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "inability to reproduce test execution order with a fixed BOOST_TEST_RANDOM seed",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: 'Here the value is only checked for presence, never read... so a fixed seed no longer reproduces.'",
      "resolution_evidence": "2026-09-10: 'Fixed by using a random seed and printing it if equal to 1, and setting the seed directly if > 1.'"
     },
     {
      "reviewer": "jeanpablojp",
      "kind": "correctness",
      "harm": "dropping -Wl,--fatal-warnings across all Linux Guix hosts instead of only removing the riscv64 workaround",
      "blocking": false,
      "author_replied": true,
      "fix_pushed": true,
      "status": "resolved",
      "evidence": "2026-08-30: 'Dropping the whole block means no Linux host links with -Wl,--fatal-warnings any more...'",
      "resolution_evidence": "2026-09-10: 'Added Wl, --fatal-warnings on head commit, lmk if thats what you mean'"
     }
    ],
    "support": [
     {
      "reviewer": "josibake",
      "reason": "Having our own simple, in house test framework gives us the ability to customise it for exactly our needs, removing barriers to writing tests and unblocking concurrency improvements",
      "substantive": true
     },
     {
      "reviewer": "jeanpablojp",
      "reason": "Confirmed test suite passes and scripted-diff reproduces correctly",
      "substantive": true
     }
    ]
   }
  },
  "dependencies": {
   "depends_on": [],
   "enables": [
    "Future concurrency in unit testing runner to accelerate CI"
   ]
  },
  "categories": [
   {
    "name": "build",
    "member": true,
    "evidence": "Modifies depends/packages/boost.mk, vcpkg.json, and contrib/guix/libexec/build_linux.sh to drop the Boost.Test package and its build workarounds.",
    "band": "P4",
    "reason_tag": "cleanup",
    "score": 0.2,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 1
    },
    "rationale": "P4 because removing the Boost.Test component from depends and vcpkg is a minor dependency cleanup that does not remove Boost completely (Boost Multi-Index is retained)."
   },
   {
    "name": "ipc",
    "member": false,
    "evidence": "Changes to src/ipc/test/ipc_tests.cpp are purely mechanical header substitutions following from the test framework migration.",
    "band": "Unranked",
    "reason_tag": "",
    "score": 0.0,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 0
    },
    "rationale": "Mechanical test adjustments following from a framework change elsewhere do not qualify the PR for membership."
   },
   {
    "name": "kernel",
    "member": false,
    "evidence": "Changes to src/test/kernel/test_kernel.cpp are mechanical header and macro replacements.",
    "band": "Unranked",
    "reason_tag": "",
    "score": 0.0,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 0
    },
    "rationale": "Does not touch the kernel API or its boundaries."
   },
   {
    "name": "tests",
    "member": true,
    "evidence": "Introduces a complete custom test runner in src/test/util/framework.h and migrates the entire unit test suite away from Boost.Test.",
    "band": "P3",
    "reason_tag": "cleanup",
    "score": 0.4,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 2
    },
    "rationale": "P3 because replacing the test runner provides clear maintainability value and cleaner assertions across test files, but is reasonably deferrable as it does not fix an active test breakage or immediately speed up CI."
   },
   {
    "name": "tools",
    "member": false,
    "evidence": "The script modified (build_linux.sh) belongs to the build category.",
    "band": "Unranked",
    "reason_tag": "",
    "score": 0.0,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 0
    },
    "rationale": "Does not touch developer or operator CLI tools."
   },
   {
    "name": "wallet",
    "member": false,
    "evidence": "Edits to wallet test files are purely mechanical macro and header substitutions.",
    "band": "Unranked",
    "reason_tag": "",
    "score": 0.0,
    "factors": {
     "security_stability": 0,
     "bug_severity": 0,
     "performance": 0,
     "user_value": 0,
     "leverage": 0
    },
    "rationale": "Does not change wallet behavior, interfaces, or wallet data."
   }
  ],
  "confidence": "high",
  "uncertainties": [],
  "needs": [],
  "card": "This pull request removes Boost.Test across the unit test suite and introduces an in-house header-only testing framework in src/test/util/framework.h. It solves long-standing issues with Boost test assertion consistency, provides cleaner expression decomposition on test failures, and drops Boost.Test from depends. There is strong conceptual support from reviewers, and critical issues regarding output flushing, null string checks, and random test order reproduction have been resolved. The PR is currently ready for review without blocking dependencies."
 },
 "raw_text": null,
 "prompt_hash": "c1bd47c5",
 "second_read_cost_usd": 0.036639
}