tests: use getroutes, not getroute (simple cases)
What changed, and why it matters
This commit only changes test code. It replaces direct calls to the older getroute() RPC helper with a new single_route() wrapper that internally uses the newer getroutes() API. There is no change to production code, no bug fix, and no security relevance.
No action required. This is a routine test maintenance/refactor commit with no security implications.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is a pure test refactor across five Python test files. Each change follows the same pattern: node.rpc.getroute(dest, amount, 1)['route'] is replaced by node.single_route(dest, amount). The wrapper is presumably defined in the test framework and returns a single route from getroutes(). The commit also adds dev_use_shadow=False to one xpay test call, which is a test-only developer flag. No C/lightningd source, RPC semantics, or cryptographic logic is modified.
Changed components
tests/test_closing.pytests/test_misc.pytests/test_pay.pytests/test_plugin.pytests/test_xpay.pyInspect captured patch +43 / −43
diff --git a/tests/test_closing.py b/tests/test_closing.py
index 9dec96d7..899ee73f 100644
--- a/tests/test_closing.py
+++ b/tests/test_closing.py
@@ -1258,7 +1258,7 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams, anchors):
# now we send one 'sticky' htlc: l4->l1
amt = 10**8 // 2
sticky_inv = l1.rpc.invoice(amt, '2', 'sticky')
- route = l4.rpc.getroute(l1.info['id'], amt, 1)['route']
+ route = l4.single_route(l1.info['id'], amt)
l4.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret'])
l1.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
@@ -1449,12 +1449,12 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams, anchors):
# now we send two 'sticky' htlcs, l1->l5 + l4->l1
amt = 10**8 // 2
sticky_inv_1 = l5.rpc.invoice(amt, '2', 'sticky')
- route = l1.rpc.getroute(l5.info['id'], amt, 1)['route']
+ route = l1.single_route(l5.info['id'], amt)
l1.rpc.sendpay(route, sticky_inv_1['payment_hash'], payment_secret=sticky_inv_1['payment_secret'])
l5.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
sticky_inv_2 = l1.rpc.invoice(amt, '2', 'sticky')
- route = l4.rpc.getroute(l1.info['id'], amt, 1)['route']
+ route = l4.single_route(l1.info['id'], amt)
l4.rpc.sendpay(route, sticky_inv_2['payment_hash'], payment_secret=sticky_inv_2['payment_secret'])
l1.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
@@ -2121,7 +2121,7 @@ def test_onchain_middleman_simple(node_factory, bitcoind, chainparams, anchors):
inv = l3.rpc.invoice(10**8, 'middleman', 'desc')
rhash = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], 10**8, 1)["route"]
+ route = l1.single_route(l3.info['id'], 10**8)
assert len(route) == 2
q = queue.Queue()
@@ -2260,7 +2260,7 @@ def test_onchain_middleman_their_unilateral_in(node_factory, bitcoind, chainpara
inv = l3.rpc.invoice(10**8, 'middleman', 'desc')
rhash = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], 10**8, 1)["route"]
+ route = l1.single_route(l3.info['id'], 10**8)
assert len(route) == 2
q = queue.Queue()
@@ -2368,7 +2368,7 @@ def test_onchain_their_unilateral_out(node_factory, bitcoind, chainparams, ancho
{**opts, **{'disconnect': disconnects}}])
channel_id = first_channel_id(l1, l2)
- route = l1.rpc.getroute(l2.info['id'], 10**8, 1)["route"]
+ route = l1.single_route(l2.info['id'], 10**8)
assert len(route) == 1
q = queue.Queue()
@@ -3706,7 +3706,7 @@ We send an HTLC, and peer unilaterally closes: do we close upstream?
ph1 = l3.rpc.invoice(amount_msat="10000sat", label='x1', description='desc2')['payment_hash']
ph2 = l3.rpc.invoice(amount_msat="10000sat", label='x2', description='desc2')['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], 1, 1)['route']
+ route = l1.single_route(l3.info['id'], 1)
# Start a payment
l1.rpc.sendpay(route, ph1)
@@ -4028,7 +4028,7 @@ def test_peer_anchor_push(node_factory, bitcoind, executor, chainparams):
# Get HTLC stuck, so l2 has reason to push commitment tx.
amt = 100_000_000
sticky_inv = l3.rpc.invoice(amt, 'sticky', 'sticky')
- route = l1.rpc.getroute(l3.info['id'], amt, 1)['route']
+ route = l1.single_route(l3.info['id'], amt)
l1.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret'])
l3.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
@@ -4229,7 +4229,7 @@ def test_anchorspend_using_to_remote(node_factory, bitcoind, anchors):
# Get HTLC stuck, so l2 has reason to push commitment tx.
amt = 100_000_000
sticky_inv = l3.rpc.invoice(amt, 'sticky', 'sticky')
- route = l1.rpc.getroute(l3.info['id'], amt, 1)['route']
+ route = l1.single_route(l3.info['id'], amt)
l1.rpc.sendpay(route, sticky_inv['payment_hash'], payment_secret=sticky_inv['payment_secret'])
l3.daemon.wait_for_log('dev_disconnect: -WIRE_UPDATE_FULFILL_HTLC')
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 3fcf133e..b1f26bb2 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -2198,7 +2198,7 @@ def test_bad_onion_immediate_peer(node_factory, bitcoind):
l1, l2 = node_factory.line_graph(2, opts=[{}, {'dev-fail-process-onionpacket': None}])
inv = l2.rpc.invoice(123000, 'test_bad_onion_immediate_peer', 'description')
- route = l1.rpc.getroute(l2.info['id'], 123000, 1)['route']
+ route = l1.single_route(l2.info['id'], 123000)
assert len(route) == 1
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
@@ -3419,7 +3419,7 @@ def test_listforwards_and_listhtlcs(node_factory, bitcoind):
# failed payment
failed_inv = l3.rpc.invoice(4000, 'failed', 'desc')
- failed_route = l1.rpc.getroute(l3.info['id'], 4000, 1)['route']
+ failed_route = l1.single_route(l3.info['id'], 4000)
l2.rpc.close(c23)
diff --git a/tests/test_pay.py b/tests/test_pay.py
index 0d6ab046..7737a6c2 100644
--- a/tests/test_pay.py
+++ b/tests/test_pay.py
@@ -270,7 +270,7 @@ def test_pay_disconnect(node_factory, bitcoind):
rhash = inv['payment_hash']
# Can't use `pay` since that'd notice that we can't route, due to disabling channel_update
- route = l1.rpc.getroute(l2.info['id'], 123000, 1)["route"]
+ route = l1.single_route(l2.info['id'], 123000)
l2.stop()
# Make sure channeld has exited!
@@ -1479,13 +1479,13 @@ def test_forward_stats(node_factory, bitcoind):
inv = l3.rpc.invoice(amount, "first", "desc")
payment_hash = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret'])
l1.rpc.waitsendpay(payment_hash)
# l4 rejects since it doesn't know the payment_hash
- route = l1.rpc.getroute(l4.info['id'], amount, 1)['route']
+ route = l1.single_route(l4.info['id'], amount)
payment_hash = "F" * 64
with pytest.raises(RpcError):
l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret'])
@@ -1493,7 +1493,7 @@ def test_forward_stats(node_factory, bitcoind):
# l5 will hold the HTLC hostage.
l5.rpc.dev_ignore_htlcs(id=l2.info['id'], ignore=True)
- route = l1.rpc.getroute(l5.info['id'], amount, 1)['route']
+ route = l1.single_route(l5.info['id'], amount)
inv = l5.rpc.invoice(amount, "first", "desc")
payment_hash = inv['payment_hash']
l1.rpc.sendpay(route, payment_hash, payment_secret=inv['payment_secret'])
@@ -1618,7 +1618,7 @@ def test_forward_local_failed_stats(node_factory, bitcoind, executor):
inv = l3.rpc.invoice(amount, "first", "desc")
payment_hash = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
l2.rpc.close(c23, 1)
@@ -1777,7 +1777,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind):
l4.rpc.dev_ignore_htlcs(id=l3.info['id'], ignore=True)
# L2 tries to pay
- r = l2.rpc.getroute(l4.info['id'], 10**8, 1)["route"]
+ r = l2.single_route(l4.info['id'], 10**8)
l2.rpc.sendpay(r, h, payment_secret=inv['payment_secret'])
# Now increment CLTV
@@ -1785,7 +1785,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind):
sync_blockheight(bitcoind, [l1, l2, l3, l4])
# L1 tries to pay
- r = l1.rpc.getroute(l4.info['id'], 10**8, 1)["route"]
+ r = l1.single_route(l4.info['id'], 10**8)
l1.rpc.sendpay(r, h, payment_secret=inv['payment_secret'])
# Now increment CLTV
@@ -1793,7 +1793,7 @@ def test_htlcs_cltv_only_difference(node_factory, bitcoind):
sync_blockheight(bitcoind, [l1, l2, l3, l4])
# L3 tries to pay
- r = l3.rpc.getroute(l4.info['id'], 10**8, 1)["route"]
+ r = l3.single_route(l4.info['id'], 10**8)
l3.rpc.sendpay(r, h, payment_secret=inv['payment_secret'])
# Give them time to go through.
@@ -2843,7 +2843,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams):
num_dusty_htlcs = max_dust_limit_sat // htlc_val_sat
# add a some non-dusty htlcs, these will fail when we raise the dust limit
- route = l1.rpc.getroute(l2.info['id'], non_dust_htlc_val_sat * 1000, 1)['route']
+ route = l1.single_route(l2.info['id'], non_dust_htlc_val_sat * 1000)
for i in range(0, 3):
inv = l2.rpc.invoice((non_dust_htlc_val_sat * 1000), str(i + 100), str(i + 100))
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
@@ -2852,7 +2852,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams):
assert res['status'] == 'pending'
# add some dusty-htlcs
- route = l1.rpc.getroute(l2.info['id'], htlc_val_msat, 1)['route']
+ route = l1.single_route(l2.info['id'], htlc_val_msat)
for i in range(0, num_dusty_htlcs):
inv = l2.rpc.invoice(htlc_val_msat, str(i), str(i))
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
@@ -2867,7 +2867,7 @@ def test_htlc_too_dusty_outgoing(node_factory, bitcoind, chainparams):
wait_for(lambda: only_one(l1.rpc.listsendpays(payment_hash=inv['payment_hash'])['payments'])['status'] == 'failed')
# but we can still add a non dust htlc
- route = l1.rpc.getroute(l2.info['id'], non_dust_htlc_val_sat * 1000, 1)['route']
+ route = l1.single_route(l2.info['id'], non_dust_htlc_val_sat * 1000)
inv = l2.rpc.invoice((10000 * 1000), str(120), str(120))
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
l2.daemon.wait_for_log(r'their htlc .* dev_ignore_htlcs')
@@ -2895,7 +2895,7 @@ def test_htlc_too_dusty_incoming(node_factory, bitcoind):
htlc_val_sat = 250
htlc_val_msat = htlc_val_sat * 1000
num_dusty_htlcs = max_dust_limit_sat // htlc_val_sat
- route = l1.rpc.getroute(l3.info['id'], htlc_val_msat, 1)['route']
+ route = l1.single_route(l3.info['id'], htlc_val_msat)
# l1 sends as much money as it can
for i in range(0, num_dusty_htlcs):
@@ -3261,7 +3261,7 @@ def test_partial_payment_timeout(node_factory, bitcoind):
inv = l2.rpc.invoice(1000, 'inv', 'inv')
paysecret = l2.rpc.decode(inv['bolt11'])['payment_secret']
- route = l1.rpc.getroute(l2.info['id'], 500, 1)['route']
+ route = l1.single_route(l2.info['id'], 500)
l1.rpc.sendpay(
route=route,
payment_hash=inv['payment_hash'],
@@ -3316,7 +3316,7 @@ def test_partial_payment_restart(node_factory, bitcoind):
inv = l3.rpc.invoice(1000, 'inv', 'inv')
paysecret = l3.rpc.decode(inv['bolt11'])['payment_secret']
- route = l1.rpc.getroute(l3.info['id'], 500, 1)['route']
+ route = l1.single_route(l3.info['id'], 500)
l1.rpc.sendpay(
route=route,
@@ -3361,7 +3361,7 @@ def test_partial_payment_htlc_loss(node_factory, bitcoind):
inv = l3.rpc.invoice(1000, 'inv', 'inv')
paysecret = l3.rpc.decode(inv['bolt11'])['payment_secret']
- route = l1.rpc.getroute(l3.info['id'], 500, 1)['route']
+ route = l1.single_route(l3.info['id'], 500)
l1.rpc.sendpay(route=route, payment_hash=inv['payment_hash'], amount_msat=1000, bolt11=inv['bolt11'], payment_secret=paysecret, partid=1)
@@ -3433,18 +3433,18 @@ caused a crash in 0.8.0, so we then disallowed it.
with pytest.raises(RpcError, match=r'Do not specify msatoshi \(1001msat\) without'
' partid: if you do, it must be exactly'
r' the final amount \(1000msat\)'):
- l1.rpc.sendpay(route=l1.rpc.getroute(l2.info['id'], 1000, 1)['route'], payment_hash=inv['payment_hash'], amount_msat=1001, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
+ l1.rpc.sendpay(route=l1.single_route(l2.info['id'], 1000), payment_hash=inv['payment_hash'], amount_msat=1001, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
with pytest.raises(RpcError, match=r'Do not specify msatoshi \(999msat\) without'
' partid: if you do, it must be exactly'
r' the final amount \(1000msat\)'):
- l1.rpc.sendpay(route=l1.rpc.getroute(l2.info['id'], 1000, 1)['route'], payment_hash=inv['payment_hash'], amount_msat=999, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
+ l1.rpc.sendpay(route=l1.single_route(l2.info['id'], 1000), payment_hash=inv['payment_hash'], amount_msat=999, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
# Can't send MPP payment which pays any more than amount.
with pytest.raises(RpcError, match=r'Final amount 1001msat is greater than 1000msat, despite MPP'):
- l1.rpc.sendpay(route=l1.rpc.getroute(l2.info['id'], 1001, 1)['route'], payment_hash=inv['payment_hash'], amount_msat=1000, bolt11=inv['bolt11'], partid=1, payment_secret=inv['payment_secret'])
+ l1.rpc.sendpay(route=l1.single_route(l2.info['id'], 1001), payment_hash=inv['payment_hash'], amount_msat=1000, bolt11=inv['bolt11'], partid=1, payment_secret=inv['payment_secret'])
# But this works
- l1.rpc.sendpay(route=l1.rpc.getroute(l2.info['id'], 1001, 1)['route'], payment_hash=inv['payment_hash'], amount_msat=1001, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
+ l1.rpc.sendpay(route=l1.single_route(l2.info['id'], 1001), payment_hash=inv['payment_hash'], amount_msat=1001, bolt11=inv['bolt11'], payment_secret=inv['payment_secret'])
l1.rpc.waitsendpay(inv['payment_hash'])
inv = only_one(l2.rpc.listinvoices('inv')['invoices'])
diff --git a/tests/test_plugin.py b/tests/test_plugin.py
index 2a40d475..d663cf94 100644
--- a/tests/test_plugin.py
+++ b/tests/test_plugin.py
@@ -1202,7 +1202,7 @@ def test_htlc_accepted_hook_fail(node_factory):
# This must fail
inv = l2.rpc.invoice(1000, "lbl", "desc")
phash = inv['payment_hash']
- route = l1.rpc.getroute(l2.info['id'], 1000, 1)['route']
+ route = l1.single_route(l2.info['id'], 1000)
# Here shouldn't use `pay` command because l2 rejects with WIRE_TEMPORARY_NODE_FAILURE,
# then it will be excluded when l1 try another pay attempt.
@@ -1507,14 +1507,14 @@ def test_forward_event_notification(node_factory, bitcoind, executor):
inv = l3.rpc.invoice(amount, "first", "desc")
payment_hash13 = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
# status: offered -> settled
l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret'])
l1.rpc.waitsendpay(payment_hash13)
# status: offered -> failed
- route = l1.rpc.getroute(l4.info['id'], amount, 1)['route']
+ route = l1.single_route(l4.info['id'], amount)
payment_hash14 = "f" * 64
with pytest.raises(RpcError):
l1.rpc.sendpay(route, payment_hash14, payment_secret="f" * 64)
@@ -1622,7 +1622,7 @@ def test_sendpay_notifications(node_factory, bitcoind):
payment_hash1 = inv1['payment_hash']
inv2 = l3.rpc.invoice(amount, "second", "desc")
payment_hash2 = inv2['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
l1.rpc.sendpay(route, payment_hash1, payment_secret=inv1['payment_secret'])
response1 = l1.rpc.waitsendpay(payment_hash1)
@@ -1653,7 +1653,7 @@ def test_sendpay_notifications_nowaiter(node_factory):
payment_hash1 = inv1['payment_hash']
inv2 = l3.rpc.invoice(amount, "second", "desc")
payment_hash2 = inv2['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
l1.rpc.sendpay(route, payment_hash1, payment_secret=inv1['payment_secret'])
l1.daemon.wait_for_log(r'Received a sendpay_success')
@@ -2446,14 +2446,14 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
inv = l3.rpc.invoice(amount, "first", "desc")
payment_hash13 = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
# status: offered -> settled
l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret'])
l1.rpc.waitsendpay(payment_hash13)
# status: offered -> failed
- route = l1.rpc.getroute(l3.info['id'], amount, 1)['route']
+ route = l1.single_route(l3.info['id'], amount)
payment_hash13 = "f" * 64
with pytest.raises(RpcError):
l1.rpc.sendpay(route, payment_hash13, payment_secret=inv['payment_secret'])
@@ -2462,14 +2462,14 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
# go the other direction
inv = l1.rpc.invoice(amount // 2, "first", "desc")
payment_hash31 = inv['payment_hash']
- route = l3.rpc.getroute(l1.info['id'], amount // 2, 1)['route']
+ route = l3.single_route(l1.info['id'], amount // 2)
l3.rpc.sendpay(route, payment_hash31, payment_secret=inv['payment_secret'])
l3.rpc.waitsendpay(payment_hash31)
# receive a payment (endpoint)
inv = l2.rpc.invoice(amount, "first", "desc")
payment_hash12 = inv['payment_hash']
- route = l1.rpc.getroute(l2.info['id'], amount, 1)['route']
+ route = l1.single_route(l2.info['id'], amount)
l1.rpc.sendpay(route, payment_hash12, payment_secret=inv['payment_secret'])
l1.rpc.waitsendpay(payment_hash12)
@@ -2478,7 +2478,7 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams):
payment_hash21 = inv['payment_hash']
# Make sure previous completely settled
wait_for(lambda: only_one(l2.rpc.listpeerchannels(l1.info['id'])['channels'])['htlcs'] == [])
- route = l2.rpc.getroute(l1.info['id'], amount // 2, 1)['route']
+ route = l2.single_route(l1.info['id'], amount // 2)
l2.rpc.sendpay(route, payment_hash21, payment_secret=inv['payment_secret'])
l2.rpc.waitsendpay(payment_hash21)
@@ -2741,7 +2741,7 @@ def test_htlc_accepted_hook_malformedtlvs(node_factory):
l2.rpc.setcustomtlvs(tlvs=mal_tlv)
inv = l3.rpc.invoice(1000, 'customtlvs-maltlvs', '')
phash = inv['payment_hash']
- route = l1.rpc.getroute(l3.info['id'], 1000, 1)['route']
+ route = l1.single_route(l3.info['id'], 1000)
# Here shouldn't use `pay` command because l2 should fail with a broken log.
l1.rpc.sendpay(route, phash, payment_secret=inv['payment_secret'])
@@ -4252,7 +4252,7 @@ def test_sql(node_factory, bitcoind):
# And I need at least one HTLC in-flight so listpeers.channels.htlcs isn't empty:
l3.rpc.plugin_start(os.path.join(os.getcwd(), 'tests/plugins/hold_invoice.py'))
inv = l3.rpc.invoice(amount_msat=12300, label='inv3', description='description')
- route = l1.rpc.getroute(l3.info['id'], 12300, 1)['route']
+ route = l1.single_route(l3.info['id'], 12300)
l1.rpc.sendpay(route, inv['payment_hash'], payment_secret=inv['payment_secret'])
# And an in-flight channel open...
l2.openchannel(l3, confirm=False, wait_for_announce=False)
diff --git a/tests/test_xpay.py b/tests/test_xpay.py
index f708a54d..97938947 100644
--- a/tests/test_xpay.py
+++ b/tests/test_xpay.py
@@ -718,7 +718,7 @@ def test_fail_after_success(node_factory, bitcoind, executor, slow_mode):
wait_for(lambda: len(l1.rpc.listchannels()['channels']) == 10)
inv = l5.rpc.invoice(800000000, 'test_xpay_slow_mode', 'test_xpay_slow_mode', preimage='00' * 32)['bolt11']
- fut = executor.submit(l1.rpc.xpay, invstring=inv, retry_for=0)
+ fut = executor.submit(l1.rpc.xpay, invstring=inv, retry_for=0, dev_use_shadow=False)
# Part via l3 is fine. Part via l4 is stuck, so we kill l4 and mine
# blocks to make l2 force close.
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.