feat(mr): show note and discussion IDs in mr note list
glab mr note list printed discussions without the identifiers needed to act on them, so the output could not drive the sibling commands: reply/resolve need a discussion ID and update/delete need a note ID. This MR surfaces those IDs and makes the piped output usable in scripts.
Each note now carries a [note #<id>] annotation and each thread shows its discussion ID (Thread [discussion: <id>]). Terminal and piped output share a single rendering path: markdown is rendered in a terminal, while piped output emits the note body verbatim so redirecting to a file yields no control characters and preserves the exact markdown source. The envelope (author, timestamp, IDs, indentation) is identical in both modes.
Internally this collapses the previous TTY/raw split in mrutils: PrintDiscussionsTTY becomes PrintDiscussions and drives both cases via a small renderBody helper that keys off IsOutputTTY(). mr view uses the same renderer, so its --comments output gains the IDs consistently.
How has this been tested
Ran glab mr note list against a real MR (gitlab-org/editor-extensions/gitlab-lsp e2e branch) in three modes:
- Terminal: colored, markdown-rendered bodies, thread grouping, IDs present.
- Piped (
| cat,>> file): identical layout, zero ANSI/OSC control characters, verbatim markdown bodies, IDs present. - Copied a printed discussion ID prefix into
glab mr note create --reply <prefix>and a[note #ID]intoglab mr note updateto confirm the surfaced IDs are the ones those commands consume.
Unit tests updated and passing for internal/commands/mr/mrutils, internal/commands/mr/note, and internal/commands/mr/view.
Output before/after
One resolved thread from gitlab-lsp!3605, long bodies trimmed with ….
Piped (glab mr note list | cat) — the flat, ID-less dump becomes a grouped thread with copyable IDs:
-GitLabDuo commented 2026-06-26 05:35:51.086 +0000 UTC
-`upsert` does a read-modify-write (`load` → mutate → `save`) with no file locking. …
-...
-elwyn-gitlab commented 2026-06-30 05:14:32.284 +0000 UTC
-Wontfix, too edge-casey to warrant the extra complexity in this initial implementation
+Thread [discussion: 42180e9a…] ✓ resolved
+ @GitLabDuo commented about 5 days ago [note #3495896683]
+ on packages/duo_plugin_marketplace/src/plugin/installed_plugins_store.ts:67
+ `upsert` does a read-modify-write (`load` → mutate → `save`) with no file locking. …
+
+ @elwyn-gitlab replied about 1 day ago [note #3506272287]
+ Wontfix, too edge-casey to warrant the extra complexity in this initial implementationTerminal — same layout as before, now annotated with the discussion ID and per-note IDs:
-Thread [#3495896683] ✓ resolved
- @GitLabDuo commented about 5 days ago
+Thread [discussion: 42180e9a…] ✓ resolved
+ @GitLabDuo commented about 5 days ago [note #3495896683]
on packages/duo_plugin_marketplace/src/plugin/installed_plugins_store.ts:67
upsert does a read-modify-write (load → mutate → save) with no file locking. …
- @elwyn-gitlab replied about 1 day ago
+ @elwyn-gitlab replied about 1 day ago [note #3506272287]
Wontfix, too edge-casey to warrant the extra complexity in this initial implementation