Skip to content

chore(release): SemVer 도입 및 v1.0.0 첫 공식 릴리스#85

Closed
TejNote wants to merge 35 commits into
six-ddc:mainfrom
TejNote:chore/versioning-v1.0.0
Closed

chore(release): SemVer 도입 및 v1.0.0 첫 공식 릴리스#85
TejNote wants to merge 35 commits into
six-ddc:mainfrom
TejNote:chore/versioning-v1.0.0

Conversation

@TejNote
Copy link
Copy Markdown

@TejNote TejNote commented May 14, 2026

Summary

  • pyproject.toml 버전을 0.1.01.0.0으로 bump
  • CHANGELOG.md 신설 (Keep a Changelog 포맷, SemVer 기준). v1.0.0은 fork 누적분 전체를 Added/Changed/Fixed/Pending upstream merges 카테고리로 재구성
  • README.md의 Changelog 섹션 39줄 → 3줄로 단순화 (CHANGELOG.md 링크만 유지)

Why

기존 fork는 pyproject.toml version=0.1.0으로 박제된 채 변경 이력만 README에 누적되어 있어 "지금 어떤 버전이고 뭐가 새로 들어갔는지" 추적이 어려웠음. SemVer + CHANGELOG.md 체계로 전환해 슬랙 공유 시 vX.Y.Z 변경분만 떼서 전달할 수 있게 함.

정책

  • MAJOR (v2.0.0): 호환성 깨는 변경 (state.json 스키마, .env 키 rename, CLI 인자)
  • MINOR (v1.x.0): 기능 추가 (provider, hook, 명령어)
  • PATCH (v1.0.x): 버그픽스, 안정성, 문서

다음 릴리스 워크플로

  1. [Unreleased] 섹션에 변경 누적
  2. 릴리스 시 [Unreleased][1.x.y] - YYYY-MM-DD로 promote
  3. pyproject.toml bump → tag vX.Y.Z 생성
  4. 슬랙엔 해당 버전 CHANGELOG 항목만 잘라 공유 (전체 누적 X)

Test plan

  • cat pyproject.toml | grep version1.0.0
  • CHANGELOG.md 렌더 확인 (GitHub 미리보기)
  • README의 Changelog 섹션이 짧은 안내 + CHANGELOG.md 링크로 단순화됐는지 확인
  • 머지 후 v1.0.0 git tag 생성 + GitHub Release 발행

🤖 Generated with Claude Code

TejNote and others added 30 commits April 3, 2026 17:45
Group session copies (ccbot-15, ccbot-12) were recording session_map keys
with their own names (ccbot-15:@4) instead of the canonical name (ccbot:@4).
Bot only processes ccbot: prefix, so these sessions were invisible.

Fix: read TMUX_SESSION_NAME from .ccbot/.env and use as canonical prefix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…pearance

Claude TUI does not update its status line immediately after completing a
response. Reading the terminal right after sending the response captured the
previous 'thinking...' status and re-sent it as a new status message.

Fix: sleep 150ms before _check_and_send_status at all 3 call sites.
…nd drops

Claude TUI does not process key input during response generation. Commands
sent while Claude is working were silently dropped with no feedback to user.

Fix: capture pane and parse status line in send_to_window. If status contains
'esc to interrupt', return an error message instead of sending keys.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lRegistry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ge tracking

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/clear는 같은 프로세스 안에서 session_id만 리셋하기 때문에
SessionStart 훅이 재실행되지 않아 session_map.json이 갱신 안 됨.
결과: 새 세션의 JSONL이 모니터링 대상에서 빠져 텔레그램 전달 불가.

_auto_detect_session_changes() 추가:
- 매 폴링마다 각 window의 project dir에서 더 새로운 JSONL 확인
- 발견 시 session_map.json 자동 업데이트
- 성능 최적화: tracked JSONL이 활발히 크고 있으면 dir scan 스킵
  (stat 1회로 판단), stale 시에만 glob 실행

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CCBOT_BATCH_WINDOW > 0 일 때 batcher.flush_and_send / _timer_loop 가
safe_send 로 메시지를 직접 보내면서 message_queue worker 와 race —
결과적으로 텔레그램에 결과 응답이 먼저 도착하고 thinking/tool batch
요약이 뒤따라 도착하던 순서 역전 버그.

batcher 도 enqueue_direct_message 로 큐를 통과시켜 다른 content task
와 같은 FIFO 줄에 서도록 수정. 큐 worker 가 user 별 단일 처리이므로
순서 보장.

검증:
- ruff/pyright 통과
- 251 tests 통과
- ccbot 재시작 후 message queue worker 정상 시작 확인

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ubcommand

Problem: ccbot 재시작마다 이전 상태 메시지(Metamorphosing…, Baked for Ns 등)가
orphan으로 쌓여 Telegram 토픽에 메시지가 누적됨.

Fix:
- session.py: status_msg_ids를 state.json에 영속화
- bot.py post_init: 시작 시 orphaned 상태 메시지 일괄 삭제
- message_queue.py: send/delete/convert 시 state.json 동기화
  (content 변환 시 ID 미삭제 → content 메시지 삭제되는 버그도 수정)
- main.py: ccbot send 서브커맨드 디스패치 추가

Also: ~/.ccbot/.env에 CCBOT_SHOW_TOOL_CALLS=false 추가 권고
(tool_use/result 배치 제외 → 작업 중 요약 빈도 감소)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
TejNote and others added 5 commits May 8, 2026 17:03
* Codex topic routing now matches Claude-style Telegram flow

Codex windows keep topic bindings by provider, send input through tmux paste-buffer, and surface Codex working state through a provider-specific status parser while final responses are pushed by the runtime ccbot bridge.

Constraint: Preserve the existing 1 Topic = 1 Window = 1 Session contract and window_id-based routing.
Rejected: Keep sending Codex pane snapshots from ccbot core | It produced noisy Telegram snapshots instead of Claude-style final responses.
Confidence: high
Scope-risk: moderate
Directive: Runtime validation still depends on the external OMX ccbot-bridge.mjs hook for Codex turn-complete pushes.
Tested: git diff --cached --check; uv run --extra dev ruff check src/ tests/; uv run --extra dev ruff format --check src/ tests/; uv run --extra dev pyright src/ccbot/; uv run --extra dev pytest (270 passed)
Not-tested: MR creation and remote CI
Co-authored-by: OmX <omx@oh-my-codex.dev>

* Codex topic routing absorbs claude branch validation assets

The Codex base branch (8773850) ships the architectural decisions —
auto provider detection, Literal type hint, stale cleanup protection,
bot.py / message_queue.py / hook.py integration — but lacks the
validation/documentation assets developed on the claude branch
(ccbot-codex-connect-by-cluade). This commit imports those assets
without altering Codex base architecture.

Constraint: Preserve every Codex base behavior (provider detection,
session_map cleanup guard, paste-buffer composer route, polling parser);
only add backward-compat, regression coverage, and design records.
Rejected: Always serialize 'provider' in WindowState.to_dict | every
existing state.json row would gain "provider": "claude", silently
breaking grep/jq tooling and inflating storage for users on legacy
state files.
Rejected: Trust the first window_display_names fallback match | stale
@old codex window_ids can remain after ccbot kickstart and would route
ccbot send --window codex to a dead window_id — silent Telegram fail.
Confidence: high
Scope-risk: narrow (only WindowState serialization + send fallback
guard mutate runtime; rest is docs and tests).
Directive: Keep window_display_names fallback constrained to window_ids
present in thread_bindings; omit default provider from to_dict;
preserve claude branch's M1/M2 plan and the codex thinking pane trace
as regression fixture.

Imported assets:
- plans/2026-05-07-codex-omx-ccbot-연동.md  (M1 양방향 폐루프 design)
- plans/2026-05-08-codex-thinking-status-알림-design.md  (M2 spec)
- plans/2026-05-08-codex-thinking-status-구현.md          (M2 TDD plan)
- tests/ccbot/fixtures/codex_thinking_trace.txt
    3,237-line live capture-pane trace anchoring CODEX_THINKING_RE /
    CODEX_TOOL_RE regression coverage.

Code changes:
- src/ccbot/session.py — WindowState.to_dict omits provider when default
  ('claude'); from_dict already restores 'claude' on missing key.
- src/ccbot/send.py — _resolve_routing fallback now intersects
  window_display_names with thread_bindings.values() so stale wids
  are not picked.

Test deltas (+8 net):
- tests/ccbot/test_session.py: +2 cases
    test_to_dict_omits_default_provider_for_backward_compat
    test_from_dict_legacy_state_defaults_to_claude
- tests/ccbot/test_send.py: rebuilt as TestResolveRouting class
    state_file_missing_returns_none
    resolve_routing_by_window_name (codex base preserved)
    window_states_match_by_session_id
    fallback_to_display_names_when_window_states_empty
    fallback_skips_stale_window_id_not_in_thread_bindings (new guard)
    fallback_does_not_apply_for_session_id_only
    no_match_anywhere_returns_none
    no_thread_binding_returns_none

Tested: uv run --extra dev pytest tests/ -q (278 passed);
uv run --extra dev ruff check src/ tests/ (All checks passed);
uv run --extra dev ruff format --check src/ tests/ (53 files formatted);
uv run --extra dev pyright src/ccbot/ (0 errors, 0 warnings).
Not-tested: MR creation and remote CI.

Co-authored-by: claude (ccbot-codex-connect-by-cluade)
Co-authored-by: codex (codex-connext-by-code, codex-connext-by-code-v2)

---------

Co-authored-by: OmX <omx@oh-my-codex.dev>
…ue (#2)

* fix(queue): drop immediate status enqueue after content tasks

Status was being re-sent immediately after every content message
via _check_and_send_status, pushing the latest answer above the
status indicator. The user could not see their final answer because
'⚙️ working' kept appearing below it.

Delegate status display entirely to status_polling (1s interval).
The answer now stays as the last visible message; status only
appears in gaps longer than ~1s and is converted into the next
content message via _convert_status_to_content.

Removed 3 immediate _check_and_send_status calls (tool_result edit
path, fallback edit path, normal content send path).

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

* fix: persist status message IDs and clean up orphans on restart

Status messages were tracked in-memory only. On each ccbot restart,
old status messages (Metamorphosing…, Baked for Ns, etc.) were
orphaned in Telegram while new ones were created, causing them to
accumulate with each restart.

Fix:
- session.py: add status_msg_ids field, persist to state.json
- message_queue.py: call session_manager on send/delete
- bot.py post_init: delete persisted status messages on startup

Also adds ccbot send subcommand dispatch to main.py (from this session).

Also: add CCBOT_SHOW_TOOL_CALLS=false to ~/.ccbot/.env so tool_use/
tool_result are filtered before the batcher, reducing batch summary noise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: clear persisted status msg ID when converting status to content

_convert_status_to_content edits the Telegram message in-place to show
Claude's response. The message ID is no longer a status message, but
session_manager.status_msg_ids still held the old ID — causing ccbot to
delete the content message on next restart.

Clear the persisted ID immediately after popping from _status_msg_info,
before any edit/delete attempt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a turn ends but a backgrounded Bash tool is still alive, Claude Code
briefly shows a spinner line like '· Sautéed for 3s · 1 shell still running'
above the chrome separator. status_polling caught this as a working status
and enqueued a new status message — but since the line lacks 'esc to
interrupt', no further updates arrive and the message is left stale on
Telegram after the background shell exits.

Filter spinner lines that match the background-shell indicator pattern
(/\d+ shells? still running/) and contain no 'esc to interrupt' signal —
treat them as turn-complete, not as active working state.

Tests cover both the filtering (1 shell / 2 shells / Generating variant)
and the regression guard for genuine active working spinners.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
상단에 fork notice 추가하여 TejNote/ccbot이 six-ddc/ccbot 의 fork임을 명확히
표시. Features 섹션을 'Upstream' / 'Fork additions' 두 그룹으로 분리해
어떤 기능이 fork 추가분인지 한눈에 보이도록 정리.

Codex/OMX provider 라우팅, plugin skill menu (`/favorite`+사용 빈도 sorting),
MessageBatcher, DirectMessage 큐, `ccbot send` CLI subcommand, status msg ID
영속화, parse_status_line의 background-shell spinner 차단 등 fork 추가 기능을
Fork additions 절에 항목별로 설명. 옵션 env 변수 표에도 🔱 마크로 fork-only
설정(`CCBOT_BATCH_WINDOW`, `CCBOT_SHOW_USER_MESSAGES`,
`CCBOT_SHOW_TOOL_CALLS`)을 표시.

File Structure 트리에 send.py / skill_registry.py / message_batcher.py 등
신규 파일과 수정된 모듈을 🔱 표시와 함께 명시.

Changelog (fork) 섹션 신설 — 머지된 PR(#1, #2, #4, #5)과 주요 commit을 시간
역순으로 정리하고, 아직 fork에 반영 안 된 upstream 커밋 3건(six-ddc#67, six-ddc#73,
f5ddd7f)을 'Pending upstream merges' 표로 트래킹.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
기존 fork는 pyproject.toml version=0.1.0으로 박제된 채 변경 이력만 README에 누적되어 있어 "지금 어떤 버전이고 뭐가 새로 들어갔는지" 추적이 어려웠음. SemVer + CHANGELOG.md 체계로 전환해 슬랙 공유 시 vX.Y.Z 변경분만 전달 가능하게 함.

변경
- pyproject.toml: 0.1.0 → 1.0.0
- CHANGELOG.md 신설 (Keep a Changelog 포맷)
  - v1.0.0 = fork 누적분 전체 (Codex routing, skill menu, MessageBatcher,
    DirectMessage queue, ccbot send CLI, status msg orphan cleanup,
    spinner 무시, busy-state guard 등)
  - Added/Changed/Fixed/Pending upstream merges 카테고리로 재구성
- README.md Changelog 섹션 39줄 → 3줄로 단순화 (CHANGELOG.md 링크만 유지)

정책
- MAJOR: 호환성 깨는 변경 (state.json 스키마, .env 키 rename, CLI 인자)
- MINOR: 기능 추가 (provider, hook, 명령어)
- PATCH: 버그픽스, 안정성, 문서

다음 릴리스부터는 [Unreleased] 섹션에 누적 → 릴리스 시 promote + tag.

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

TejNote commented May 14, 2026

잘못된 repo로 PR 생성됨. TejNote/ccbot fork 내부 운영 PR입니다. 닫고 fork 쪽에 다시 생성하겠습니다.

@TejNote TejNote closed this May 14, 2026
@TejNote TejNote deleted the chore/versioning-v1.0.0 branch May 14, 2026 02:39
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