Repository navigation
fix(bridge/memory): close audience-routed pending jobs as superseded after a mode switch (#2333) - #2410
Merged
Conversation
…after a mode switch (#2333) After a node switches CCC_BRIDGE_MEMORY_MODE from audience-scoped to off/curated, audience-routed distill jobs left at local_sink_status pending (or retryable_failed) were never claimed again: claim_local_sink returned None forever and observers kept counting them as unmatched backlog. #2296 only adopts route-free UNROUTABLE work. These jobs are deliberately NOT adopted into the node-global sink: audience-scoped content may belong to a non-owner audience, and the global memory is the owner's own (privacy boundary). Instead: - claim_local_sink with a global route and no audience routes closes a routed PENDING/RETRYABLE_FAILED job as superseded: local_sink_status TERMINAL_FAILED plus error_code "local_sink_superseded_route" (status, error_code, updated_at only; no lease, no attempt, nothing written). global_route=False keeps the historical None/pending contract. - Rollback-safe: no new status value. Pre-#2333 list_jobs() and recover_stale_running() raise on an unknown status, which would stall the whole local-sink loop after a self-update rollback; the chosen representation parses there as plain terminal work (tested against the 22d2478 sources). - Wiki-sink writes share error_code; they now keep the marker. - With audience_routes, exactly these marked jobs are claimable again like PENDING (attempt counter preserved), so re-enabling audience mode writes them to their original audience once. The local-sink loop offers them only to a worker with audience routes (new CodexDistillLocalSinkWorker.audience_routes_enabled); genuine terminal failures are never resumed. - Retention: terminal like DONE/UNROUTABLE; the sweep passes keep_superseded_route while audience routes exist. - ccc-memory-check.sh projects the marked records as local status superseded_route, neither pending nor degraded. - docs/memory.md documents the behavior; changelog fragments added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 tasks
jinon86
previously approved these changes
Oct 20, 2026
jinon86
left a comment
Contributor
There was a problem hiding this comment.
Approved after exact-head validation and fresh operator authorization using the relay-held jinon86 credential.
…oute-pending # Conflicts: # docs/memory.md
jinon86
approved these changes
Oct 20, 2026
jinon86
left a comment
Contributor
There was a problem hiding this comment.
Approved after exact-head validation and fresh operator authorization using the relay-held jinon86 credential.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2333
문제
메모리 모드가 audience에서
off/curated로 바뀌면, audience 시절에 라우팅된local_sink_status=pending잡을 local sink가 끝내 가져가지 않습니다(distill_journal.py:645). 저널은 pending으로 굳고, 관측기는 이 잡들을 "미연결 backlog"로 계속 보고합니다.결정: 전역 편입 대신 종결
audience 라우팅된 잡에는 오너가 아닌 audience의 내용이 들어 있을 수 있습니다. 반면 node-global 메모리는 오너 전용입니다. 그래서 전역 sink로 편입하지 않고 명시적으로 종결합니다. 이슈는 두 방식을 모두 허용합니다.
변경
local_sink_status=terminal_failed와error_code="local_sink_superseded_route"로 표현합니다. 처음 시도한superseded_route새 상태는 이전 빌드의list_jobs()·recover_stale_running()이ValueError로 멈추게 만들었고, 이를 재현한 뒤 폐기했습니다.PENDING/RETRYABLE_FAILED이고audience_routes=False,global_route=True일 때만 전환합니다. 바뀌는 것은 status·error_code·updated_at뿐이며 어떤 메모리 저장소에도 쓰지 않습니다. 다시 실행해도 결과는 같습니다.global_route=False이면 지금처럼 pending을 유지합니다. #2296의 UNROUTABLE 편입도 그대로입니다.error_code를 쓰는데, 다섯 군데의 쓰기 경로 모두 표식을 지우지 않도록 수정했습니다.scripts/ccc-memory-check.sh: 표식이 있는 레코드는local_status_counts.superseded_route로 따로 셉니다. degraded나 pending으로 세지 않습니다.docs/memory.md를 갱신하고 changelog 조각 2개(bridge, harness)를 추가했습니다.검증 (로컬, CI 고정 의존성 venv)
test_superseded_record_stays_readable_after_a_rollback: base22d24780의 journal 모듈을git show로 불러와, 새 코드가 쓴 레코드를list_jobs·recover_stale_running·claim·prune으로 정상 처리하는지 확인합니다.ccc-memory.test.sh193/0참고
observe-node.py는 이 레포에 없습니다. 레포 안에서 같은 저널을 읽는ccc-memory-check.sh를 갱신했습니다.🤖 Generated with Claude Code