The form stops asking for what the tool already writes down

Nine of the bug form's fourteen fields were transcription: version, host, OS,
terminal, size, platform, device model, firmware, transport. `meshterm
diagnostics --out` writes every one of them, correctly, from the machine that
has the problem, and the form went on asking a tired person to copy them out by
hand.

A field that demands precision from someone who does not have it does not
produce precision. It produces an abandoned form, or an invented answer -- a
reporter guessing at their radio's chip name because the form would not let them
past without one. A guess is worse than a blank, because it reads as a fact.

So the required set drops from nine fields to five, and not one of the five asks
for something the reporter has to look up: what happened, how often, how to
repeat it, whether `--mock` changes it, and the diagnostics block itself.

Two of the cut fields came back as optional, because the block genuinely cannot
know them. It reads the model and firmware off the radio, so a report about a
radio that will not connect -- the most common first-run report there is -- has
nothing to read them from. And `platform` only separates PicoCalc from regular,
so a uConsole and a laptop look alike to it. Both fields now say exactly when
they apply, which is rarely.

The command itself lands in 0.9.0 and the released build is 0.3.7, so both the
form and the forum say what to do when it is not recognised: name your version
and send what you can. That line comes out once nobody is running an older one.

The trailer workflow inverts the obvious design. It does not nag about commits
with no issue trailer, because most commits here legitimately close nothing and
a workflow that complains about all of them gets muted within a week. It checks
the trailers that are there: `Fixes: #42` against an issue that does not exist
is not an error in GitHub's eyes, it is silence -- the issue stays open, the
reporter is never told, and the commit looks like it did the job. That is the
failure worth a comment.

Four labels join the stock set for the states a report actually passes through:
needs-diagnostics, confirmed, needs-hardware, cannot-reproduce. They say what
state a thing is in. The hardware goes in the title, where it does not
multiply.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jean-Pierre MartineauandClaude Opus 5 committed 2026-09-20 13:13:39 -04:00
1 parent 1bd8752a7e
commit cf934e781f
3 files changed
+158 -107

No files matched your search

+69 -104
View File
@@ -7,12 +7,26 @@ body:
value: |
Hopefully you never need this form.
If you do: how much of this you fill in really does decide what happens next. A
report I can act on gets worked on. A vague one usually doesn't, because I can't
do anything with it. If it isn't worth describing properly, it's probably not
worth fixing.
If you do: start by running this, and attach the file it writes.
Most of these take ten seconds each.
```
meshterm diagnostics --out bug.md
```
It answers which MeshTerm, on which machine, in which terminal, talking to which
radio over which transport and firmware — most of what I would otherwise ask one
question at a time, and the details people most often end up guessing at. Nothing
in it is private: no keys, no pairing PINs, no positions, no contacts. That is a
tested property, not a promise.
No clipboard on your handheld? The **Diagnostics** page saves the same file with
`s`, next to the log.
**`diagnostics` not recognised?** You are on 0.3.7 or older, where the command does
not exist yet. Say which version you have in the block below and fill in what you
can — that is a complete answer, not a failure.
The rest of this form asks only for what that file cannot know.
- type: textarea
id: problem
@@ -49,118 +63,63 @@ body:
validations:
required: true
- type: textarea
id: workaround
attributes:
label: Is there a way around it
description: Anything that avoids it, or gets you unstuck. Say so even if it's ugly.
- type: input
id: version
attributes:
label: MeshTerm version
description: It's on the splash screen when you start, and on the About page.
placeholder: "0.2.0"
validations:
required: true
- type: input
id: hardware
attributes:
label: What are you running MeshTerm on
description: >
Desktop, laptop, Mac, or a handheld — and if it's a handheld, which one.
placeholder: "ClockworkPi uConsole (CM4), or: desktop PC"
validations:
required: true
- type: input
id: os
attributes:
label: Which OS, exact version
placeholder: "Windows 11 24H2 / macOS 15.3 / Debian 12"
validations:
required: true
- type: input
id: terminal
attributes:
label: Which terminal, and how big
description: >
PowerShell, Windows Terminal, iTerm2, the PicoCalc console, ssh from something.
Size in columns x rows if you know it — a lot of layout bugs are really terminal
bugs.
placeholder: "Windows Terminal, 120x40"
validations:
required: true
- type: input
id: companion
attributes:
label: Which companion device
description: >
Be precise. There are a lot of these and they don't behave the same. "A Xiao"
doesn't narrow it down — "Seeed XIAO nRF52840 + Wio-SX1262" does. Leave blank if
no radio was involved.
placeholder: "Heltec V3 / RAK4631 / XIAO nRF52840 + Wio-SX1262"
- type: input
id: firmware
attributes:
label: Which firmware version is on it
placeholder: "MeshCore 1.15.0"
- type: dropdown
id: transport
attributes:
label: How is it connected
options:
- USB / serial
- Bluetooth
- TCP
- SPI-to-TCP bridge
- Something else (say so below)
- No radio — simulator / --mock
validations:
required: true
- type: dropdown
id: flavour
attributes:
label: Regular or PicoCalc
description: >
MeshTerm draws itself differently on a PicoCalc — narrower, fewer colours, a
different font. A bug in one often doesn't exist in the other, so this saves a
round of guessing.
options:
- Regular (desktop, laptop, ssh)
- PicoCalc handheld
- Not sure
validations:
required: true
- type: dropdown
id: mock
attributes:
label: Does it still happen with `meshterm --mock`
description: >
`--mock` runs the whole app against a fake radio. If the bug survives that, it's
in MeshTerm and I can chase it without hardware. If it doesn't, it's in the link
or the radio, which is a different hunt. Skip it if the bug is about connecting
in the first place.
`--mock` runs the whole app against a fake radio. If the bug survives that, it is
in MeshTerm and I can chase it without owning your hardware. If it doesn't, it is
in the link or the radio, which is a different hunt. This one question decides
which of those two jobs this is, so it is worth the minute it takes.
options:
- "Yes, still happens with --mock"
- "No, --mock is fine"
- "Haven't tried"
- "Doesn't apply"
- "Doesn't apply — the problem is connecting"
validations:
required: true
- type: textarea
id: diagnostics
attributes:
label: The diagnostics block
description: >
Attach `bug.md` by dragging it in, or paste its contents here. If you genuinely
cannot produce one — an older build, or MeshTerm will not start at all — write down
why instead, along with your version, and I will work with that.
render: markdown
validations:
required: true
- type: input
id: handheld
attributes:
label: Which handheld, if it is a handheld
description: >
Only if you are running on something the diagnostics file cannot name. It knows a
PicoCalc from a regular terminal, but a uConsole and a laptop look much the same to
it. Leave blank on a desktop, laptop or Mac.
placeholder: "ClockworkPi uConsole (CM4) / M5Stack Cardputer"
- type: input
id: radio
attributes:
label: Which radio and firmware, if MeshTerm could not reach it
description: >
The diagnostics file reads the model and firmware off the radio itself, so when the
problem *is* connecting, it has nothing to read. That is the one case where I need
you to tell me. Be precise — "a Xiao" covers several boards that do not behave
alike.
placeholder: "Seeed XIAO nRF52840 + Wio-SX1262, MeshCore 1.15.0"
- type: textarea
id: error
attributes:
label: The exact error, if there was one
description: >
Copy it as text rather than photographing the screen — text can be searched, and
a photo of a terminal is hard to read. Paste the whole traceback if it crashed.
Copy it as text rather than photographing the screen — text can be searched, and a
photo of a terminal is hard to read. Paste the whole traceback if it crashed.
render: text
- type: textarea
@@ -170,10 +129,16 @@ body:
description: >
MeshTerm keeps one at `~/.meshterm/meshterm.log` (or wherever `MESHTERM_HOME`
points). Attach it, or paste the last twenty lines. If the problem is hard to
catch, set **Log detail** to `DEBUG` on the Preferences page, do it once more,
and send that instead — it records a great deal more.
catch, set **Log detail** to `DEBUG` on the Preferences page, do it once more, and
send that instead — it records a great deal more.
render: text
- type: textarea
id: workaround
attributes:
label: Is there a way around it
description: Anything that avoids it, or gets you unstuck. Say so even if it's ugly.
- type: textarea
id: extra
attributes:
+5 -3
View File
@@ -4,10 +4,12 @@ contact_links:
url: https://discord.gg/AZwe5Uvb3S
about: >
Setup trouble, "is it supposed to do this", or anything you want a second opinion
on. The support forum is the place. Someone running your radio has probably hit it.
on. The #support forum is the place. Someone running your radio has probably hit it.
- name: No GitHub account? Report it on Discord instead
- name: No GitHub account? Report it in the #bugs forum instead
url: https://discord.gg/AZwe5Uvb3S
about: >
Drop reproducible bugs in #bugs and they'll get moved here. Being told beats
One post per bug, tagged, with the diagnostics file attached. Real ones get opened
here and your post is renamed with the issue number, so you can follow it without an
account — and something comes back to tell you when it ships. Being told beats
filing it tidily.
+84
View File
@@ -0,0 +1,84 @@
name: Issue trailers
# A commit that names an issue is the only thing connecting a fix to the person
# who reported it. GitHub resolves that link silently: `Fixes: #42` against an
# issue that does not exist is not an error, it is nothing at all -- the issue
# stays open, the reporter is never told, and the commit looks like it did the
# job. A typo costs a whole loop and announces itself nowhere.
#
# So this checks the trailers that ARE there rather than nagging about the ones
# that are not. Most commits here are internal work that legitimately closes
# nothing, and a workflow that complains about all of them gets muted in a week.
#
# Cross-repo trailers (`Fixes: owner/repo#12`) are reported but not verified:
# GITHUB_TOKEN only reaches this repository.
on:
push:
branches: [main]
permissions:
contents: write # to leave a comment on the offending commit
issues: read
jobs:
check:
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]')"
steps:
- name: Verify every issue named in a trailer exists
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
COMMITS: ${{ toJSON(github.event.commits) }}
run: |
set -euo pipefail
echo "$COMMITS" > /tmp/commits.json
count=$(jq 'length' /tmp/commits.json)
echo "checking $count commit(s)"
problems=0
for i in $(seq 0 $((count - 1))); do
sha=$(jq -r ".[$i].id" /tmp/commits.json)
msg=$(jq -r ".[$i].message" /tmp/commits.json)
short="${sha:0:8}"
# Trailers only: a line that starts with the keyword. A bare "#12"
# in prose is a reference someone wrote on purpose, not a claim
# that this commit closes anything.
refs=$(printf '%s\n' "$msg" \
| grep -oiE '^(fixes|closes|resolves|refs|see):[[:space:]]*([A-Za-z0-9._-]+/[A-Za-z0-9._-]+)?#[0-9]+' \
|| true)
[ -z "$refs" ] && continue
while IFS= read -r ref; do
[ -z "$ref" ] && continue
target=$(printf '%s' "$ref" | sed -E 's/^[A-Za-z]+:[[:space:]]*//')
num="${target##*#}"
if [ "$target" != "#${num}" ]; then
repo="${target%%#*}"
echo " $short -> $target (other repository, not verified here)"
continue
fi
if state=$(gh api "repos/$REPO/issues/$num" --jq .state 2>/dev/null); then
echo " $short -> #$num ($state)"
else
echo "::error::commit $short names #$num, which does not exist in $REPO"
problems=$((problems + 1))
gh api "repos/$REPO/commits/$sha/comments" \
-f body="This commit's trailer names **#$num**, which does not exist in \`$REPO\`.
GitHub resolves a closing keyword silently, so nothing failed and nothing was linked — the issue this was meant to close is still open, and whoever reported it has not been told. Worth a follow-up commit with the right number, or a note on the issue itself." \
>/dev/null
fi
done <<< "$refs"
done
if [ "$problems" -gt 0 ]; then
echo "::warning::$problems trailer(s) pointed at issues that do not exist"
fi