diff --git a/agent-ops/.version b/agent-ops/.version index 166971bb..1c6102d2 100644 --- a/agent-ops/.version +++ b/agent-ops/.version @@ -1 +1 @@ -1.1.186 +1.1.187 diff --git a/agent-ops/skills/common/prepare-milestone-workspace/SKILL.md b/agent-ops/skills/common/prepare-milestone-workspace/SKILL.md index 1591d600..69a5d612 100644 --- a/agent-ops/skills/common/prepare-milestone-workspace/SKILL.md +++ b/agent-ops/skills/common/prepare-milestone-workspace/SKILL.md @@ -1,6 +1,6 @@ --- name: prepare-milestone-workspace -description: 계획 상태의 Milestone을 명시 workspace의 Git Flow feature worktree로 준비하거나, 이미 준비된 현재 feature workspace에서 선택한 한 개 또는 여러 Epic을 검토된 작업으로 변환하고 전체 준비 배리어 뒤 dispatcher를 시작할 때 사용한다. "../iop-s1 위치에 X 작업 준비해", "현 마일스톤에 두 번째 에픽 작업 시작해", "X 마일스톤에 1,2번째 에픽까지 작업 시작해" 요청에서 사용한다. +description: 계획 상태의 Milestone을 명시 workspace의 Git Flow feature worktree로 준비하거나, 이미 준비된 현재 feature workspace에서 선택한 한 개·범위·남은 모든 Epic을 검토된 작업으로 변환하고 전체 준비 배리어 뒤 dispatcher를 시작할 때 사용한다. "../iop-s1 위치에 X 작업 준비해", "현 마일스톤에 두 번째 에픽 작업 시작해", "X 마일스톤에 1,2번째 에픽까지 작업 시작해", "현 마일스톤에 남은 에픽 작업들 시작해" 요청에서 사용한다. --- # Prepare Milestone Workspace @@ -20,10 +20,10 @@ description: 계획 상태의 Milestone을 명시 workspace의 Git Flow feature - `planner-model`, `review-model`: provider별 model override. Codex 기본 사용 시 `planner-model` 생략 시 `gpt-5.6-sol`, 다른 provider는 해당 CLI 기본 모델을 사용한다. (선택) - `reasoning-effort`: 지원하는 provider의 reasoning/thinking override. 생략 시 `xhigh` (선택) - `pi-provider`: Pi provider override (선택) -- `target-epics`: `first-incomplete`, 정확한 Epic id/title의 comma list, 또는 문서 순서의 1-based inclusive range `N..M`. 생략하면 `first-incomplete`를 사용한다. (선택) +- `target-epics`: `remaining`, `first-incomplete`, 정확한 Epic id/title의 comma list, 또는 문서 순서의 1-based inclusive range `N..M`. 생략하면 `first-incomplete`를 사용한다. (선택) - `retry`: 기록된 attention/recovery 조건을 사용자가 해소한 뒤 batch를 재개할 때만 사용한다. (선택) -생성 모드의 첫 번째 위치 표현(``)은 workspace로, 두 번째 표현(``)은 대상 Milestone으로 각각 확정한다. 상대 workspace는 develop repository root 기준으로 해석한다. 현재 workspace 실행 모드의 `현 마일스톤`은 `current.md`와 현재 feature branch가 함께 가리키는 Milestone으로, 이름을 지정하면 같은 workspace의 branch/current와 정확히 일치해야 한다. `두 번째 Epic`은 `2..2`, `두 번째 Epic까지`와 `1,2번째 Epic까지`는 `1..2`, `세 번째부터 네 번째 Epic까지`는 `3..4`로 변환한다. +생성 모드의 첫 번째 위치 표현(``)은 workspace로, 두 번째 표현(``)은 대상 Milestone으로 각각 확정한다. 상대 workspace는 develop repository root 기준으로 해석한다. 현재 workspace 실행 모드의 `현 마일스톤`은 `current.md`와 현재 feature branch가 함께 가리키는 Milestone으로, 이름을 지정하면 같은 workspace의 branch/current와 정확히 일치해야 한다. `두 번째 Epic`은 `2..2`, `두 번째 Epic까지`와 `1,2번째 Epic까지`는 `1..2`, `세 번째부터 네 번째 Epic까지`는 `3..4`, `남은 Epic`은 문서 순서의 미완료 Epic 전체를 선택하는 `remaining`으로 변환한다. ## 사전 조건 @@ -70,6 +70,7 @@ python3 agent-ops/skills/common/prepare-milestone-workspace/scripts/prepare_work ``` - 현재 workspace가 target feature branch/current와 다르면 다른 worktree를 탐색하거나 branch를 바꾸지 않고 `FAILED`로 멈춘다. + - `remaining`에 미완료 Epic이 없으면 agent/dispatcher를 시작하지 않고 완료 event로 종료한다. - 두 모드 모두 실행 중 caller LLM이 timer polling, `ps`, state 파일 검사 또는 중복 실행을 하지 않는다. 3. **선택 Epic batch를 준비한다** diff --git a/agent-ops/skills/common/prepare-milestone-workspace/scripts/prepare_workspace.py b/agent-ops/skills/common/prepare-milestone-workspace/scripts/prepare_workspace.py index 04db87e6..5223e8f0 100755 --- a/agent-ops/skills/common/prepare-milestone-workspace/scripts/prepare_workspace.py +++ b/agent-ops/skills/common/prepare-milestone-workspace/scripts/prepare_workspace.py @@ -183,6 +183,8 @@ def parse_epics(text: str) -> list[Epic]: def select_epics(epics: list[Epic], selector: str) -> list[Epic]: if not epics: raise PreparationError("target Milestone has no Epic") + if selector == "remaining": + return [epic for epic in epics if epic.incomplete_ids] if selector == "first-incomplete": selected = next((epic for epic in epics if epic.incomplete_ids), None) if selected is None: @@ -1033,7 +1035,7 @@ def parser() -> argparse.ArgumentParser: value.add_argument("--pi-provider") value.add_argument( "--epics", - help="prepare and dispatch one/list/range selector; use first-incomplete or 1..N", + help="prepare and dispatch remaining/first-incomplete/one/list/range selector", ) value.add_argument( "--retry", @@ -1105,7 +1107,7 @@ def prepare_existing(args: argparse.Namespace) -> int: reviewer_model = args.review_model or ( args.planner_model if reviewer_agent == args.planner_agent else None ) - for agent in {args.planner_agent, reviewer_agent}: + for agent in {args.planner_agent, reviewer_agent} if selected else set(): command = AGENT_COMMAND[agent] if shutil.which(command) is None and not args.skip_agent_probe: raise PreparationError(f"agent command not found: agent={agent} command={command}") @@ -1166,7 +1168,7 @@ def prepare_existing(args: argparse.Namespace) -> int: ) if args.dry_run: return 0 - if not args.skip_agent_probe and not resuming_batch: + if selected and not args.skip_agent_probe and not resuming_batch: probe_agents( workspace, args.planner_agent, diff --git a/agent-ops/skills/common/prepare-milestone-workspace/tests/test_prepare_workspace.py b/agent-ops/skills/common/prepare-milestone-workspace/tests/test_prepare_workspace.py index bb69d0fe..0e82cc8f 100644 --- a/agent-ops/skills/common/prepare-milestone-workspace/tests/test_prepare_workspace.py +++ b/agent-ops/skills/common/prepare-milestone-workspace/tests/test_prepare_workspace.py @@ -64,6 +64,36 @@ class PrepareWorkspaceTest(unittest.TestCase): ["first", "second"], ) + def test_remaining_epics_selects_only_incomplete_epics_in_document_order(self) -> None: + epics = MODULE.parse_epics( + """## 기능 + +### Epic: [first] First + +- [x] [first-task] first + +### Epic: [second] Second + +- [X] [second-task] second + +### Epic: [third] Third + +- [ ] [third-task] third + +### Epic: [fourth] Fourth + +- [ ] [fourth-task] fourth +""" + ) + self.assertEqual( + [epic.epic_id for epic in MODULE.select_epics(epics, "remaining")], + ["third", "fourth"], + ) + self.assertEqual( + MODULE.select_epics(epics[:2], "remaining"), + [], + ) + def test_workspace_defaults_to_codex_top_model_and_reasoning(self) -> None: args = MODULE.parser().parse_args( ["--repo", "/repo", "--milestone", "milestone.md", "--workspace", "/workspace"] diff --git a/agent-ops/skills/common/router.md b/agent-ops/skills/common/router.md index c26130e0..923ef537 100644 --- a/agent-ops/skills/common/router.md +++ b/agent-ops/skills/common/router.md @@ -47,7 +47,7 @@ | 이 마일스톤은 X가 끝나야 가능해, A 전까지 B 잠가둬, 잠금 해제 조건은 X야, X 프로젝트 작업 뒤에 현재 마일스톤 진행, 의존성 설정해, 외부 의존 잠금 | `agent-ops/skills/common/update-roadmap/SKILL.md` | | roadmap dependency 확인, locks.yaml 판별, 외부 의존 잠금 확인, unlock-ready 판별, 잠금 해제 조건 충족 여부 확인, roadmap-dependency-checker.sh | `agent-ops/skills/common/check-roadmap-dependency/SKILL.md` | | 지금 작업이 뭐지?, 현재 작업 분석, 어디까지 했지?, 로드맵상 현 위치, 현재 마일스톤 위치, current 기준 breadcrumb | `agent-ops/skills/common/analyze-roadmap-position/SKILL.md` | -| X에 Y 작업 준비해, X 위치에 Y 작업 준비해, 현 마일스톤에 N번째 에픽 작업 시작해, 현 마일스톤에 N번째 에픽까지 작업 시작해, Y 마일스톤에 1,2번째 에픽까지 작업 시작해 | `agent-ops/skills/common/prepare-milestone-workspace/SKILL.md` | +| X에 Y 작업 준비해, X 위치에 Y 작업 준비해, 현 마일스톤에 N번째 에픽 작업 시작해, 현 마일스톤에 N번째 에픽까지 작업 시작해, Y 마일스톤에 1,2번째 에픽까지 작업 시작해, 현 마일스톤에 남은 에픽 작업들 시작해, Y 마일스톤에 남은 에픽 작업 시작해 | `agent-ops/skills/common/prepare-milestone-workspace/SKILL.md` | | 현 마일스톤 Epic 작업 준비해, 마일스톤 Epic 작업 준비해, 이 Epic의 작은 작업은 바로 처리하고 큰 작업은 plan으로 작성해, Epic 작업을 작은 작업과 plan으로 나눠 | `agent-ops/skills/common/prepare-epic-work-items/SKILL.md` | | 계획 세워줘, 계획 작성해, 계획 만들어줘, 구현 계획, PLAN.md, plan, plan 작성해, plan 만들어줘 | `agent-ops/skills/common/plan/SKILL.md` | | 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, task 세분화해, plan 분리해 | `agent-ops/skills/common/refine-plans/SKILL.md` | @@ -62,7 +62,7 @@ 라우팅 우선순위: - `X에 Y 작업 준비해`처럼 workspace 위치와 대상 Milestone이 함께 명시되면 `prepare-milestone-workspace` 생성 모드를 선택한다. 상대 workspace는 develop repository root 기준으로 해석한다. 이 형식에서 workspace 위치가 없으면 확인을 요청한다. -- `현 마일스톤에 N번째 에픽 작업 시작해` 또는 `Y 마일스톤에 1,2번째 에픽까지 작업 시작해`는 같은 스킬의 현재 workspace 실행 모드를 선택한다. `현 마일스톤`은 current/feature branch의 단일 일치 target, 이름 있는 Milestone은 현재 workspace branch/current와 정확히 일치하는 target만 허용한다. `N번째`는 `N..N`, `N번째까지`는 `1..N`, `1,2번째까지`는 `1..2`로 해석한다. 현재 workspace가 준비되지 않았거나 target과 다르면 workspace를 추정·전환하지 않고 거부한다. +- `현 마일스톤에 N번째 에픽 작업 시작해`, `Y 마일스톤에 1,2번째 에픽까지 작업 시작해` 또는 `현|Y 마일스톤에 남은 에픽 작업들 시작해`는 같은 스킬의 현재 workspace 실행 모드를 선택한다. `현 마일스톤`은 current/feature branch의 단일 일치 target, 이름 있는 Milestone은 현재 workspace branch/current와 정확히 일치하는 target만 허용한다. `N번째`는 `N..N`, `N번째까지`는 `1..N`, `1,2번째까지`는 `1..2`, `남은 에픽`은 문서 순서의 미완료 Epic 전체를 뜻하는 `remaining`으로 해석한다. 현재 workspace가 준비되지 않았거나 target과 다르면 workspace를 추정·전환하지 않고 거부한다. - 두 모드 모두 선택 Epic을 각각 `prepare-epic-work-items`로 준비하되 전체 `MILESTONE_WORK_ITEMS_READY` 전에는 dispatcher를 시작하지 않는다. - 한 Epic 안에서 작은 작업 직접 처리와 큰 작업 plan 작성을 함께 요청하면 `prepare-epic-work-items`를 선택한다. 이미 존재하는 plan만 세분화하는 요청과 새로운 plan만 작성하는 요청에는 이 스킬을 선택하지 않는다. - 이미 생성된 미착수 pair의 분할만 요청하면 lane과 관계없이 `refine-plans`를 선택한다. 새 plan 작성이나 구현 범위 재분석이 포함되면 `plan`을 선택한다.