forge: add patch 12 — spell out hops/byte, drop channel name in test ack

Test response now reads:
  @[user] | 2 hops, 2-byte hashes, SNR -1.25 | recv 21:25:45
(was: @[user] #bot | 2h@2B SNR -1.25 | recv 21:25:45)

Path response now reads:
  Path @[user] 6 hops, 2-byte hashes, SNR -8.50 | <path>
(was: Path @[user] 6h@2B SNR -8.50 | <path>)

DM responses keep 'direct' indicator. Trace and other commands
unchanged for now. Tests updated for the new strings.

Submodule pointer stays at upstream 910b1bee so CI submodule clone
succeeds; apply-patches.sh applies the queue at build time.
This commit is contained in:
cj-vana
2026-05-16 21:32:19 -06:00
parent 0670688b7b
commit 5f35af7854
13 changed files with 113 additions and 22 deletions

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 11:44:21 -0600 Date: Fri, 15 May 2026 11:44:21 -0600
Subject: [PATCH 01/11] Add companion radio firmware bot command parity Subject: [PATCH 01/12] Add companion radio firmware bot command parity
--- ---
.../companion_radio/BotCommandRegistry.cpp | 121 ++ .../companion_radio/BotCommandRegistry.cpp | 121 ++

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 19:58:42 -0600 Date: Fri, 15 May 2026 19:58:42 -0600
Subject: [PATCH 02/11] Harden firmware bot response coordination Subject: [PATCH 02/12] Harden firmware bot response coordination
--- ---
examples/companion_radio/BotCommands.cpp | 2 +- examples/companion_radio/BotCommands.cpp | 2 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Fri, 15 May 2026 20:09:58 -0600 Date: Fri, 15 May 2026 20:09:58 -0600
Subject: [PATCH 03/11] Allow prefixless firmware bot DMs Subject: [PATCH 03/12] Allow prefixless firmware bot DMs
--- ---
examples/companion_radio/BotPolicy.cpp | 2 +- examples/companion_radio/BotPolicy.cpp | 2 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 04:12:02 +0000 Date: Sat, 16 May 2026 04:12:02 +0000
Subject: [PATCH 04/11] Align firmware bot commands with upstream behavior Subject: [PATCH 04/12] Align firmware bot commands with upstream behavior
--- ---
.../companion_radio/BotCommandRegistry.cpp | 25 +- .../companion_radio/BotCommandRegistry.cpp | 25 +-

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 12:38:13 -0600 Date: Sat, 16 May 2026 12:38:13 -0600
Subject: [PATCH 05/11] Add hop-aware bot coordination, utility commands, and Subject: [PATCH 05/12] Add hop-aware bot coordination, utility commands, and
bounded delays bounded delays
Adds new utility commands (TIME, LORA, ID, NEIGHBORS), neighbor tracking, Adds new utility commands (TIME, LORA, ID, NEIGHBORS), neighbor tracking,

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 18:58:28 -0600 Date: Sat, 16 May 2026 18:58:28 -0600
Subject: [PATCH 06/11] Mark bot adverts, speed up initial advert, default Subject: [PATCH 06/12] Mark bot adverts, speed up initial advert, default
contacts auto-overwrite contacts auto-overwrite
Three coordination/discoverability fixes: Three coordination/discoverability fixes:

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 19:33:04 -0600 Date: Sat, 16 May 2026 19:33:04 -0600
Subject: [PATCH 07/11] Prefix bot responses with request token for inter-bot Subject: [PATCH 07/12] Prefix bot responses with request token for inter-bot
suppression suppression
Adds a 4-hex request token (low 16 bits of the request fingerprint) as a Adds a 4-hex request token (low 16 bits of the request fingerprint) as a

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 19:55:36 -0600 Date: Sat, 16 May 2026 19:55:36 -0600
Subject: [PATCH 08/11] Drop [MCBOT] advert suffix and auto-learn known-bot Subject: [PATCH 08/12] Drop [MCBOT] advert suffix and auto-learn known-bot
path path
Removes BOT_ADVERT_MARKER / writeBotAdvertName / isBotAdvertName from Removes BOT_ADVERT_MARKER / writeBotAdvertName / isBotAdvertName from

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 20:05:19 -0600 Date: Sat, 16 May 2026 20:05:19 -0600
Subject: [PATCH 09/11] Widen hop-step + drop "ack " prefix from test response Subject: [PATCH 09/12] Widen hop-step + drop "ack " prefix from test response
Two changes: Two changes:

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 20:31:12 -0600 Date: Sat, 16 May 2026 20:31:12 -0600
Subject: [PATCH 10/11] Widen coordinator delays a tiny bit more Subject: [PATCH 10/12] Widen coordinator delays a tiny bit more
~25% bump across the main coordination knobs: ~25% bump across the main coordination knobs:
- BOT_RESPONSE_DELAY_BASE_MILLIS 1200 -> 1500 - BOT_RESPONSE_DELAY_BASE_MILLIS 1200 -> 1500

View File

@@ -1,7 +1,7 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online> From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 20:49:51 -0600 Date: Sat, 16 May 2026 20:49:51 -0600
Subject: [PATCH 11/11] Auto-advert on startup (initial flood at 5s instead of Subject: [PATCH 11/12] Auto-advert on startup (initial flood at 5s instead of
120s) 120s)
BOT_PREFS_INITIAL_FLOOD_ADVERT_MILLIS 120000 -> 5000. The bot now sends BOT_PREFS_INITIAL_FLOOD_ADVERT_MILLIS 120000 -> 5000. The bot now sends

View File

@@ -0,0 +1,91 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: cj-vana <cj@depth23.online>
Date: Sat, 16 May 2026 21:32:04 -0600
Subject: [PATCH 12/12] Spell out hops/byte in test+path; drop channel name
from test ack
Test response (writeAckResponse):
- before: @[user] #bot | 2h@2B SNR -1.25 | recv 21:25:45
- after : @[user] | 2 hops, 2-byte hashes, SNR -1.25 | recv 21:25:45
DMs keep the 'direct' indicator; channel responses now omit the channel
name (redundant in-channel) for readability.
Path response (executePathLike + executePathArg):
- before: Path @[user] 6h@2B SNR -8.50 | <path>
- after : Path @[user] 6 hops, 2-byte hashes, SNR -8.50 | <path>
- before: Path direct zero-hop SNR 0.00
- after : Path direct zero-hop, SNR 0.00
Trace and other responses unchanged for now.
---
examples/companion_radio/BotCommands.cpp | 10 +++++-----
examples/companion_radio/FirmwareBot.cpp | 14 ++++++++------
2 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/examples/companion_radio/BotCommands.cpp b/examples/companion_radio/BotCommands.cpp
index 1aa4406d..198dc32f 100644
--- a/examples/companion_radio/BotCommands.cpp
+++ b/examples/companion_radio/BotCommands.cpp
@@ -381,15 +381,15 @@ BotCommandResult executePathLike(const BotCommandContext& context, char* output,
formatQuarters(context.path_snr_quarters, snr, sizeof(snr));
const char* target = context.response_target[0] ? context.response_target : NULL;
if (context.path_hash_count == 0 || context.path_len == 0) {
- if (target) return writeFormatted(output, output_len, "%s @[%s] direct zero-hop SNR %s", label, target, snr);
- return writeFormatted(output, output_len, "%s direct zero-hop SNR %s", label, snr);
+ if (target) return writeFormatted(output, output_len, "%s @[%s] direct zero-hop, SNR %s", label, target, snr);
+ return writeFormatted(output, output_len, "%s direct zero-hop, SNR %s", label, snr);
}
if (!context.path) return writeFormatted(output, output_len, "%s unavailable", label);
int written = target
- ? snprintf(output, output_len, "%s @[%s] %uh@%uB SNR %s | ", label, target,
+ ? snprintf(output, output_len, "%s @[%s] %u hops, %u-byte hashes, SNR %s | ", label, target,
(unsigned)context.path_hash_count, (unsigned)context.path_hash_size, snr)
- : snprintf(output, output_len, "%s %uh@%uB SNR %s | ", label,
+ : snprintf(output, output_len, "%s %u hops, %u-byte hashes, SNR %s | ", label,
(unsigned)context.path_hash_count, (unsigned)context.path_hash_size, snr);
if (written < 0) return makeResult(BOT_COMMAND_RESULT_NO_SPACE, 0);
size_t pos = (size_t)written;
@@ -402,7 +402,7 @@ BotCommandResult executePathArg(const BotCommand& command, const BotCommandConte
ParsedPathArg path;
if (!parsePathArgument(command.args, command.args_len, context.path_hash_size, &path)) return writeText(output, output_len, "Usage: path [path]");
if (!output || output_len == 0) return makeResult(BOT_COMMAND_RESULT_NO_SPACE, 0);
- int written = snprintf(output, output_len, "Path %uh@%uB | ", (unsigned)path.hash_count, (unsigned)path.hash_size);
+ int written = snprintf(output, output_len, "Path %u hops, %u-byte hashes | ", (unsigned)path.hash_count, (unsigned)path.hash_size);
if (written < 0) return makeResult(BOT_COMMAND_RESULT_NO_SPACE, 0);
size_t pos = (size_t)written;
appendPathHops(output, output_len, &pos, path.bytes, path.hash_size, path.hash_count);
diff --git a/examples/companion_radio/FirmwareBot.cpp b/examples/companion_radio/FirmwareBot.cpp
index e228b7c8..afd44d41 100644
--- a/examples/companion_radio/FirmwareBot.cpp
+++ b/examples/companion_radio/FirmwareBot.cpp
@@ -319,10 +319,12 @@ BotWriteResult writeAckResponse(const BotMessage& message, const BotCommand& com
if (!output || output_len == 0) return BOT_WRITE_NO_SPACE;
const char* sender = message.sender_name[0] ? message.sender_name : "unknown";
- const char* connection = message.channel_kind == BOT_CHANNEL_DM
- ? "direct"
- : (message.channel_name[0] ? message.channel_name : "channel");
- int n = snprintf(output, output_len, "@[%s] %s", sender, connection);
+ int n;
+ if (message.channel_kind == BOT_CHANNEL_DM) {
+ n = snprintf(output, output_len, "@[%s] direct", sender);
+ } else {
+ n = snprintf(output, output_len, "@[%s]", sender);
+ }
if (n < 0) {
output[0] = 0;
return BOT_WRITE_NO_SPACE;
@@ -337,9 +339,9 @@ BotWriteResult writeAckResponse(const BotMessage& message, const BotCommand& com
char path_block[40];
int path_n;
if (message.path_hash_count == 0 || message.path_hash_size == 0) {
- path_n = snprintf(path_block, sizeof(path_block), " | 0h SNR %s%d.%02d", sign, value / 4, (value % 4) * 25);
+ path_n = snprintf(path_block, sizeof(path_block), " | 0 hops, SNR %s%d.%02d", sign, value / 4, (value % 4) * 25);
} else {
- path_n = snprintf(path_block, sizeof(path_block), " | %uh@%uB SNR %s%d.%02d",
+ path_n = snprintf(path_block, sizeof(path_block), " | %u hops, %u-byte hashes, SNR %s%d.%02d",
(unsigned)message.path_hash_count, (unsigned)message.path_hash_size, sign, value / 4,
(value % 4) * 25);
}

View File

@@ -539,7 +539,7 @@ static void test_ack_response_format() {
char out[BOT_MAX_RESPONSE_LEN + 1]; char out[BOT_MAX_RESPONSE_LEN + 1];
size_t written = 0; size_t written = 0;
assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK); assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK);
assert(strcmp(out, "@[alice] #bot | 0h SNR 0.00 | recv 21:25:45 | hello") == 0); assert(strcmp(out, "@[alice] | 0 hops, SNR 0.00 | recv 21:25:45 | hello") == 0);
assert(written == strlen(out)); assert(written == strlen(out));
message.channel_kind = BOT_CHANNEL_DM; message.channel_kind = BOT_CHANNEL_DM;
@@ -547,7 +547,7 @@ static void test_ack_response_format() {
message.channel_name[0] = 0; message.channel_name[0] = 0;
assert(FirmwareBot::parseCommand("!t", 2, &command)); assert(FirmwareBot::parseCommand("!t", 2, &command));
assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK); assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK);
assert(strcmp(out, "@[unknown] direct | 0h SNR 0.00 | recv 21:25:45") == 0); assert(strcmp(out, "@[unknown] direct | 0 hops, SNR 0.00 | recv 21:25:45") == 0);
uint8_t path[] = { 0x12, 0x34, 0xab, 0xcd }; uint8_t path[] = { 0x12, 0x34, 0xab, 0xcd };
message.channel_kind = BOT_CHANNEL_BOT; message.channel_kind = BOT_CHANNEL_BOT;
@@ -558,7 +558,7 @@ static void test_ack_response_format() {
message.path_hash_count = 2; message.path_hash_count = 2;
message.packet_snr_quarters = -5; message.packet_snr_quarters = -5;
assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK); assert(FirmwareBot::writeAckResponse(message, command, out, sizeof(out), &written) == BOT_WRITE_OK);
assert(strcmp(out, "@[bob] #bot | 2h@2B SNR -1.25 | recv 21:25:45") == 0); assert(strcmp(out, "@[bob] | 2 hops, 2-byte hashes, SNR -1.25 | recv 21:25:45") == 0);
assert(strstr(out, "Bot test OK") == NULL); assert(strstr(out, "Bot test OK") == NULL);
char small[16]; char small[16];
@@ -799,23 +799,23 @@ static void test_path_command() {
context.path_snr_quarters = 23; context.path_snr_quarters = 23;
BotCommandResult result = BotCommands::executeCommand(command, context, out, sizeof(out)); BotCommandResult result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path 3h@2B SNR 5.75 | 1234 -> abcd -> 0001") == 0); assert(strcmp(out, "Path 3 hops, 2-byte hashes, SNR 5.75 | 1234 -> abcd -> 0001") == 0);
strncpy(context.response_target, "alice", sizeof(context.response_target) - 1); strncpy(context.response_target, "alice", sizeof(context.response_target) - 1);
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path @[alice] 3h@2B SNR 5.75 | 1234 -> abcd -> 0001") == 0); assert(strcmp(out, "Path @[alice] 3 hops, 2-byte hashes, SNR 5.75 | 1234 -> abcd -> 0001") == 0);
context.response_target[0] = 0; context.response_target[0] = 0;
assert(FirmwareBot::parseCommand("!path 1234,abcd,0001", 20, &command)); assert(FirmwareBot::parseCommand("!path 1234,abcd,0001", 20, &command));
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path 3h@2B | 1234 -> abcd -> 0001") == 0); assert(strcmp(out, "Path 3 hops, 2-byte hashes | 1234 -> abcd -> 0001") == 0);
assert(FirmwareBot::parseCommand("!path 1234abcd0001", 18, &command)); assert(FirmwareBot::parseCommand("!path 1234abcd0001", 18, &command));
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path 3h@2B | 1234 -> abcd -> 0001") == 0); assert(strcmp(out, "Path 3 hops, 2-byte hashes | 1234 -> abcd -> 0001") == 0);
assert(FirmwareBot::parseCommand("!path 12,34", 11, &command)); assert(FirmwareBot::parseCommand("!path 12,34", 11, &command));
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
@@ -830,7 +830,7 @@ static void test_path_command() {
context.path_hash_size = 0; context.path_hash_size = 0;
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path 2h@4B | 12345678 -> abcdef01") == 0); assert(strcmp(out, "Path 2 hops, 4-byte hashes | 12345678 -> abcdef01") == 0);
context.path_hash_size = 2; context.path_hash_size = 2;
assert(FirmwareBot::parseCommand("!path", 5, &command)); assert(FirmwareBot::parseCommand("!path", 5, &command));
@@ -841,17 +841,17 @@ static void test_path_command() {
context.path_snr_quarters = 0; context.path_snr_quarters = 0;
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path direct zero-hop SNR 0.00") == 0); assert(strcmp(out, "Path direct zero-hop, SNR 0.00") == 0);
context.path = NULL; context.path = NULL;
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path direct zero-hop SNR 0.00") == 0); assert(strcmp(out, "Path direct zero-hop, SNR 0.00") == 0);
strncpy(context.response_target, "alice", sizeof(context.response_target) - 1); strncpy(context.response_target, "alice", sizeof(context.response_target) - 1);
result = BotCommands::executeCommand(command, context, out, sizeof(out)); result = BotCommands::executeCommand(command, context, out, sizeof(out));
assert(result.code == BOT_COMMAND_RESULT_OK); assert(result.code == BOT_COMMAND_RESULT_OK);
assert(strcmp(out, "Path @[alice] direct zero-hop SNR 0.00") == 0); assert(strcmp(out, "Path @[alice] direct zero-hop, SNR 0.00") == 0);
context.response_target[0] = 0; context.response_target[0] = 0;
assert(FirmwareBot::parseCommand("!tracer", 7, &command)); assert(FirmwareBot::parseCommand("!tracer", 7, &command));