dispatch is anything that leaves, and the deeplink now goes somewhere

the definition was "doing something with a result beyond keeping it",
which does not obviously cover a notification ABOUT classification failing.
it should: classification decided where the item goes and it went to
unclassified/. telling somebody is a different step, and its rule belongs
in DISPATCHING.md. the test is never what the message is about — it is
whether anything left.

and the commander notification pointed at officer://command-hq/{id} where
{id} is the DIRECTORY name, while /command-hq/:sessionId addresses a
commander by its transcript id. so the tap landed nowhere.

the two want different ids and cannot be reconciled today: threading wants
the directory name, stable from creation; the route wants the transcript
id, which does not exist when the commander is created. rather than make a
commander fetch its own transcript id before it can speak — an errand it
would rightly skip, as the language rule already proved — the tap opens
Command HQ and the owner picks. one tap worse, and correct.

the honest fix is a route that accepts a directory name. noted where
whoever does the mobile deep-link work will find it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
2026-08-25 08:02:34 +00:00
co-authored by Claude Opus 5
parent 141e470aee
commit a35df2afb2
2 changed files with 21 additions and 6 deletions
+13 -3
View File
@@ -127,8 +127,18 @@ const CORE_ENTRIES: Record<string, NotificationEntry> = {
A commander with something to say.
ONE entry rather than one per commander, and the commander travels as `{id}` — so arming a new
commander needs no catalogue change and no app resync. `{id}` is the commander's row id, which is what
`officer://command-hq/{id}` opens.
commander needs no catalogue change and no app resync. `{id}` is the commander's DIRECTORY name, which
is what threads its notifications together.
The route is the LIST, deliberately, and not `officer://command-hq/{id}`. That is what it was, and it
was wrong: `/command-hq/:sessionId` addresses a commander by its TRANSCRIPT id, so a deeplink built
from the directory name lands nowhere. Threading wants the directory name (stable from creation, before
any transcript exists); the route wants the transcript id (which does not exist yet when the commander
is created). Rather than make a commander fetch its own transcript id to send a notification, the tap
opens Command HQ and the owner picks — one tap worse, and correct.
Worth revisiting when the app handles deep links properly: the honest fix is a route that accepts a
directory name, not a commander doing a lookup before it can speak.
This entry is what a commander sees when it sends nothing but a code and an id: "Voice Memos" would be
a lie without knowing which one, so the generic is honest and the deeplink does the rest. In practice a
@@ -163,7 +173,7 @@ const CORE_ENTRIES: Record<string, NotificationEntry> = {
title: 'Commander: {title}',
body: '{body}',
target: 'mobile',
route: 'officer://command-hq/{id}',
route: 'officer://command-hq',
thread: 'commander:{id}',
},
};