Skip to content

fix: keep parsing the status line when a tip block follows it - #97

Open
zellwk wants to merge 1 commit into
six-ddc:mainfrom
zellwk:pr/status-line-tip-block
Open

zellwk wants to merge 1 commit into
six-ddc:mainfrom
zellwk:pr/status-line-tip-block

Conversation

@zellwk

@zellwk zellwk commented Aug 14, 2026

Copy link
Copy Markdown

Problem

parse_status_line locates the chrome separator, then checks the first non-blank line above it. If that line doesn't start with a spinner glyph it returns None immediately.

Claude Code now renders a tip block between the status line and the chrome:

✳ Gitifying… (2m 1s · ↓ 6.5k tokens)
  ⎿ Tip: Use /btw to ask a quick side question without interrupting
     current work
────────────────────────────────────────
❯
────────────────────────────────────────
  ⏸ manual mode on · esc to interrupt · ← for agents

The scan stops on current work and reports no status. Whenever a tip is showing, the topic's status message goes stale — it keeps displaying whatever was last parsed until the tip disappears.

Fix

Keep scanning upward instead of bailing on the first non-spinner line.

The line directly above the separator is still accepted on the spinner glyph alone, so current behaviour is unchanged. Past that, a line must also carry the … of a live status line. That preserves the guard the original was written for — · bullets in Claude's prose output — and additionally keeps out the finished marker (✻ Sautéed for 7s), which has no ellipsis.

Every status line variant carries the ellipsis, including the ones quoted in #52:

✻ Thinking… 5s
✶ Coalescing… (25m 8s · ↓ 5.8k tokens · thought for 6s)
✢ Drizzling… (54s · ↓ 776 tokens)

Tests

Two added, and all existing parse_status_line tests pass unchanged:

  • the tip-block layout parses correctly
  • the finished ✻ Sautéed for 7s marker is not mistaken for a live status

parse_status_line checks the first non-blank line above the chrome separator
and returns None if it isn't a spinner. Claude Code now renders a tip block
between the status line and the chrome:

    ✳ Gitifying… (2m 1s · ↓ 6.5k tokens)
      ⎿ Tip: Use /btw to ask a quick side question without interrupting
         current work
    ────────────────────────────────────────
    ❯

so the scan stops on "current work" and reports no status. Whenever a tip is
showing, the topic's status message goes stale and the typing indicator never
lights.

Keep scanning upward instead. The line directly above the separator is still
accepted on the spinner glyph alone, preserving current behaviour; past that,
a line must also carry the ellipsis of a live status. That keeps out both the
prose bullets the original guard was written for and the finished
"✻ Sautéed for 7s" marker.
TejNote added a commit to TejNote/ccbot that referenced this pull request Sep 16, 2026
upstream 패치 자체는 맞지만 **이 fork 의 다른 부분과 겹쳐서 깨지는** 것들이다.
upstream 테스트로는 안 잡힌다.

🚨 죽은 토픽 정리 후 타이핑 keepalive 가 살아남아 무한 API 호출
  six-ddc#81 의 cleanup_dead_topic 은 clear_topic_state 를 부르지 않는 유일한 해제 경로였다
  (다른 셋은 전부 부른다). six-ddc#98 전에는 단순 누수였지만 붙고 나서는 _typing_keepalive 가
  while True 라 **텔레그램이 "그 토픽 없다" 고 답한 thread 로 4초마다 send_chat_action 을
  영원히** 던지게 됐다. 정리한 (user_id, thread_id) 목록을 반환하도록 바꿔 연결한다.

six-ddc#97 의 8줄 스캔이 `·` 불릿을 상태줄로 읽는 구멍을 비인접 줄에 열었다
  upstream 조건이 `"…" in line` 하나뿐인데 `·` 는 스피너이면서 평범한 불릿이다.
  Claude 답변의 `· 첫째 항목은…` 이 상태줄이 되고, six-ddc#98 이 그 값으로 타이핑을 켜므로
  유휴 세션에 유령 상태 메시지 + 영구 타이핑이 남는다. 비인접은 `…` **그리고** `·` 아님.
  ⚠️ 구분선 바로 위 불릿은 main 에도 있던 기존 오탐이라 손대지 않았다(실측 대조).

퍼미션 프롬프트 동안 "작업 중" 으로 보이던 것
  six-ddc#98 의 set_typing 이 함수 맨 끝 한 번인데 그 위에 조기 return 이 셋이다. 프롬프트는
  몇 시간도 떠 있고 실제로는 봇이 사용자를 기다리는 중이다. skip_status 는 제외했다 —
  큐가 찬 일시적 상태이고 에이전트는 실제로 작업 중이다.

secondary 태스크의 이미지가 고아로 남던 것
  six-ddc#94 가 모으는 id 에 _send_task_images 의 사진이 빠졌다. tool_result 는 항상 secondary 라
  다음 메시지가 오면 설명 텍스트만 지워지고 스크린샷이 남는다. send_photo 가 id 를 반환한다.

콜백 응답이 최대 45초 지연되던 것
  query.answer() 앞에 wait_for_claude_ready(30초) + wait_for_session_map_entry(5~15초)가
  있었다. 텔레그램은 약 15초를 넘기면 query is too old 를 내고 try/except 도 없다.
  응답을 맨 앞으로 옮겼다 — 결과는 safe_edit 가 본문으로 보여준다.

TOPIC_CHECK_INTERVAL docstring 60초 → 5초 정정
  ⚠️ 바인딩당 API 호출 12배로 six-ddc#52 스로틀과 방향이 반대다. 레이트 리밋을 실제로 맞은
  관측이 없어 upstream 값은 유지하고, 근거와 되돌릴 값(15~20초)을 주석에 남겼다.

Tested: pytest 440항 (신규 8) · pyright 0 errors · ruff 103 → 102, 파일·규칙 단위로
  main 에 없던 조합 0건. 신규 테스트는 **뮤테이션 4종**으로 유효성을 확인했다 —
  각 수정을 되돌리면 대응 테스트 하나씩만 실패한다.
Not-tested: 실제 텔레그램 대상 수동 검증(봇 재시작 필요 — 머지 후 별도)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.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.

1 participant