LogoSkills

discovery-audit

Triage-then-Verify codebase-wide bug pattern audit + git worktree-isolated parallel fix (Fix-Fanout) workflow. Use when a specific bug pattern (found once) might recur elsewhere in the codebase and...

Discovery Audit & Fix-Fanout#

ํ•œ๋งˆ๋””๋กœ (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

ํ•œ ๊ณณ์—์„œ ๋ฒ„๊ทธ๋ฅผ ํ•˜๋‚˜ ๊ณ ์ณค๋Š”๋ฐ, "ํ˜น์‹œ ๊ฐ™์€ ์‹ค์ˆ˜๊ฐ€ ์ฝ”๋“œ ์ „์ฒด์— ๋” ์žˆ์ง€ ์•Š์„๊นŒ?"๊ฐ€ ๊ถ๊ธˆํ•  ๋•Œ ์“ฐ๋Š” ์ ˆ์ฐจ์ž…๋‹ˆ๋‹ค. ๊ฑด๋ฌผ ํ•œ ๊ณณ์—์„œ ํ™”์žฌ ์›์ธ์„ ํ•˜๋‚˜ ์ฐพ์•˜๋‹ค๊ณ  ๋ฐ”๋กœ ์ „์ฒด๋ฅผ ๋‹ค ๊ณ ์น˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๋จผ์ € ๋น„์Šทํ•œ ๊ณณ์„ ๋„“๊ฒŒ ํ›‘์–ด "์˜์‹ฌ๋˜๋Š” ๊ณณ ๋ชฉ๋ก"์„ ๋งŒ๋“ค๊ณ (Triage), ๊ทธ ๋ชฉ๋ก์„ ๋‹ค๋ฅธ ์ ๊ฒ€๋ฐ˜์ด ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ํ™•์ธํ•ด "์ง„์งœ ์œ„ํ—˜ํ•œ ๊ณณ"๋งŒ ์ถ”๋ ค๋‚ธ ๋’ค(Verify), ํ™•์ •๋œ ๊ณณ๋“ค๋งŒ ์—ฌ๋Ÿฌ ํŒ€์ด ๋™์‹œ์— ๋‚˜๋ˆ  ๊ณ ์น˜๋Š”(Fix-Fanout) 3๋‹จ๊ณ„ ์ ˆ์ฐจ์ž…๋‹ˆ๋‹ค. ๋„“๊ฒŒ ์ฐพ๋Š” ์‚ฌ๋žŒ๊ณผ ํ™•์ •ํ•˜๋Š” ์‚ฌ๋žŒ์„ ๋ถ„๋ฆฌํ•ด์•ผ ์˜คํƒ(๊ฐ€์งœ ๊ฒฝ๋ณด)์ด ๊ทธ๋Œ€๋กœ ์ž‘์—… ์ง€์‹œ๋กœ ์ด์–ด์ง€๋Š” ์‚ฌ๊ณ ๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌด์—‡์„ยท์–ธ์ œ (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

  • ๋ฌด์—‡์„ ํ•ด์ฃผ๋‚˜์š”
    • 1๋‹จ๊ณ„(Triage): "์ด๋Ÿฐ ํŒจํ„ด์˜ ๋ฒ„๊ทธ"๋ผ๋Š” ์„ค๋ช…์„ ์—ฌ๋Ÿฌ ์กฐ์ˆ˜์—๊ฒŒ ๋‚˜๋ˆ ์ฃผ๊ณ , ์ฝ”๋“œ ์ „์ฒด์—์„œ ์˜์‹ฌ ํ›„๋ณด ๋ชฉ๋ก์„ ๋น ๋ฅด๊ฒŒ ๋ฝ‘์Šต๋‹ˆ๋‹ค.
    • 2๋‹จ๊ณ„(Verify): ํ›„๋ณด ํ•˜๋‚˜ํ•˜๋‚˜๋ฅผ Triage์™€ ๋‹ค๋ฅธ ์กฐ์ˆ˜๊ฐ€ ์›๋ณธ ์ฝ”๋“œ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ฝ๊ณ  "์ง„์งœ ๋ฌธ์ œ์ธ์ง€" ์žฌํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ์•ˆ ์“ฐ๋Š” ์ฃฝ์€ ์ฝ”๋“œ์ธ์ง€, ์ •๋ง ๋ฉˆ์ถ”๋Š”์ง€ ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์กฐ๊ธˆ ๋Šฆ๊ฒŒ ๊ฐฑ์‹ ๋˜๋Š” ์ •๋„์ธ์ง€๊นŒ์ง€ ๋”ฐ์ง‘๋‹ˆ๋‹ค.
    • 3๋‹จ๊ณ„(Fix-Fanout): ํ™•์ •๋œ ๋ชฉ๋ก๋งŒ ๊ฐ๊ฐ ๋…๋ฆฝ๋œ ์ž‘์—… ๊ณต๊ฐ„(git worktree)์—์„œ ๋™์‹œ์— ๊ณ ์น˜๊ณ , ๊ฒ€์‚ฌโ†’์ปค๋ฐ‹โ†’ํ•ฉ์น˜๊ธฐ ์š”์ฒญ(PR)๊นŒ์ง€ ๊ฐ์ž ๋๋ƒ…๋‹ˆ๋‹ค.
  • ์–ธ์ œ ์“ฐ๋‚˜์š”
    • "์ด ๋ฒ„๊ทธ, ๋‹ค๋ฅธ ๋ฐ๋„ ์žˆ์„ ๊ฒƒ ๊ฐ™์€๋ฐ" ์‹ถ์„ ๋•Œ โ€” ์ฆ‰ ํ•œ ๋ฒˆ ์ฐพ์€ ๊ฒฐํ•จ ํŒจํ„ด์ด ์ฝ”๋“œ๋ฒ ์ด์Šค ๋‹ค๋ฅธ ๊ณณ์—๋„ ๋ฐ˜๋ณต๋์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์„ ๋•Œ.
    • ํ™•์ •๋œ ๋ฌธ์ œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฑด์ด๋ผ ํ•œ ๋ช…์ด ์ˆœ์„œ๋Œ€๋กœ ๊ณ ์น˜๋ฉด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๋•Œ.
  • ์ฃผ์˜ํ•  ์ : ๋„“๊ฒŒ ์ฐพ๋Š” ์‚ฌ๋žŒ์ด ์Šค์Šค๋กœ "์ด๊ฑด ์ง„์งœ ๋ฌธ์ œ๋‹ค"๊นŒ์ง€ ํ™•์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ๋ณ„๋„์˜ ํ™•์ธ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผ ๊ฐ€์งœ ๊ฒฝ๋ณด๊ฐ€ ์‹ค์ œ ์ž‘์—…์œผ๋กœ ์ด์–ด์ง€๋Š” ๊ฒƒ์„ ๋ง‰์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ์šฉ์–ด (๋น„๊ฐœ๋ฐœ์ž์šฉ)#

์šฉ์–ด์‰ฌ์šด ์„ค๋ช…
Triage(ํŠธ๋ฆฌ์•„์ง€)๋„“๊ณ  ๋น ๋ฅด๊ฒŒ ํ›‘์–ด "์˜์‹ฌ ํ›„๋ณด"๋งŒ ๊ณจ๋ผ๋‚ด๋Š” 1์ฐจ ์„ ๋ณ„ ๋‹จ๊ณ„
Verify(๊ฒ€์ฆ)ํ›„๋ณด๋ฅผ ๋ณ„๋„ ์ธ๋ ฅ์ด ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ํ™•์ธํ•ด ์ง„์งœ/๊ฐ€์งœ๋ฅผ ๊ฐ€๋ฆฌ๋Š” 2์ฐจ ํ™•์ธ ๋‹จ๊ณ„
์ ๋Œ€์  ๊ฒ€์ฆ"์ด๊ฒŒ ์ง„์งœ ๋งž๋‚˜?"๋ฅผ ์˜์‹ฌํ•˜๋Š” ํƒœ๋„๋กœ ์žฌํ™•์ธํ•˜๋Š” ๊ฒƒ โ€” ์ฐพ์€ ์‚ฌ๋žŒ์ด ์Šค์Šค๋กœ ํ™•์ •ํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๋Š” ์•ˆ์ „์žฅ์น˜
Fix-Fanoutํ™•์ •๋œ ์—ฌ๋Ÿฌ ๊ฑด์„ ๋™์‹œ์— ๋‚˜๋ˆ  ๊ณ ์น˜๋Š” ๋ณ‘๋ ฌ ์ˆ˜์ • ๋‹จ๊ณ„
git worktree๊ฐ™์€ ํ”„๋กœ์ ํŠธ๋ฅผ ์™„์ „ํžˆ ๋…๋ฆฝ๋œ ์ž‘์—… ๊ณต๊ฐ„์œผ๋กœ ๋ถ„๋ฆฌํ•ด ์„œ๋กœ ๊ฐ„์„ญ ์—†์ด ๋ณ‘๋ ฌ ์ž‘์—…ํ•˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•
์ฃฝ์€ ์ฝ”๋“œ(dead code)์ด์ œ ์•„๋ฌด๋„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”, ๊ณ ์ณ๋„ ์˜๋ฏธ ์—†๋Š” ์ฝ”๋“œ
Self-healing์ž ๊น ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ๋„ ๋‹ค์Œ ๋™์ž‘(์˜ˆ: ๋‹ค์Œ ํŽ˜์ด์ง€ ์ด๋™)์—์„œ ์ €์ ˆ๋กœ ๋ณต๊ตฌ๋˜๋Š” ๊ฒฝ๋กœ
Rate limitํ•œ๊บผ๋ฒˆ์— ๋„ˆ๋ฌด ๋งŽ์€ ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉด ์„œ๋ฒ„๊ฐ€ "์ž ์‹œ ์ฒœ์ฒœํžˆ ๋ณด๋‚ด๋ผ"๊ณ  ์ œํ•œํ•˜๋Š” ๊ฒƒ

์–ธ์ œ ์ด ํŒจํ„ด์„ ์“ฐ๋Š”๊ฐ€#

๋ฒ„๊ทธ๋ฅผ ํ•˜๋‚˜ ๊ณ ์น˜๊ณ  ๋‚˜์„œ "์ด ํŒจํ„ด์ด ์ฝ”๋“œ๋ฒ ์ด์Šค ๋‹ค๋ฅธ ๊ณณ์—๋„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค"๋Š” ํ™•์‹ ์ด ๋“ค ๋•Œ. ์˜ˆ๋ฅผ ๋“ค์–ด:

  • ํŠน์ • ์–ธ์–ด/ํ”„๋ ˆ์ž„์›Œํฌ ํ•จ์ •(์˜ˆ: [cc-flutter-dev:swr-pattern]์˜ unawaited() + Error ์นจ๋ฌต ์‹คํŒจ ํ•จ์ •)์„ ํ•˜๋‚˜ ๋ฐœ๊ฒฌํ–ˆ๊ณ , grep์œผ๋กœ ํ›„๋ณด๋ฅผ ๋„“๊ฒŒ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ
  • ๊ฐ™์€ ์•ˆํ‹ฐํŒจํ„ด(์˜ˆ: ํŠน์ • API์˜ ์ž˜๋ชป๋œ ์‚ฌ์šฉ๋ฒ•)์ด ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์— ๋ฐ˜๋ณต๋์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๊ฒฝ์šฐ

์ด ํŒจํ„ด์€ ํ•œ ์—์ด์ „ํŠธ๊ฐ€ "์ฐพ๊ณ  โ†’ ํ™•์ •ํ•˜๊ณ  โ†’ ๊ณ ์น˜๋Š”" ๊ฒƒ์„ ์ „๋ถ€ ํ˜ผ์ž ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์›์น™ ์œ„์— ์„œ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐพ๊ธฐ(๋„“๊ฒŒ, ๋น ๋ฅด๊ฒŒ)์™€ ํ™•์ •(์ข๊ฒŒ, ๋А๋ฆฌ๊ฒŒ, ์ ๋Œ€์ )์„ ๋ถ„๋ฆฌํ•ด์•ผ, ํ›„๋ณด ๋‹จ๊ณ„์˜ ์˜คํƒ์ด ๊ทธ๋Œ€๋กœ ์ˆ˜์ • PR๋กœ ์ด์–ด์ง€๋Š” ์‚ฌ๊ณ ๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3๋‹จ๊ณ„ ๊ตฌ์กฐ#

Phase 1: Triage (๋„“๊ฒŒ, ๋น ๋ฅด๊ฒŒ, ํ›„๋ณด ์œ„์ฃผ)
  โ†’ gray-list ์ƒ์„ฑ โ†’ ์ฒญํฌ ๋ถ„ํ•  โ†’ ๋ณ‘๋ ฌ ์—์ด์ „ํŠธ์— ๋ฐฐ๋ถ„
Phase 2: Verify (์ข๊ฒŒ, ๋А๋ฆฌ๊ฒŒ, ์ ๋Œ€์ /๋…๋ฆฝ์ )
  โ†’ ํ›„๋ณด๋งˆ๋‹ค ๋ณ„๋„ ์—์ด์ „ํŠธ๊ฐ€ ์›๋ณธ ์†Œ์Šค๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌํ™•์ธ
  โ†’ dead code / self-healing / ์˜ค์ง„๋‹จ ์—ฌ๋ถ€๊นŒ์ง€ ์žฌํ‰๊ฐ€
Phase 3: Fix-Fanout (worktree ๊ฒฉ๋ฆฌ ๋ณ‘๋ ฌ ์ˆ˜์ •)
  โ†’ ํ™•์ •๋œ ํ•ญ๋ชฉ๋งŒ ๊ฐ์ž ๋…๋ฆฝ worktree์—์„œ ๋ธŒ๋žœ์น˜โ†’์ˆ˜์ •โ†’๊ฒ€์ฆโ†’PR

ํ•œ ์„ธ์…˜์—์„œ Phase 1โ†’2โ†’3์„ ์ˆœ์„œ๋Œ€๋กœ(Verify๋ฅผ ํ†ต๊ณผํ•œ ๊ฒƒ๋งŒ Phase 3๋กœ) ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์›์น™์ด๋ฉฐ, Phase 2๊ฐ€ Phase 1์˜ ๊ฒฐ๊ณผ(ํŠนํžˆ severity)๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฏฟ์ง€ ์•Š๊ณ  ์žฌํ‰๊ฐ€ํ•œ๋‹ค๋Š” ์ ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.


Phase 1 โ€” Triage (๋„“๊ฒŒ, ๋น ๋ฅด๊ฒŒ, ํ›„๋ณด ์œ„์ฃผ)#

๋ชฉํ‘œ#

์ •ํ™•๋„๋ณด๋‹ค **์žฌํ˜„์œจ(recall)**์„ ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‹จ๊ณ„์˜ ๋ชฉ์ ์€ ํ™•์ •์ด ์•„๋‹ˆ๋ผ "๋‹ค์Œ ๋‹จ๊ณ„์—์„œ ๊ฒ€ํ† ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š” ํ›„๋ณด ๋ชฉ๋ก"์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ ˆ์ฐจ#

  1. grep ๋“ฑ์œผ๋กœ ๊ฒฐํ•จ ํŒจํ„ด์ด ์žˆ์„ ๋งŒํ•œ ํŒŒ์ผ์˜ gray-list(์ „์ˆ˜ ๋ชฉ๋ก)๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
    • ์˜ˆ: grep -rl "unawaited(" --include="*.dart" feature/ package/ app/ | grep -v _test.dart
  2. gray-list๋ฅผ ํฐ ์ฒญํฌ(์˜ˆ: ํŒŒ์ผ 18~40๊ฐœ์”ฉ)๋กœ ๋‚˜๋ˆ  ๋ณ‘๋ ฌ ์—์ด์ „ํŠธ์— ๋ฐฐ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ฐ ์—์ด์ „ํŠธ ํ”„๋กฌํ”„ํŠธ์—๋Š” ์ •ํ™•ํžˆ ์–ด๋–ค ํŒจํ„ด์„ ์ฐพ๋Š”์ง€์™€ ์Šค์ฝ”ํ”„ ์ถ•์†Œ ๋ฌธ๊ตฌ๋ฅผ ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
    • "unawaited() ํ˜ธ์ถœ ์ž์ฒด๊ฐ€ ๋‚˜์˜๋‹ค๋Š” ๊ฒŒ ์•„๋‹ˆ๋‹ค โ€” ๊ทธ ์•ˆ์˜ ํ˜ธ์ถœ ์ฒด์ธ์ด Error๋ฅผ ๋†“์น˜๋Š” catch๋งŒ ์žˆ๋Š” ๊ฒฝ์šฐ๋งŒ ํ›„๋ณด๋กœ ํ‘œ์‹œํ•˜๋ผ"์ฒ˜๋Ÿผ, ๋ฌด์—‡์ด ์•„๋‹Œ์ง€๋„ ๋ช…์‹œํ•ด์•ผ ์˜คํƒ์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

Workflow ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์‹œ (Triage)#

export const meta = {
  name:  ' unawaited-error-triage ' ,
  description:  ' unawaited() ํ˜ธ์ถœ ์ฒด์ธ์˜ Error ๋ˆ„๋ฝ ํ›„๋ณด ๊ฐ์‚ฌ ' ,
  phases: [{ title:  ' Triage '   }],
}

// gray-list๋Š” ์Šคํฌ๋ฆฝํŠธ ๋ณธ๋ฌธ์— ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ง์ ‘ ๋ฐ•์•„๋„ฃ๋Š”๋‹ค (์•„๋ž˜  " ์šด์˜์ƒ ์ฃผ์˜์  "   ์ฐธ์กฐ)
const GRAY_LIST = [/* 274๊ฐœ ํŒŒ์ผ ๊ฒฝ๋กœ */]
const CHUNK_SIZE = 30 // rate limit ์‹œ ๋Š˜๋ ค์„œ ๋™์‹œ์„ฑ์„ ์ค„์ธ๋‹ค

const chunks = []
for (let i = 0; i  <   GRAY_LIST.length; i += CHUNK_SIZE) {
  chunks.push(GRAY_LIST.slice(i, i + CHUNK_SIZE))
}

const CANDIDATES_SCHEMA = { /* { file, function, line, callChain, reason } ๋ฐฐ์—ด */ }

const results = await parallel(chunks.map(chunk = >   () = > 
   agent(
    `๋‹ค์Œ ํŒŒ์ผ๋“ค์—์„œ unawaited(fn()) ํŒจํ„ด์„ ์ฐพ์•„๋ผ: ${chunk.join( ' ,  ' )}\n` +
    `์ฐพ์„ ๊ฒƒ: fn()์˜ ์ „์ฒด ํ˜ธ์ถœ ์ฒด์ธ์—์„œ ๋ชจ๋“  catch ์ ˆ์ด on Exception๋งŒ ์žก๊ณ  Error(TypeError, ` +
    `StateError, NoSuchMethodError, JsonUnsupportedObjectError ๋“ฑ)๋ฅผ ๋†“์น˜๋Š” ๊ฒฝ์šฐ.\n` +
    `์ฃผ์˜: unawaited() ์ž์ฒด๊ฐ€ ๋‚˜์œ ๊ฒŒ ์•„๋‹ˆ๋‹ค โ€” ์œ„ ์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ๋งŒ ํ›„๋ณด๋กœ ๋ณด๊ณ ํ•˜๋ผ.`,
    { phase:  ' Triage ' , schema: CANDIDATES_SCHEMA }
  )
))

const candidates = results.filter(Boolean).flatMap(r = >   r.candidates)

Phase 2 โ€” Verify (์ข๊ฒŒ, ๋А๋ฆฌ๊ฒŒ, ์ ๋Œ€์ /๋…๋ฆฝ์ )#

์›์น™: ์ฐพ์€ ์—์ด์ „ํŠธ๊ฐ€ ์Šค์Šค๋กœ ํ™•์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค#

Triage์—์„œ ๋‚˜์˜จ ๊ฐ ํ›„๋ณด๋Š” Triage์™€ ๋ณ„๋„์˜, ๋…๋ฆฝ์ ์ธ ์—์ด์ „ํŠธ๊ฐ€ ์‹ค์ œ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ฝ๊ณ  ์žฌํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์—์ด์ „ํŠธ๊ฐ€ ์ฐพ๊ณ  ์Šค์Šค๋กœ ํ™•์ •๊นŒ์ง€ ํ•˜๋ฉด, ์˜คํƒ(false positive)์ด ๊ทธ๋Œ€๋กœ ํ™•์ •๋œ ๊ฒฐํ•จ์œผ๋กœ ๊ตณ์–ด์ง‘๋‹ˆ๋‹ค.

๋ฐ˜๋“œ์‹œ ํ™•์ธํ•ด์•ผ ํ•˜๋Š” 3๊ฐ€์ง€#

ํ™•์ธ ํ•ญ๋ชฉ๋ฐฉ๋ฒ•์‹ค์ธก ์˜ˆ
์ฃฝ์€ ์ฝ”๋“œ/๋„๋‹ฌ ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒฝ๋กœ์ธ๊ฐ€ grep์œผ๋กœ ์‹ค์‚ฌ์šฉ ํ˜ธ์ถœ๋ถ€ ํ™•์ธ "high" ๋“ฑ๊ธ‰ ํ›„๋ณด 2๊ฑด์ด @Deprecated/๊ณ ์•„ ์ฝ”๋“œ๋กœ ๊ธฐ๊ฐ
์†Œ๋น„์ž๊ฐ€ ์ •๋ง "์˜์›ํžˆ ๋ฉˆ์ถ”๋Š”"๊ฐ€, ์•„๋‹ˆ๋ฉด ๊ฐ’๋งŒ staleํ•ด์ง€๋Š”๊ฐ€ ์ปจ์Šˆ๋จธ(BLoC/Cubit/ValueNotifier/StreamController)์˜ ์‹ค์ œ ๋Œ€๊ธฐ ๋ฐฉ์‹ ์ถ”์  BehaviorSubject.seeded()๋Š” ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  ๊ฐฑ์‹ ๋งŒ ๋Šฆ์–ด์ง โ€” ๊ธฐ๊ฐ
self-healing ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋Š”๊ฐ€ ๋‹ค์Œ ์ด๋ฒคํŠธ/๋„ค๋น„๊ฒŒ์ด์…˜์—์„œ ์žฌ์‹œ๋„๋˜๋Š”์ง€ ํ™•์ธ ๋‹ค์Œ ํŽ˜์ด์ง€ ์ด๋™ ์‹œ ์žฌ์‹œ๋„๋˜๋Š” ๊ฒฝ๋กœ๋Š” severity ํ•˜ํ–ฅ ๊ทผ๊ฑฐ

Triage์˜ ์ฃผ์žฅ(ํŠนํžˆ severity)์„ ๊ทธ๋Œ€๋กœ ๋ฏฟ์ง€ ๋ง๊ณ , ์œ„ 3๊ฐ€์ง€๋ฅผ ๋ฐ˜๋“œ์‹œ ์žฌํ‰๊ฐ€ํ•œ ๋’ค confirmed/rejected๋ฅผ ํŒ์ •ํ•ฉ๋‹ˆ๋‹ค.

Workflow ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์‹œ (Verify)#

const VERDICT_SCHEMA = { /* { confirmed: bool, severity, reason, isDead, isSelfHealing } */ }

const verified = await parallel(candidates.map(c = >   () = > 
   agent(
    `๋‹ค์Œ ํ›„๋ณด๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌํ™•์ธํ•˜๋ผ(Triage ๊ฒฐ๊ณผ๋ฅผ ์‹ ๋ขฐํ•˜์ง€ ๋ง ๊ฒƒ): ` +
    `${c.file}:${c.line} (${c.function})\n` +
    `1) grep์œผ๋กœ ์‹ค์‚ฌ์šฉ ํ˜ธ์ถœ๋ถ€๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ โ€” ์—†์œผ๋ฉด dead code๋กœ ๊ธฐ๊ฐ\n` +
    `2) ์ปจ์Šˆ๋จธ๊ฐ€ ์ •๋ง ์˜์›ํžˆ ๋ฉˆ์ถ”๋Š”์ง€, ์•„๋‹ˆ๋ฉด ๊ฐ’๋งŒ staleํ•ด์ง€๋Š”์ง€ ํ™•์ธ\n` +
    `3) ๋‹ค์Œ ์ด๋ฒคํŠธ/๋„ค๋น„๊ฒŒ์ด์…˜์—์„œ ์žฌ์‹œ๋„๋˜๋Š” self-healing ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ\n` +
    `Triage severity๋ฅผ ๊ทธ๋Œ€๋กœ ์“ฐ์ง€ ๋ง๊ณ  ์žฌํ‰๊ฐ€ํ•˜๋ผ.`,
    { phase:  ' Verify ' , schema: VERDICT_SCHEMA }
  ).then(v = >   ({ ...c, verdict: v }))
))

const confirmed = verified.filter(Boolean).filter(v = >   v.verdict.confirmed)

Phase 3 โ€” Fix-Fanout (git worktree ๊ฒฉ๋ฆฌ ๋ณ‘๋ ฌ ์ˆ˜์ •)#

์–ธ์ œ worktree ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ๊ฐ€#

ํ™•์ •๋œ ํ•ญ๋ชฉ์ด ์—ฌ๋Ÿฌ ๊ฑด์ด๊ณ , ์„œ๋กœ ๋‹ค๋ฅธ ํŒŒ์ผ/๋ชจ๋“ˆ์„ ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ๊ณ ์ณ์•ผ ํ•  ๋•Œ. agent()์˜ isolation: 'worktree' ์˜ต์…˜์„ ์“ฐ๋ฉด ํ•ญ๋ชฉ๋‹น ๋ณ„๋„ git worktree๊ฐ€ ์ž๋™ ์ƒ์„ฑ๋˜์–ด, N๊ฐœ ์—์ด์ „ํŠธ๊ฐ€ ๋™์‹œ์— ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ โ†’ ์ฝ”๋“œ ์ˆ˜์ • โ†’ ๊ฒ€์ฆ โ†’ ์ปค๋ฐ‹ โ†’ ํ‘ธ์‹œ โ†’ PR ์ƒ์„ฑ๊นŒ์ง€ ๊ฐ์ž ๋…๋ฆฝ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•ด๋„ ๊ฐ™์€ working tree๋ฅผ ๊ณต์œ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์„œ๋กœ ์ถฉ๋Œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Serverpod 4 ํ’€์Šคํƒ์„ worktree๋งˆ๋‹ค ๋„์šฐ๋Š” ํฌํŠธยทMCP ๊ฒฉ๋ฆฌ๋Š” [cc-serverpod:serverpod-worktree-parallel] ์ฐธ์กฐ. Agent Teams(ํŒŒ์ผ ์†Œ์œ ๊ถŒ ๋ถ„๋ฆฌ๋กœ ๋ณ‘๋ ฌํ™”)์™€์˜ ์ฐจ์ด๋Š” [cc-dev-cycle:agent-teams]์˜ "ํŒŒ์ผ์‹œ์Šคํ…œ ๊ฒฉ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด git worktree์™€ ์ƒํ˜ธ๋ณด์™„" ์ฐธ์กฐ.

๊ฐ ์—์ด์ „ํŠธ ํ”„๋กฌํ”„ํŠธ์— ๋ฐ˜๋“œ์‹œ ํฌํ•จํ•  ๊ฒƒ#

ํ”„๋กฌํ”„ํŠธ์— ์•„๋ž˜๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ๋„ฃ์„์ˆ˜๋ก ์ •ํ™•๋„๊ฐ€ ๋†’์•˜์Šต๋‹ˆ๋‹ค:

  • ์ •ํ™•ํ•œ ๊ฒฐํ•จ ์„ค๋ช… โ€” ํŒŒ์ผ/ํ•จ์ˆ˜/๋ผ์ธ/ํ˜ธ์ถœ ์ฒด์ธ. Verify ๋‹จ๊ณ„์—์„œ ์ด๋ฏธ ํ™•๋ณดํ•œ ์ •๋ณด๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉํ•˜๊ณ , ์—์ด์ „ํŠธ๊ฐ€ ์ฒ˜์Œ๋ถ€ํ„ฐ ์žฌ์กฐ์‚ฌํ•˜์ง€ ์•Š๊ฒŒ ํ•œ๋‹ค.
  • ์ •ํ™•ํ•œ ์ˆ˜์ • ๋ฐฉํ–ฅ โ€” ๊ฐ€๋Šฅํ•˜๋ฉด "์ด ํ•œ ์ค„์„ ์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ”๋ผ" ์ˆ˜์ค€๊นŒ์ง€ ๊ตฌ์ฒด์ ์œผ๋กœ.
  • git/PR ํ‘œ์ค€ ์ž‘์—… ์ˆœ์„œ โ€” ๋ธŒ๋žœ์น˜๋ช… ๊ทœ์น™, ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€ ์ปจ๋ฒค์…˜, dart analyze --fatal-infos/dcm analyze ํ†ต๊ณผ ํ•„์ˆ˜, ๊ธฐ์กด ํ…Œ์ŠคํŠธ ํŒŒ์ผ์ด ์žˆ์œผ๋ฉด ํšŒ๊ท€ ํ…Œ์ŠคํŠธ 1๊ฐœ ์ถ”๊ฐ€, gh pr create, ๋จธ์ง€๋Š” ํ•˜์ง€ ๋ง ๊ฒƒ.
  • pre-push hook(lefthook ๋“ฑ) ์‹คํŒจ ์‹œ ์šฐํšŒ ๊ธˆ์ง€ โ€” ์‹คํŒจํ•˜๋ฉด ์›์ธ์„ ์ˆ˜์ •ํ•˜๋ผ๊ณ  ๋ช…์‹œ (LEFTHOOK=0 ๊ธˆ์ง€๋Š” [cc-dev-cycle:dev] ์Šคํ‚ฌ์˜ ๊ณตํ†ต ๊ทœ์น™๊ณผ ๋™์ผ).

Workflow ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์‹œ (Fix-Fanout)#

phase( ' Fix ' )
const fixResults = await parallel(confirmed.map(c = >   () = > 
   agent(
    `๋‹ค์Œ ํ™•์ •๋œ ๊ฒฐํ•จ์„ ์ˆ˜์ •ํ•˜๋ผ: ${c.file}:${c.line} (${c.function})\n` +
    `๊ฒฐํ•จ: ${c.verdict.reason}\n` +
    `์ˆ˜์ • ๋ฐฉํ–ฅ: unawaited(fn()) ๋Œ€์‹  fn()์˜ catch ์ ˆ์„ on Object catch (๋˜๋Š” ` +
    `on Exception catch + on Error catch ๋ณ‘ํ–‰)๋กœ ๋„“ํ˜€ Error๋„ ๋กœ๊น…/์ฒ˜๋ฆฌํ•˜๋ผ.\n` +
    `์ž‘์—… ์ˆœ์„œ: fix/{issue}-{slug} ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ โ†’ ์ˆ˜์ • โ†’ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ 1๊ฐœ ์ถ”๊ฐ€ โ†’ ` +
    `dart analyze --fatal-infos  & &   dcm analyze ํ†ต๊ณผ โ†’ ์ปค๋ฐ‹ โ†’ ํ‘ธ์‹œ โ†’ gh pr create.\n` +
    `๋จธ์ง€๋Š” ํ•˜์ง€ ๋งˆ๋ผ. pre-push hook ์‹คํŒจ ์‹œ ์šฐํšŒํ•˜์ง€ ๋ง๊ณ  ์›์ธ์„ ๊ณ ์ณ๋ผ.`,
    { isolation:  ' worktree ' , label: `fix:${c.file}` }
  )
))

์šด์˜์ƒ ์ฃผ์˜์  (์‹ค์ธก)#

  • args ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํฐ ๋ฐฐ์—ด(270+ ํ•ญ๋ชฉ)์„ ๋„˜๊ธฐ๋ฉด ํŒŒ์‹ฑ์ด ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค โ†’ ๋ฐ์ดํ„ฐ๋ฅผ ์Šคํฌ๋ฆฝํŠธ ๋ณธ๋ฌธ์— JS ๋ฆฌํ„ฐ๋Ÿด๋กœ ์ง์ ‘ ๋ฐ•์•„๋„ฃ๋Š” ๋ฐฉ์‹์œผ๋กœ ์šฐํšŒํ•œ๋‹ค (์œ„ Triage ์˜ˆ์‹œ์˜ GRAY_LIST ์ฐธ์กฐ).
  • "Server is temporarily limiting requests" rate limit โ†’ ์ฒญํฌ ํฌ๊ธฐ๋ฅผ ํ‚ค์›Œ ๋™์‹œ ์—์ด์ „ํŠธ ์ˆ˜ ์ž์ฒด๋ฅผ ์ค„์—ฌ์„œ ์žฌ์‹คํ–‰ํ•˜๋ฉด ํ•ด๊ฒฐ๋œ๋‹ค (์˜ˆ: 16๊ฐœ ๋™์‹œ โ†’ 5๊ฐœ ๋™์‹œ). ๋™์‹œ์„ฑ์„ ๋‚ฎ์ถ”๋ ค๋ฉด CHUNK_SIZE๋ฅผ ๋Š˜๋ ค ์ฒญํฌ(=์—์ด์ „ํŠธ) ๊ฐœ์ˆ˜๋ฅผ ์ค„์ธ๋‹ค.
  • Verify phase๋„ ๋™์ผํ•˜๊ฒŒ rate limit์— ๊ฑธ๋ฆด ์ˆ˜ ์žˆ๋‹ค (ํ›„๋ณด ์ˆ˜๋งŒํผ ๋™์‹œ ์‹คํ–‰๋˜๋ฏ€๋กœ) โ†’ ์ „์ฒด๋ฅผ ์žฌ์‹คํ–‰ํ•˜์ง€ ๋ง๊ณ  ์‹คํŒจํ•œ ๊ฒƒ๋งŒ ๊ณจ๋ผ ๋ณ„๋„๋กœ ์žฌ์‹คํ–‰ํ•œ๋‹ค. Workflow์˜ resumeFromRunId๋ฅผ ์“ฐ๋ฉด ์ด๋ฏธ ์„ฑ๊ณตํ•œ ํ˜ธ์ถœ์€ ์บ์‹œ์—์„œ ์ฆ‰์‹œ ๋ฐ˜ํ™˜๋˜๊ณ  ์‹คํŒจ/์‹ ๊ทœ ํ˜ธ์ถœ๋งŒ ์žฌ์‹คํ–‰๋œ๋‹ค.

โš ๏ธ Fix-Fanout ํ›„ ๋จธ์ง€ ์ถฉ๋Œ ํ•จ์ • โ€” ์›๋ณธ fix PR์„ ๋จผ์ € ๋จธ์ง€ํ•˜๋ผ#

๊ฐ™์€ ๊ทผ๋ณธ ์›์ธ์˜ ์—ฌ๋Ÿฌ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์‚ฌ๋กœ ์ฐพ์•„ ํŒŒ์ƒ fix๋“ค์„ ๋ณ‘๋ ฌ ๋ธŒ๋žœ์น˜๋กœ ๋”ธ ๋•Œ, ์›๋ณธ ๋ฌธ์ œ์˜ ์ตœ์ดˆ ์ˆ˜์ • PR์ด ์•„์ง ๋จธ์ง€๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ํŒŒ์ƒ fix ๋ธŒ๋žœ์น˜๋“ค์„ ๋งŒ๋“ค๋ฉด, ์›๋ณธ PR์ด ๋จผ์ € ๋จธ์ง€๋œ ๋’ค ํŒŒ์ƒ ๋ธŒ๋žœ์น˜๋“ค์ด ๊ฐ™์€ ํŒŒ์ผ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ๊ฑด๋“œ๋ฆฌ๊ณ  ์žˆ์–ด ๋จธ์ง€ ์‹œ ์ถฉ๋Œ์ด ๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ธก ์‚ฌ๋ก€: swr_strategy_impl.dart์˜ ์ค‘์ฒฉ๋œ unawaited(saveToCache) ์ˆ˜์ • PR 1๊ฑด์ด, ์ด๋ฏธ ๋จธ์ง€๋œ ์›๋ณธ ์ˆ˜์ • PR(#7746/#7748)๊ณผ ๋ณ„๋„๋กœ ๊ฐ™์€ ํŒŒ์ผ์˜ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๊ณ ์น˜๊ณ  ์žˆ์—ˆ๊ณ , ์–‘์ชฝ์ด ํšŒ๊ท€ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ๊ฐ ์ถ”๊ฐ€ํ•ด ๋ณ‘ํ•ฉ ์‹œ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์—์„œ๋งŒ ์ถฉ๋Œ์ด ๋ฐœ์ƒ(๋ณธ์ฒด ์ฝ”๋“œ๋Š” ์ž๋™ ๋ณ‘ํ•ฉ๋จ). ํ•ด๊ฒฐ: ํ•ด๋‹น ๋ธŒ๋žœ์น˜์— ์ตœ์‹  origin/development๋ฅผ merge โ†’ lib ์ฝ”๋“œ ์ถฉ๋Œ ์—†์Œ ํ™•์ธ โ†’ test ํŒŒ์ผ๋งŒ "๋‘ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๋ชจ๋‘ ์œ ์ง€"๋กœ ์ˆ˜๋™ ์ •๋ฆฌ โ†’ dart analyze/ํ…Œ์ŠคํŠธ ์žฌํ™•์ธ โ†’ merge commit push. ์ƒ์„ธ ํ•ด์†Œ ์ ˆ์ฐจ๋Š” [cc-dev-cycle:merge-conflict-resolution] ์ฐธ์กฐ.

๊ตํ›ˆ (์ฒดํฌ๋ฆฌ์ŠคํŠธํ™”):

  • Fix-Fanout์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์—, ๊ฐ™์€ ํŒŒ์ผ/ํ•จ์ˆ˜๋ฅผ ๊ฑด๋“œ๋ฆฌ๋Š” ์›๋ณธ ๊ฒฐํ•จ์˜ ์ตœ์ดˆ ์ˆ˜์ • PR์ด ์ด๋ฏธ ๋จธ์ง€๋๋Š”์ง€ ํ™•์ธํ•˜๋ผ. ์•„์ง open ์ƒํƒœ๋ผ๋ฉด, ๊ฐ€๋Šฅํ•˜๋ฉด ์›๋ณธ PR์„ ๋จผ์ € ๋จธ์ง€ํ•œ ๋’ค ํŒŒ์ƒ fix ๋ธŒ๋žœ์น˜๋“ค์„ ๋”ฐ๋ผ.
  • ์ด๋ฏธ ํŒŒ์ƒ ๋ธŒ๋žœ์น˜๋“ค์„ ๋‹ค ๋งŒ๋“  ์ƒํƒœ์—์„œ ์›๋ณธ PR์ด ๋จธ์ง€๋๋‹ค๋ฉด, ๊ฐ ํŒŒ์ƒ ๋ธŒ๋žœ์น˜์— origin/development(๋˜๋Š” base) merge๋ฅผ ์„ ํ–‰ํ•˜๊ณ  ์ถฉ๋Œ(๋Œ€๊ฐœ ํšŒ๊ท€ ํ…Œ์ŠคํŠธ ํŒŒ์ผ)์„ ์ •๋ฆฌํ•œ ๋’ค PR์„ ์˜ฌ๋ ค๋ผ.
  • ๋ณ‘๋ ฌ ์ˆ˜์ • PR๋“ค์ด ์‹ค์ œ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ํŒŒ์ผ๋งŒ ๊ฑด๋“œ๋ฆฌ๋Š”์ง€ Fix-Fanout ์ „์— ํ•œ ๋ฒˆ ํ™•์ธํ•˜๋ฉด, ์ด๋Ÿฐ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์„ ๋ฏธ๋ฆฌ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

์ฒดํฌ๋ฆฌ์ŠคํŠธ#

Triage#

  • gray-list๊ฐ€ grep ๋“ฑ์œผ๋กœ ์ „์ˆ˜ ์ƒ์„ฑ๋๋Š”๊ฐ€ (์ž„์˜ ์ƒ˜ํ”Œ๋ง ์•„๋‹˜)
  • ๊ฐ ์—์ด์ „ํŠธ ํ”„๋กฌํ”„ํŠธ์— "์ด ํŒจํ„ด์ด ์•„๋‹Œ ๊ฒƒ"์ด ๋ช…์‹œ๋๋Š”๊ฐ€ (์Šค์ฝ”ํ”„ ์ถ•์†Œ)
  • ์ฒญํฌ ํฌ๊ธฐ๊ฐ€ rate limit์„ ๊ณ ๋ คํ•ด ์ ์ ˆํ•œ๊ฐ€

Verify#

  • Triage์™€ ๋ณ„๋„์˜ ์—์ด์ „ํŠธ๊ฐ€ ๊ฒ€์ฆํ•˜๋Š”๊ฐ€ (๋™์ผ ์—์ด์ „ํŠธ ์ž์ฒด ํ™•์ • ๊ธˆ์ง€)
  • dead code / self-healing / stale-only(๋ฉˆ์ถ”์ง€ ์•Š์Œ) 3๊ฐ€์ง€๋ฅผ ์žฌํ™•์ธํ–ˆ๋Š”๊ฐ€
  • Triage์˜ severity๋ฅผ ๊ทธ๋Œ€๋กœ ์‹ ๋ขฐํ•˜์ง€ ์•Š๊ณ  ์žฌํ‰๊ฐ€ํ–ˆ๋Š”๊ฐ€

Fix-Fanout#

  • ๊ฒฐํ•จ ์„ค๋ช…(ํŒŒ์ผ/ํ•จ์ˆ˜/๋ผ์ธ/ํ˜ธ์ถœ์ฒด์ธ)๊ณผ ์ˆ˜์ • ๋ฐฉํ–ฅ์ด ํ”„๋กฌํ”„ํŠธ์— ๊ตฌ์ฒด์ ์œผ๋กœ ํฌํ•จ๋๋Š”๊ฐ€
  • isolation: 'worktree'๋กœ ํ•ญ๋ชฉ๋ณ„ ๊ฒฉ๋ฆฌ๊ฐ€ ์ ์šฉ๋๋Š”๊ฐ€
  • ์›๋ณธ root-cause fix PR์ด ๋จผ์ € ๋จธ์ง€๋๋Š”์ง€(๋˜๋Š” ๋จธ์ง€ ํ›„ ํŒŒ์ƒ ๋ธŒ๋žœ์น˜์— rebase/mergeํ•  ๊ณ„ํš์ธ์ง€) ํ™•์ธํ–ˆ๋Š”๊ฐ€
  • ๊ฐ fix ์—์ด์ „ํŠธ๊ฐ€ ๋จธ์ง€๊นŒ์ง€๋Š” ํ•˜์ง€ ์•Š๊ณ  PR ์ƒ์„ฑ์—์„œ ๋ฉˆ์ถ”๋Š”๊ฐ€

์‹ค์ œ ์‚ฌ๋ก€ โ€” kobic #7746#

kobic(Flutter/Dart melos ๋ชจ๋…ธ๋ ˆํฌ) ํ”„๋กœ์ ํŠธ์—์„œ SwrStrategyImpl._revalidate์˜ ๋ฌดํ•œ ๋กœ๋”ฉ ๋ฒ„๊ทธ(#7746, ์ƒ์„ธ๋Š” [cc-flutter-dev:swr-pattern] ์ฐธ์กฐ)๋ฅผ ๊ณ ์นœ ๋’ค, ๊ฐ™์€ unawaited() + on Exception catch(Error ๋ˆ„๋ฝ) ํŒจํ„ด์ด ๋‹ค๋ฅธ ๊ณณ์—๋„ ์žˆ๋Š”์ง€ ์ด ์ ˆ์ฐจ๋กœ ๊ฐ์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

  • Triage: unawaited(์„ ํฌํ•จํ•˜๋Š” ํ”„๋กœ๋•์…˜ ํŒŒ์ผ 274๊ฐœ๋ฅผ gray-list๋กœ ๋งŒ๋“ค์–ด 30๊ฐœ์”ฉ ์ฒญํฌ ๋ถ„ํ• , ๋ณ‘๋ ฌ ์—์ด์ „ํŠธ ๋ฐฐ๋ถ„
  • Verify: ํ›„๋ณด ์ค‘ severity "high" 2๊ฑด์ด ์ฃฝ์€ ์ฝ”๋“œ(@Deprecated)๋กœ ๊ธฐ๊ฐ, 1๊ฑด์ด BehaviorSubject.seeded()๋ผ ๋ฉˆ์ถ”์ง€ ์•Š๊ณ  stale๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ธฐ๊ฐ
  • Fix-Fanout: ํ™•์ • 11๊ฑด + ๋ถ€์ˆ˜ ๋ฐœ๊ฒฌ ์ฃฝ์€ ์ฝ”๋“œ ์ •๋ฆฌ 1๊ฑด, ์ด 12๊ฑด์„ isolation: 'worktree'๋กœ ๋™์‹œ ์ˆ˜์ • (EPUB ๋ฆฌ๋” ์ „์ฒด ๋ฉˆ์ถค ๋“ฑ high severity ํฌํ•จ)
  • ๋จธ์ง€ ํ›„: 12๊ฑด ์ค‘ 1๊ฑด์—์„œ ์œ„ "๋จธ์ง€ ์ถฉ๋Œ ํ•จ์ •"์ด ์‹ค์ œ๋กœ ๋ฐœ์ƒ โ€” origin/development merge + ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ˆ˜๋™ ์ •๋ฆฌ๋กœ ํ•ด๊ฒฐ

๊ด€๋ จ ์Šคํ‚ฌ#

  • [cc-flutter-dev:swr-pattern] โ€” ์ด ์‚ฌ๋ก€์˜ ๊ทผ๋ณธ ์›์ธ์ด ๋œ Dart unawaited() + Error ์นจ๋ฌต ์‹คํŒจ ํ•จ์ • ์ƒ์„ธ
  • [cc-dev-cycle:merge-conflict-resolution] โ€” Fix-Fanout ํ›„ ๋ฐœ์ƒํ•˜๋Š” ๋จธ์ง€ ์ถฉ๋Œ์˜ ํŒŒ์ผ ์œ ํ˜•๋ณ„ ํ•ด์†Œ ์ „๋žต
  • [cc-dev-cycle:agent-teams] โ€” Agent Teams(ํŒŒ์ผ ์†Œ์œ ๊ถŒ ๋ถ„๋ฆฌ) vs git worktree(ํŒŒ์ผ์‹œ์Šคํ…œ ๊ฒฉ๋ฆฌ) ๋ณ‘๋ ฌํ™” ๋น„๊ต
  • [cc-serverpod:serverpod-worktree-parallel] โ€” worktree๋ณ„ Serverpod ํ’€์Šคํƒ ํฌํŠธ/MCP ๊ฒฉ๋ฆฌ (ํ’€์Šคํƒ ๊ฒ€์ฆ์ด ํ•„์š”ํ•œ fix์— ์ ์šฉ)