|
@@ -350,6 +350,26 @@ changes must keep them, or consciously renegotiate the docs.**
|
|
|
- **Processing reactions.** 👀 while working, then ✅, ❌, or 🚫 (cancelled) —
|
|
- **Processing reactions.** 👀 while working, then ✅, ❌, or 🚫 (cancelled) —
|
|
|
driven by `on_processing_start`/`on_processing_complete` and the `reactions`
|
|
driven by `on_processing_start`/`on_processing_complete` and the `reactions`
|
|
|
setting, never applied to the bot's own events.
|
|
setting, never applied to the bot's own events.
|
|
|
|
|
+- **Interactive prompt cards thread into their conversation, and their emoji
|
|
|
|
|
+ match by normalized key.** `send_clarify` and `_send_exec_approval_prompt`
|
|
|
|
|
+ resolve the thread through the same `_resolve_outbound_thread` call as
|
|
|
|
|
+ `send()` — an answer to a card is routed by session key, and that key
|
|
|
|
|
+ includes the thread ID, so a card at the room root is answered into a
|
|
|
|
|
+ session nobody is waiting in (the "Question-Loop" bug: the card worked, the
|
|
|
|
|
+ answer never arrived). Emoji matching compares `_normalize_reaction_emoji`
|
|
|
|
|
+ of the incoming reaction against keys the card builders also store
|
|
|
|
|
+ normalized: it strips variation selectors (U+FE0E/U+FE0F) and folds
|
|
|
|
|
+ check-mark variants (✔, ✔️, ☑️, ✓) onto ✅, because the card seeds ✅
|
|
|
|
|
+ (U+2705) while clients send whatever the emoji picker offers and may add or
|
|
|
|
|
+ strip a selector in transit. Keycap digits (1️⃣…9️⃣) keep their combining
|
|
|
|
|
+ keycap (U+20E3) — only the VS16 goes. Display forms (card text, seeded
|
|
|
|
|
+ reactions, the reply emoji in `_forward_reaction`) stay raw; only
|
|
|
|
|
+ *comparison* keys are normalized, on both sides at once. The prompt emoji
|
|
|
|
|
+ sets live once as module constants (`_PROMPT_NUMBER_EMOJIS`,
|
|
|
|
|
+ `_PROMPT_OTHER_EMOJI`, `_PROMPT_APPROVAL_EMOJIS` and their derived
|
|
|
|
|
+ normalized key lists) — a fourth hand-copied list is the bug waiting to
|
|
|
|
|
+ happen, since a list that forgets normalization rejects valid reactions
|
|
|
|
|
+ again.
|
|
|
- **Reconnects resume, restarts resume inside a window.** The realtime loop hands
|
|
- **Reconnects resume, restarts resume inside a window.** The realtime loop hands
|
|
|
`stream_events` the cursor of the last event it finished handling, and advances
|
|
`stream_events` the cursor of the last event it finished handling, and advances
|
|
|
it only after the handler returns: a raising handler leaves the old cursor so
|
|
it only after the handler returns: a raising handler leaves the old cursor so
|
|
@@ -870,3 +890,39 @@ Why this earns a rule of its own: the script deletes things (`rm -rf
|
|
|
"$VENDOR_DIR"`, the build-dir trap), so a quoting or word-splitting bug is
|
|
"$VENDOR_DIR"`, the build-dir trap), so a quoting or word-splitting bug is
|
|
|
destructive rather than merely wrong output — and both are exactly the
|
|
destructive rather than merely wrong output — and both are exactly the
|
|
|
mistakes review tends to skim past.
|
|
mistakes review tends to skim past.
|
|
|
|
|
+
|
|
|
|
|
+## Research notes
|
|
|
|
|
+
|
|
|
|
|
+**A bug whose diagnosis took real digging gets its findings written down here,
|
|
|
|
|
+in its own kind of note — not just the fix in code.**
|
|
|
|
|
+
|
|
|
|
|
+Most bugs in this repo are legible from the diff: the test that fails names the
|
|
|
|
|
+behavior, the fix names the cause. The ones worth recording are the other kind —
|
|
|
|
|
+where the expensive part was *finding out how the system actually works*, and
|
|
|
|
|
+the fix alone does not carry that knowledge:
|
|
|
|
|
+
|
|
|
|
|
+- **The knowledge lives across repo boundaries.** The emoji bug needed three
|
|
|
|
|
+ sources read together to diagnose: the adapter's own matching code, the
|
|
|
|
|
+ Hermes gateway code that keys answers to sessions (`build_session_key`
|
|
|
|
|
+ includes the thread ID — a fact visible only in Hermes, not here), and the
|
|
|
|
|
+ Unicode facts themselves (✔️ U+2714 vs ✅ U+2705 are different codepoints;
|
|
|
|
|
+ variation selectors U+FE0E/U+FE0F are added or stripped by clients in
|
|
|
|
|
+ transit; keycap sequences keep their combining U+20E3). None of these is
|
|
|
|
|
+ discoverable from this repo alone.
|
|
|
|
|
+- **The wrong fix looks right.** Normalizing only the incoming emoji, or
|
|
|
|
|
+ normalizing on only one of the two comparison sides, fixes the reported
|
|
|
|
|
+ ✔️ case and silently breaks others (1️⃣ losing its keycap, a stored key
|
|
|
|
|
+ still carrying its selector). What made the fix correct was deriving both
|
|
|
|
|
+ sides from one function — a decision a diff does not explain.
|
|
|
|
|
+- **The diagnosis inverted a plausible reading of the report.** The
|
|
|
|
|
+ "reactions to questions are broken" report read as a clarify-prompt bug,
|
|
|
|
|
+ but ✅ is not a clarify option at all — the failing case was the
|
|
|
|
|
+ exec-approval card. Writing that down stops the next reader from
|
|
|
|
|
+ re-testing the wrong prompt.
|
|
|
|
|
+
|
|
|
|
|
+So when a diagnosis required that kind of work, add a note here (or extend the
|
|
|
|
|
+relevant *Behavioural contract* entry) recording: what the wrong plausible
|
|
|
|
|
+reading was, which cross-repo sources had to be read together, and what makes
|
|
|
|
|
+the naive fix incorrect. The measure is not thoroughness — it is whether the
|
|
|
|
|
+next agent facing a similar report can skip the digging. The first reader of
|
|
|
|
|
+such a note is the agent that meets the sibling bug in another code path.
|