fix(branch,workflow): branch agent state 유지 + workflow filter 유지 (T1~T4)#300
Conversation
branch shadow conv (`branch:<branchId>`) 진입 시 부모 conv 의 engine/model/persona 를 shadow conv 키로 상속한다. 상속 저장은 set() (selectedConversationId 변경) 이후 호출하여 NewMessageInput 의 restore effect 가 상속값을 읽도록 한다. 부모 engine 미설정 시 상속하지 않아 기존 default 동작을 보존한다 (INV-BAF-2). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
상속 저장을 첫 진입에만 적용하도록 `!getConversationEngine(branchConvId)` 조건을 추가한다. 사용자가 branch 안에서 engine 을 명시적으로 바꾼 뒤 나갔다 재진입할 때 부모 engine 으로 덮어쓰지 않고 그 선택을 보존한다. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
onStatusChanged 콜백에서 setActiveStage("plan-check") 를 제거한다. status
변경(done/draft 등) 시마다 필터가 plan-check 으로 강제 리셋되던 회귀를
없앤다. setPlanRefreshKey 는 유지하여 plan 리스트는 갱신된다. phase 변경
시의 자동 stage 전환(onPhaseChanged → PHASE_TO_STAGE)은 그대로 보존한다
(INV-BAF-4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ge (T4) - openBranchStream: 첫 진입 부모 engine 상속(INV-BAF-1) / 재진입 시 사용자 선택 보존(T2) / 부모 미설정 시 상속 안 함(INV-BAF-2) — 실제 store action 구동 - CenterPanel: onStatusChanged 가 활성 필터를 plan-check 으로 리셋하지 않음 (INV-BAF-3) / phase 변경 시 PHASE_TO_STAGE 자동 전환 보존(INV-BAF-4) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request resolves issues with workflow filter persistence and branch conversation state. Specifically, it prevents resetting the active workflow filter to 'plan-check' upon status changes in CenterPanel, and inherits the parent conversation's engine configuration when entering a branch conversation in branchSlice. Comprehensive tests have also been added to verify these behaviors. The reviewer recommends shallow copying the inherited parentEngine object to prevent potential shared-state mutation bugs.
| const parentEngine = get().getConversationEngine(selectedConversationId); | ||
| if (parentEngine && !get().getConversationEngine(branchConvId)) { | ||
| get().saveConversationEngine(branchConvId, parentEngine); | ||
| } |
There was a problem hiding this comment.
To prevent accidental shared-state mutation bugs, it is highly recommended to shallow copy the parentEngine object when inheriting it for the branch conversation. In state management libraries like Zustand, sharing the same object reference across multiple keys can lead to unexpected side effects if any part of the application mutates the state object directly.
| const parentEngine = get().getConversationEngine(selectedConversationId); | |
| if (parentEngine && !get().getConversationEngine(branchConvId)) { | |
| get().saveConversationEngine(branchConvId, parentEngine); | |
| } | |
| const parentEngine = get().getConversationEngine(selectedConversationId); | |
| if (parentEngine && !get().getConversationEngine(branchConvId)) { | |
| get().saveConversationEngine(branchConvId, { ...parentEngine }); | |
| } |
…persist hotfix 매니페스트 4 곳 + Cargo.lock bump. CHANGELOG entry 추가. 핵심 fix (PR #300, merge 56cf50c): - branch shadow conv engine 상속 (engine/model/persona reset 회복) - workflow filter 유지 (plan status 변경 시 plan-check 강제 리셋 제거) 다모앙 커뮤니티 사용자 보고 2건. frontend 한정, FE 491→496. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…se 2 archive 이동 다모앙 사용자 요청. 기존 4개 문서 정책 (navigationModel/versioningPolicy/ metadataSchema/namingRule) 정합 분석 후 월폴더 신설 대신 메타+인덱스 방향. Phase 1 (가상 필터 + index 자동 + Gemini #300 shallow copy) / Phase 2 (완료 archive 이동) 분리. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… 1) (#301) * feat(docs-panel): join DB plan metadata + status/date filter for plans section (T1+T2) docs/plans 항목에 DB `plans` 테이블 (`list_plans_by_project`) 메타 join — `docs/plans/{slug}.md` 파일명 slug → plan lookup → status 배지 표시. status (all/draft/active/done/abandoned) + 날짜 (all/7d/30d/이번달, updated_at) 가상 필터 추가 (frontend state, 경로 불변). DB 미등록 doc·동반 파일·디렉터리는 graceful (배지 없음 + 필터 무관 항상 표시, INV-DPO-1). i18n ko/en. T1(join/배지)·T2(필터 UI)는 같은 DocsSection 재작성 단위라 합본 커밋 (T2 의 slugToPlan 의존 + 단일 파일 hunk 분리 비현실적). 회귀 0 — 필터 미사용 시 원본 entries 그대로. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(plans): auto-generate index.md active table + archive summary (T3) `regenerate_plans_index` command 추가 — DB `plans` 테이블 (project_key join) 기준으로 docs/plans/index.md 의 자동 영역만 갱신. 마커 (`<!-- AUTO-INDEX-START/END -->`) 기반 부분 갱신으로 수동 설명 영역 (navigationModel 구조 안내) 보존 (INV-DPO-4). 마커 없으면 append, 있으면 교체. active 테이블 (title/status/updated_at/slug link, updated_at DESC) + archive 요약 (done/abandoned 카운트). 경로 불변 — 파일 이동 없음. 순수 helper (build_plans_index_block / merge_index_block) 분리 + 5 unit test. docs/plans/index.md 에 마커 seed (수동 통계/설명 보존). frontend API binding (regeneratePlansIndex) 추가. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(branch): shallow copy inherited engine (gemini PR #300 review, T4) shadow conv 가 parent conv 의 engine state 를 상속할 때 객체 참조를 공유하면 이후 parent mutation 이 branch 로 새는 위험 (Gemini PR #300 review medium). `saveConversationEngine(branchConvId, parentEngine)` → `{ ...parentEngine }` shallow copy. ConversationEngineState 는 1-depth primitive 필드라 shallow 로 완전 격리. PR #300 상속 동작 자체는 보존. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(docs-panel,branch): filter join + shallow copy coverage + helper extract (T5) T1/T2 순수 로직 (slug join / companion 판별 / 날짜 버킷 / 트리 필터) 을 planDocsFilter.ts 로 추출 (DocsSection 은 import 만) → 단위 테스트 가능화. - docsPlansFilter.test.ts: slug 매칭 / DB 미등록 graceful / 동반 파일 평면 / windows 경로 / 7d·30d·month 경계 / status·date 트리 필터 (회귀 0 가드 포함). - branchEngineShallowCopy.test.ts: T4 상속 보존 + parent mutation 독립 격리 (별 참조) + re-entry 보존 (INV-BAF-2). vitest 496 → 513 (+17). DocsSection 동작 불변 (helper 추출 리팩토링만). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: dghong <d9ng@outlook.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
요약
다모앙 커뮤니티 사용자 보고 2건 (frontend 한정):
docs/plans/branchAgentStateAndFilterPersistPlan_2026-05-29.mddocs/prompts/branchAgentStateAndFilterPersistDeveloperHandoff_2026-05-29.mdTask 별 변경
src/stores/slices/branchSlice.tsopenBranchStream에서set()이후 부모 conv engine 을 shadow conv 키(branch:<branchId>)로 상속. 부모 미설정 시 상속 안 함 (INV-BAF-2)src/stores/slices/branchSlice.ts!getConversationEngine(branchConvId)조건으로 첫 진입만 상속 — 재진입 시 사용자가 branch 안에서 바꾼 engine 보존src/components/tunaflow/CenterPanel.tsxonStatusChanged에서setActiveStage("plan-check")제거.setPlanRefreshKey유지.onPhaseChanged → PHASE_TO_STAGE자동 전환은 보존 (INV-BAF-4)src/tests/branchAgentStateAndFilterPersist.test.tsx변경 통계: 3 files, +232 / -1 (T4 테스트 214줄 포함). 실 로직 변경은 branchSlice +5줄, CenterPanel -1줄.
Verification
npx tsc --noEmit— PASS (0 error)npx vitest run— 496 passed (baseline 491 + T4 5건)cargo check— Finished, 0 변경 (Rust 영역 미수정)회귀 가드 (handoff §6)
git diff main -- src-tauri/→ 0줄 (Rust 미변경)git diff main -- NewMessageInput.tsx→ 0줄 (restore effect 보존)setActiveStage("plan-check")한 줄 제거만 —onPhaseChanged핸들러 +PHASE_TO_STAGE매핑 byte-identical (보존)if (parentEngine && !get().getConversationEngine(branchConvId))상속 가드 확인RT participants scope 명시
본 PR 은 engine 상속만 다룸. RT config (participants/mode, DB
rt_config) 상속은 별 이슈 — 사용자 보고의 "agent 활성화" 가 engine selector 면 본 PR 로 해결, RT participants 면 별 plan 으로 escalate (Non-goal 명시).환경 메모
worktree 에
node_modules/src-tauri/binaries부재 → main repo symlink 사용 (커밋 영향 없음, 미스테이지).🤖 Generated with Claude Code