Skip to content

Commit 8e7c76b

Browse files
ellatairaclaude
andcommitted
coordinator: inbox filter by marker only, not author login
The coordinator posts its own status comments under the same GitHub login the operator uses to type steering comments (both `ellataira`). The author-login branch of the own-filter was swallowing every human steering message as "own output" — silently, for 2+ days, while last_seen_id advanced normally. The zero-width-space marker (OWN_MESSAGE_MARKER = "​") is prepended by github_out.format_message on every coordinator-emitted comment. Humans cannot type it by accident. Using the marker alone as the own-filter cleanly distinguishes the two cases. Drops the now-unused `_own_login` helper + its cache. `user_login` still returned by `_fetch_comments` query for debugging (harmless). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent bfec600 commit 8e7c76b

1 file changed

Lines changed: 10 additions & 35 deletions

File tree

tasks/coordinator/github_in.py

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -63,33 +63,6 @@ def _append_to_inbox(root: Path, text: str) -> None:
6363
f.write(text.rstrip() + "\n\n")
6464

6565

66-
_own_login_cache: str | None = None
67-
68-
69-
def _own_login() -> str | None:
70-
"""Return the GitHub login of whoever `gh` is authenticated as.
71-
72-
Cached for the process lifetime. If auth is broken or gh is missing,
73-
returns None and the caller falls back to marker-only filtering (which
74-
is fragile but strictly additive — never re-ingest own comments).
75-
"""
76-
global _own_login_cache
77-
if _own_login_cache is not None:
78-
return _own_login_cache
79-
try:
80-
r = subprocess.run(
81-
["gh", "api", "user", "--jq", ".login"],
82-
capture_output=True, text=True, timeout=15,
83-
)
84-
except (FileNotFoundError, subprocess.TimeoutExpired, Exception):
85-
return None
86-
if r.returncode != 0:
87-
return None
88-
login = r.stdout.strip()
89-
_own_login_cache = login or None
90-
return _own_login_cache
91-
92-
9366
def _fetch_comments(pr: str) -> tuple[list[dict] | None, str]:
9467
"""Call `gh api` to pull all issue comments for the PR (PRs are issues).
9568
@@ -159,11 +132,15 @@ def poll(root: Path = Path(".")) -> tuple[int, str]:
159132
# Process oldest-first so inbox ordering matches chronology.
160133
comments.sort(key=lambda c: int(c.get("id", 0)))
161134

162-
# Primary own-filter: author login. Marker is kept as a belt-and-
163-
# suspenders check in case gh is re-authed mid-run to a different
164-
# login (e.g. a human posts as themselves during a coordinator pause).
165-
own_login = _own_login()
166-
135+
# Own-filter: body-marker ONLY. Every coordinator-emitted comment
136+
# begins with OWN_MESSAGE_MARKER (U+200B, zero-width space) prepended
137+
# by github_out.format_message. A human posting from the same GitHub
138+
# login as the coordinator's gh auth cannot type that marker, so the
139+
# marker cleanly distinguishes the two — author login cannot, because
140+
# the coordinator posts under the same account the operator uses to
141+
# type steering comments, and an author-login filter silently swallows
142+
# every human message. (Pre-fix: this exact bug dropped 2+ days of
143+
# steering input without a trace.)
167144
appended = 0
168145
max_id = last_seen_id
169146
for c in comments:
@@ -174,9 +151,7 @@ def poll(root: Path = Path(".")) -> tuple[int, str]:
174151
if cid <= last_seen_id:
175152
continue
176153
body = c.get("body") or ""
177-
author = c.get("user_login") or ""
178-
is_own = (own_login is not None and author == own_login) or \
179-
body.startswith(github_out.OWN_MESSAGE_MARKER)
154+
is_own = body.startswith(github_out.OWN_MESSAGE_MARKER)
180155
if is_own:
181156
# Own comment; advance the cursor so we don't reconsider next poll.
182157
if cid > max_id:

0 commit comments

Comments
 (0)