sequential-workflow
Supporting reference module for /cc-dev:batch — per-issue cycle detail, Stall Budget ladder, and error recovery. Not a standalone command entry point.
| 항목 | 내용 |
|---|---|
| 별칭 | @sequential-workflow |
| 모델 | inherit |
| 사용 도구 |
Read
,
Edit
,
Write
,
Bash
,
Glob
,
Grep
,
Task
|
| MCP 서버 | zenhub |
| 지원 | /cc-dev:batch |
⚠️ This is a supporting reference module, not the command definition. The canonical
/cc-dev:batchentry point (Epic branch → Story branch → Sub-task branch, perbranch-hierarchy) is commands/batch.md. That file references this one specifically for the Stall Budget ladder and Error Recovery sections below — it is not a competing implementation.@sequential-workflowmay still be invoked directly for a single-Story sequential cycle outside of a full Epic batch.
Sequential Workflow Agent#
A supporting workflow module detailing the per-issue processing cycle, stall-budget ladder, and error recovery used by
/cc-dev:batch.
Triggers#
@sequential-workflow(direct invocation for a single-Story sequential cycle)-
Referenced internally by
/cc-dev:batch(commands/batch.md) for Stall Budget / Error Recovery detail
Workflow Cycle#
Phase 1: Issue Selection#
1. Query Story children under the Epic (each Story's own Sub-tasks are
discovered and processed within that Story's own cycle — see
branch-hierarchy: Sub-task's parent is Story, not Epic)
2. Filter issues in the New Issues pipeline
3. Sort by priority and issue number
4. Select the first issue
Phase 2: Start Work#
0. ⛔ Claim guard — claimStatus(issue) 가 "other-live" 면 이 Story 는 다른 세션이 잡고 있다.
착수하지 않고 SKIPPED-OCCUPIED 로 기록한 뒤 다음 Story 로 넘어간다(보드·대장을 건드리지 않는다).
판정 SoT: ../rules/zenhub-conventions.md → Work Claim Contract
1. Move the issue to the "In Progress" pipeline + acquireClaim(issue)
→ 이동만 하고 대장을 쓰지 않으면 다음 세션이 이 In Progress 를 부모 cascade 와 구분하지 못한다
→ cascade the same move up through any parent still in a pre-progress pipeline
(New Issues/Icebox/Product Backlog/Sprint Backlog) — see
agents/dev/issue-state-agent.md → cascadeStartToParents. Matters here specifically
because this module may be invoked directly for a single Story outside a full batch,
so the parent Epic may not have been touched yet.
2. Create branch: feature/{issue}-{slug}
3. Analyze issue requirements (title, body, acceptance criteria)
Phase 3: Implementation#
1. Analyze existing codebase
2. Implement code matching the requirements
3. Write tests (as needed)
4. Verify build and analysis pass
Phase 4: PR Creation#
1. Commit changes (include Closes #{issue})
2. Push branch
3. Create PR as a draft (gh pr create --draft — 초안에서는 가벼운 CI 층만 돈다)
4. Move issue to "Review/QA" pipeline (reflectBoardState(issue, "review") — 점유는 유지)
5. 로컬 점검 통과 확인 → gh pr ready → ready 뒤 새 CI run 을 기다려 판정(초안의 초록 ≠ 통과,
상세는 `../commands/run.md` Step 10.5 · `../skills/ci-receipts/SKILL.md`)
Phase 5: Code Review Response#
1. Check review feedback
2. ⭐ 변경 요청(CHANGES_REQUESTED) 또는 CI 실패 시: 이슈를 Review/QA → "In Progress" 로 되돌린다
(재작업 중임을 보드에 반영). fail-closed find() 로 pipelineId 해석.
3. Add fix commits → re-push → 다시 "Review/QA" 로 이동
(CI 실패는 로컬에서 재현 · 수정 · 검증한 뒤 push — CI 시험 루프 금지. 재현되지 않는 플레이크 · 러너
문제는 `gh run rerun <run-id> --failed` 로 실패 잡만 다시. 리뷰 반영은 모아서 한 번 push)
4. Wait for approval
Phase 6: Completion and Next Issue#
1. Squash merge PR
1.5. ⛔ 열린 자식 확인 — 이 이슈에 열린 자식이 있으면 **닫지 않는다**(이미 `Closes #N` 으로 닫혔다면
`gh issue reopen` 으로 복구). 판정은 `openChildrenStatus()` tri-state — `rules/zenhub-conventions.md`
→ "Parent Closure Invariant". Story/Sub-task leaf 에서는 사실상 no-op 이다.
2. ⭐ 명시적 Close + 검증 (필수 — auto-close 의존 금지):
PR base 가 `development`(저장소 기본 브랜치가 아닐 수 있음)면 `Closes #N` 이 발화하지 않는다.
- STATE=$(gh issue view {N} --json state -q .state); [ "$STATE" != CLOSED ] && gh issue close {N} --reason completed
- mcp__zenhub__searchClosedIssues({query:"#{N}"}) 에 없으면 → updateIssue({issueId, state:"CLOSED"})
3. Return to development + git pull --ff-only origin development + submodule sync/update
4. Go back to Phase 1 — **단, 종료 조건에 걸리지 않을 때만**(아래 루프 계약):
- Phase 1 재조회가 이번 run 의 `attempted` 집합에 **없는** 이슈를 0개 내놓으면 정지한다
(`attempted` = 이번 run 에서 착수한 이슈 번호 집합. 성공·BLOCKED 모두 넣는다 —
BLOCKED 를 빼면 같은 이슈를 영원히 다시 고른다)
- 조회 실패는 빈 집합이 아니다 — `unknown` 은 "다 끝났다" 가 아니라 **정지 + 기록**이다
- 연속 K = 3 pass 동안 어떤 이슈도 closed 또는 BLOCKED 로 전이되지 않으면 정지한다
(no-progress stop — 이슈가 계속 나오는데 아무것도 끝나지 않는 상태)
⚠️ Phase 6 는 GitHub
Closes #N자동 닫힘에 의존하지 않는다. 비-default base 머지는 자동으로 닫히지 않아 이슈가 Review/QA 에 영구 잔류하므로, GitHub state 를 source of truth 로 직접 닫고 ZenHub 동기화를 검증한다(/cc-dev:runStep 8 과 동일 패턴).
이슈 순회 루프 계약 contract:L-sequential-workflow.phase6-next-issue#
Phase 6 → Phase 1 로 되돌아가는 바깥 루프는 지금까지 정지 술어가 없었다. 필드 정의는
../rules/orchestration-graph.md §2, 값은 여기:
inv: 매 pass 진입·종료 시 attempted 는 단조 증가하고 이번 run 에서 착수한 모든 이슈를 담는다
(attempted 에 넣지 않고 같은 이슈를 다시 고르는 경로 금지)
prog: remaining = |Phase 1 후보 − attempted|, pass 하나마다 강한 감소
no-prog: remaining 이 줄지 않은 pass 는 noProgressStreak++ (예산에서 차감)
term: remaining == 0 (= attempted 에 없는 이슈가 없다) || noProgressStreak == 3
budget: pass 당 이슈 1개 · noProgressStreak K = 3 연속 pass · 이슈당 사다리 예산 4 attempts
(run 당 이슈 수 상한은 데이터 주도 — 예산은 K 와 이슈별 사다리 카운터가 진다)
exhaust: 정지 + 남은 후보·BLOCKED 목록을 컨테이너 이슈 코멘트에 내구 기록. 조용한 종료 금지
resume: ZenHub 파이프라인 재조회 + 각 이슈의 `<!-- cc-dev:stall-ladder -->` 코멘트.
attempted 는 run 범위(대화 구조라 `/clear` 를 못 넘는다) — 그래서 재개를 가로지르는
예산은 K 가 아니라 이슈별 **내구** 사다리 카운터가 진다
log: 선택마다 한 줄 — `▶ #1415 selected (attempted 3, remaining 5→4, streak 0)`
+ 정지 시 이유 한 줄(`remaining==0` | `noProgressStreak==3` | `query=unknown`)
ZenHub MCP Usage#
Workspace Info Query (once at session start)#
const workspace = await mcp__zenhub__getWorkspacePipelinesAndRepositories();
const pipelines = workspace.pipelines;
const repos = workspace.githubRepositories; // ⚠️ 필드명은 githubRepositories (repositories 아님)
// fail-closed 해석 — 못 찾으면 throw (rename/오타 시 undefined.id 무음 누락 방지)
const pid = (n) => { const p = pipelines.find(p => p.name === n); if (!p) throw new Error(`'${n}' 없음. 라이브: ${pipelines.map(p => p.name).join(", ")}`); return p; };
const newIssues = pid("New Issues");
const inProgress = pid("In Progress");
const reviewQA = pid("Review/QA");
Issue Search#
mcp__zenhub__searchLatestIssues({ query: "SALES-001" })
// Query issues by pipeline
mcp__zenhub__getIssuesInPipeline({
pipelineId: newIssues.id,
repositoryIds: [repos[0].id]
})
Pipeline Move#
// In Progress
mcp__zenhub__moveIssueToPipeline({
issueId: "{graphql_id}",
pipelineId: inProgress.id
})
// Review/QA
mcp__zenhub__moveIssueToPipeline({
issueId: "{graphql_id}",
pipelineId: reviewQA.id
})
Note: Pipeline ID and Repository ID differ per workspace. Do not hardcode them.
Branch Strategy#
# Create issue work branch
git checkout development
git pull origin development
git checkout -b feature/{issue_number}-{short-slug}
# Example
git checkout -b feature/1415-sales-kpi-summary
순차 의존 사슬이면 스택 모드를 고려한다 (선택형)#
이 모듈이 도는 사이클 — 한 번에 이슈 하나, 앞 이슈의 결과 위에 다음 이슈가 쌓이는 형태 — 가 순차 의존 사슬이라면, 그게 GitHub 네이티브 Stacked PR 이 정확히 맞는 자리다(스택은 트리가 아니라 선형 사슬이라 서로 독립인 형제는 못 담는다 — 독립 형제는 지금처럼 Orca 병렬 워크트리로 둔다). 기본값은 위의 기존 방식이고, 스택은 켜야 켜지는 선택형 실행 모드다. 채택 판단·CI 비용 맞교환은 stacked-prs 를 따른다.
접점만 짚으면:
-
가장 큰 실익: 앞 이슈가 머지되어 base 가 움직일 때마다 뒷 이슈를 손으로 rebase 하던 루프가
사라진다.
gh stack sync의 cascade rebase 와 머지 후 자동 retarget 이 대신한다. -
머지: 스택에서는 auto-merge 가 미지원이다. Phase 6 의 머지를
gh pr merge대신gh stack merge로 한다. 중간 PR 단독 머지는 불가능하고, 항상 아래 것들이 함께 머지된다. -
이슈 종료: 스택이라고 자동 종료를 가정하지 마라. 스택 머지 시
Closes #N이 어떻게 동작하는지는 문서에 명시가 없다. Phase 6 의 명시적gh issue close+ ZenHub 검증 절차를 그대로 유지한다.
Commit Rules#
# Korean commit message + Gitmoji
feat(console): ✨ 매출 KPI 요약 카드 구현 (#1415)
- 총 결제액 표시
- 총 판매량 표시
- 전월 대비 증감률 표시
Closes #1415
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
PR Creation Rules#
gh pr create --draft \
--base development \
--title "feat(console): ✨ 매출 KPI 요약 카드 구현 (#1415)" \
--body "$(cat <<'EOF'
## Summary
- Implement sales KPI summary card component
- Display total payment amount and sales volume
- Calculate month-over-month growth rate
## Related Issue
Closes #1415
## Test Plan
- [ ] Verify KPI card rendering
- [ ] Verify data binding
- [ ] Validate growth rate calculation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
EOF
)"
Stop Conditions#
The workflow automatically stops when:
- Build failure:
melos run analyzeorflutter buildfailure - Test failure: Unit test or widget test failure
- Code review issue: Major fix request raised
- User request: Explicit stop request
Per-story scope, not Epic scope. A single Story getting stuck must NOT halt the whole Epic. When a Story exhausts the stall ladder below, it is marked
BLOCKED('unstuck_exhausted')and the batch continues to the next Story (idempotent resume re-enters it later — see batch.md Phase 0 — but the ladder budget carries over in the durable counter below: an exhausted ladder is not reset to Rung 1 by a resume).
Stall Budget — 3-Rung Ladder#
On repeated failure within one Story, climb the ladder rung by rung. Do not loop rung 1 forever.
이 사다리가 구현측 루프의 기본
exhaust:다 (repo-wide default).../rules/orchestration-graph.md§2 가 이 문서를 기본 사다리로 지정한다 — 개별 루프는 자기 사다리를 발명하지 말고 호출 지점에contract:L-sequential-workflow.stall-ladder를 인용하고 아래 값을 상속한다(값을 자기 문서로 복사하면 두 번째 규범 사본이 생긴다). 필드 이름(inv:/prog:/term:/budget:/exhaust:/resume:/log:)의 정의도 그 문서 §2 에 있다.
Rung 1 — Same-strategy retry (existing): budget = 2 attempts
Re-run the same fix **at most 2 times** (e.g. lint/format/build
auto-fix as in Error Recovery below). An unquantified "small, bounded"
count is not a budget — in practice it never terminates.
Each retry MUST change at least one input: command/flags, the changed
file set, or the environment. A re-run with an identical input set is
not an attempt but a repeat — it consumes no budget and goes straight
to Rung 2 (`no-prog:` 위반).
Rung 2 — Lateral reframe (on repeated IDENTICAL failure):
budget = 2 reframes, ≤ 1 persona switch
When the SAME failure repeats (judged SEMANTICALLY, not by string
diff — see note), escalate to /cc-dev:unstuck solo with an affinity
persona from the symptom table below. A reframe ≠ a retry: the next
move must differ in KIND from what already failed.
**At most 2 reframed attempts**, and **at most ONE persona switch**
within them (persona #1 comes from the symptom table; the one switch
is spent only when reframe #1's named change did not move the failure).
Each reframed attempt must NAME which of {tool, layer, data,
assumption} it changed — that name IS this rung's progress measure.
An attempt that can name none of the four is not a reframe: it
consumes no budget and escalates to Rung 3.
Rung 3 — BLOCKED + CONTINUE (보드 반영 포함):
횡적 reframe 도 소진되고 Story 가 여전히 안 풀리면 blockIssue(issue, 'unstuck_exhausted')
후 배치를 CONTINUE 한다(Epic 전체 중단 금지). 그 한 번의 호출이 아래 셋을 묶어 수행한다:
- 차단 의존이 있으면 createBlockage({blockedIssueId, blockingIssueId}) 로 기록
(차단자가 이슈일 때만 — CI 실패·예산 소진에는 가짜 이슈를 만들지 않는다)
- 활성 작업과 구분되도록 holding 컬럼(Sprint Backlog)으로 이동 — In Progress 에 방치 금지
- **점유 해제** — 빠뜨리면 이 Story 는 TTL(4h)까지 다른 세션에게 "누가 하고 있다"로 읽힌다
- 정의·blocked→unblocked 계약은 rules/zenhub-conventions.md → Pipeline State Contract 참조
- 소진된 사다리 상태를 아래 카운터 코멘트에 state:blocked(unstuck_exhausted) 로 확정한다
(BLOCKED Story 는 Phase 0 멱등 resume 으로 다시 집히지만, **사다리는 rung 1 로 리셋되지
않는다** — 남은 예산이 있을 때만 재시도한다. 아래 "Ladder Counter Persistence" 참조.)
Rung 2 — Affinity Symptom Table#
Pick the starting persona by the meaning of the stuck state (default CONTRARIAN). Persona definitions live in
plugins/cc-dev/references/LATERAL_PERSONAS.md — do not restate them here.
| Symptom (semantic) | /cc-dev:unstuck call |
|---|---|
| Same error repeated N× | /cc-dev:unstuck solo hacker |
| Flip-flop / oscillation between fixes | /cc-dev:unstuck solo architect |
| Missing fact / unverified info blocks progress | /cc-dev:unstuck solo researcher |
| Over-built / complexity-buried blocker | /cc-dev:unstuck solo simplifier |
| Unknown / premise itself suspect (default) | /cc-dev:unstuck solo contrarian |
LLM-SEMANTIC, never lexical. "Is this the SAME failure again?" and "which symptom is this?" are judged by meaning, not whitespace/token overlap of error text. The audience is Korean-first: Korean has no word boundaries and attaches 조사, so two log lines describing one blocker can share almost no tokens ("빌드가 실패" vs "빌드는 또 실패"). Match by what is actually stuck, not by characters.
반사 판정 먼저 (
cc-dev:jev-reflex, 약 0.2초 — 두 판단 모두 의미 판단의 첫 단계다):> JR="${CLAUDE_PLUGIN_ROOT}/skills/jev-reflex/scripts/jev_reflex.py" > PREV="$(mktemp)"; TAIL="$(mktemp)" # last_cause 와 이번 실패 꼬리 — 파일로 넘겨 따옴표가 셸로 새지 않게, 병렬 워커끼리 겹치지 않게 > python3 "$JR" ask --set same-failure --field-file previous="$PREV" --field-file current="$TAIL" > python3 "$JR" ask --set lateral-persona --state @stuck.json # {problem_context, current_approach, failed_attempts} >
same_blockerreflex true → 같은 실패: Rung 2 로 오른다 · reflex false → 다른 실패: 새 원인으로 Rung 1 을 이어 간다 (cc-dev:stall-ladder코멘트의last_cause를 새 원인으로 바꾼다) · deliberate → 위 원칙대로 Claude 가 의미로 판단한다.personareflex → 그 페르소나로/cc-dev:unstuck solo <persona>· deliberate → 기본값 CONTRARIAN, 단 Claude 가 표에서 더 맞는 증상을 보면 그것.- unavailable(0·4 가 아닌 모든 종료 코드) → 반사 판정 없이 위 원칙대로. 사다리 예산은 판정 방식과 무관하게 같다 — 반사 판정은 예산을 늘리거나 줄이지 않고, 오르는 판단만 빠르게 한다.
/cc-dev:unstuckreturns options, not a verdict — it does not decide for the workflow. If a reframed next move is actionable, the workflow may try it (that counts as Rung 2, bounded at 2 reframes / ≤1 persona switch as above); if none unblocks the Story, proceed to Rung 3.
Ladder Counter Persistence — 재개를 가로지르는 예산#
대화 카운터는 /clear 를 넘지 못하고, batch.md Phase 0 의 멱등 resume 은 BLOCKED child 를 나중에
다시 집는다. 카운터를 어디에도 적지 않으면 그 재진입이 사다리를 rung 1 부터 다시 돌려서 — 매 pass 는
bounded 인데 resume 을 가로지르면 무제한 루프가 된다. 그래서 카운터와 의미 요약을 이슈에 적는다.
- 위치: 막힌 그 이슈 자신의 마커 코멘트 `<!-- cc-dev:stall-ladder -->`
(upsert 프로토콜은 `../skills/branch-hierarchy/SKILL.md` R3 의 마커 코멘트 읽기·쓰기 절차를 재사용 — 복제 금지)
- 항목: | rung | attempts_used | persona | persona_switched(0|1) | changed({tool|layer|data|assumption})
| last_cause(LLM-SEMANTIC 요약) | state: climbing / blocked(unstuck_exhausted) |
- 갱신 시점: **rung 전이마다 즉시**(다음 attempt 를 시작하기 전에) upsert 한다. 몰아서 쓰면
크래시 한 번에 카운터가 사라지고 예산이 리셋된다.
- 재개: 이 이슈를 다시 집으면 코멘트를 **먼저 읽고** 남은 예산부터 이어 쓴다. 코멘트가 없으면
rung 1 / attempts_used 0 이 초기값이고, **조회 실패는 "없음"이 아니라 unknown** 이므로 사다리를
새로 시작하지 않고 blocked 로 둔다(`../rules/orchestration-graph.md` §3.2 empty-set pass).
- batch 하위에서 돌 때: `../commands/batch.md` → "Stall Ladder" 의 시도 대장(attempt ledger)은
**컨테이너 쪽 바깥 예산**(child 1개당 누적 처리 pass 수)이고, 이 코멘트는 **그 pass 안쪽의
rung/attempt** 다. 단위가 다르므로 서로 덮어쓰지 않고 곱해진다(outer × inner). 둘 중 하나라도
소진되면 재시도는 없다.
루프 계약 contract:L-sequential-workflow.stall-ladder (필드 정의는
../rules/orchestration-graph.md §2, 값은 여기):
inv: 매 attempt 진입·종료 시 (rung, attempts_used) 가 마커 코멘트의 값과 일치한다
Rung 1 attempt 는 직전 attempt 와 입력 집합이 다르다
prog: attemptsLeft = (2 - rung1Used) + (2 - rung2Used), 매 attempt 강한 감소
no-prog: 입력이 같은 재실행(Rung 1) 또는 {tool,layer,data,assumption} 중 무엇도
이름 대지 못한 리프레임(Rung 2) 은 예산을 쓰지 않고 곧바로 다음 rung 으로 올린다
term: 막힌 게이트가 통과 || attemptsLeft == 0 → Rung 3
budget: Rung 1 = 2 attempts · Rung 2 = 2 reframes(persona 교체 ≤ 1) · Rung 3 = 종단 1회
= 이슈당 최대 4 attempts, **batch 재실행을 가로질러 합산**한다(대화 카운터 아님)
exhaust: Rung 3 = blockIssue(issue, 'unstuck_exhausted') (보드 + 점유 해제) + 형제 CONTINUE.
디스패치된 워커 안에서 `AskUserQuestion` 을 exhaust 로 쓰지 않는다(물어볼 사람이 없다)
resume: 막힌 이슈의 `<!-- cc-dev:stall-ladder -->` 코멘트를 읽어 위치를 판정한다.
코멘트 upsert 는 멱등이고, 사다리는 resume 마다 rung 1 로 되돌아가지 않는다
log: rung 전이마다 한 줄(rung · attempt index · 고른 persona) —
`🪜 rung 2 attempt 1/2 persona=hacker changed=assumption cause={의미 요약}`
Rung 3 도달 시 잔여 상태와 **탈락시킨 이슈**를 같은 코멘트에 내구 기록
Error Recovery#
On Build Failure (Rung 1)#
# Analyze error
melos run analyze 2>&1 | head -50
# Common fixes
melos run format
melos run build
Tooling degradation (GD-01):
melos부재 시dart analyze/dart format/flutter test를 직접 호출하는 것으로 폴백한다(= /cc-dev:run "Step 0 Degradation Contract"). 빌드 도구 미설치는 안전 위반이 아니라 degrade + 경고 대상 —command -v melos로 먼저 확인하고 분기하라.
On Repeated Identical Failure (Rung 2)#
# Same failure (semantically) after Rung 1 retries → lateral reframe
/cc-dev:unstuck solo <affinity-persona> # see Affinity Symptom Table
On Stall Exhausted (Rung 3)#
# Reframe didn't unblock → mark BLOCKED and move on
mark Story BLOCKED('unstuck_exhausted'); CONTINUE to next Story # Epic NOT halted
On Merge Conflict#
git fetch origin development
git rebase origin/development
# After resolving conflicts
git rebase --continue
On Stack Command Failure (스택 모드에서만)#
스택 모드(stacked-prs)로 돌 때는 위 수동 rebase 대신
gh stack sync / gh stack rebase 가 cascade 로 처리한다. 실패는 exit code 로 구분해 대응한다 —
셋 다 "같은 명령 재실행" 으로는 풀리지 않는다.
| exit | 의미 | 조치 |
|---|---|---|
3 |
rebase 충돌 |
충돌 파일을 해결하고
gh stack rebase --continue
. 되돌릴 거면
gh stack rebase --abort
. 해결 자체는
merge-conflict-resolution
규약을 그대로 따른다.
Rung 1 재시도로 세지 않는다
— 사람이 만든 해결이 새 입력이므로
--continue
는 재실행이 아니라 진행이다
|
7 |
이미 rebase 진행 중 |
새 rebase 를
시작하지 마라.
진행 중인 것을
--continue
로 끝내거나
--abort
로 되돌린 뒤에만 다음 명령을 낸다. 진행 상태는
.git/gh-stack-rebase-state
에 남는다
|
8 |
다른 프로세스가 스택 잠금 |
병렬 워크트리·세션이 같은 스택을 동시에 만지고 있다는 신호다. 재시도 루프 금지 — 이건 실패가 아니라
직렬화 문제
다. 잠금이 풀릴 때까지 기다렸다
1회만
재실행하고, 그래도
8
이면 Rung 2 로 올린다(누가 잡고 있는지부터 규명). 이 대기는 입력이 바뀌지 않으므로 Rung 1 예산을 쓰지 않는다
|
⚠️ 로컬 스택과 원격 스택이 갈라지면(diverged) 대화형에서는 3택을 묻지만, 비대화형에서는 아무것도 바꾸지 않고 중단한다. 무인 실행에서 이 중단을 "실패 재시도" 로 처리하지 말고 BLOCKED 로 올려라.
Checklist#
Verification items for each issue:
- Understand issue requirements
- Create branch
- Implement code
- Pass build/analysis
- Create commit (include Closes #)
- Create PR
- Move pipeline (In Progress → Review/QA)
- Address review feedback
- 실패가 있었다면 사다리 카운터를 이슈 코멘트에 기록(resume 이 rung 1 로 리셋되지 않음)
-
Switch to next issue —
attempted에 넣고 종료 조건(remaining / K=3) 재평가
Related Agents#
@console-feature- Console feature patterns@bloc- BLoC state management@flutter-ui- UI component implementation@test- Test writing