diff --git a/agent-ops/skills/common/finalize-task-routing/tests/test_finalize_task_routing.py b/agent-ops/skills/common/finalize-task-routing/tests/test_finalize_task_routing.py index d9a06e1..b4109c2 100755 --- a/agent-ops/skills/common/finalize-task-routing/tests/test_finalize_task_routing.py +++ b/agent-ops/skills/common/finalize-task-routing/tests/test_finalize_task_routing.py @@ -102,7 +102,7 @@ class FinalizeTaskRoutingTests(unittest.TestCase): COMMON_SKILLS_DIR / "complete-milestone", COMMON_SKILLS_DIR / "plan", COMMON_SKILLS_DIR / "code-review", - COMMON_SKILLS_DIR / "refine-local-plans", + COMMON_SKILLS_DIR / "refine-plans", COMMON_SKILLS_DIR / "finalize-task-routing", ) contract_files: list[Path] = [] @@ -129,6 +129,45 @@ class FinalizeTaskRoutingTests(unittest.TestCase): with self.subTest(path=path, needle=needle): self.assertNotIn(needle, text) + def test_plan_refinement_contract_is_lane_neutral(self) -> None: + refine_skill = (COMMON_SKILLS_DIR / "refine-plans" / "SKILL.md").read_text( + encoding="utf-8" + ) + router = (COMMON_SKILLS_DIR / "router.md").read_text(encoding="utf-8") + plan_skill = PLAN_SKILL.read_text(encoding="utf-8") + sync_ui_skill = (COMMON_SKILLS_DIR / "sync-agent-ui" / "SKILL.md").read_text( + encoding="utf-8" + ) + + self.assertFalse( + (COMMON_SKILLS_DIR / "refine-local-plans" / "SKILL.md").exists() + ) + self.assertIn("`PLAN-*-G??.md`", refine_skill) + self.assertIn("Build lane은 대상 자격에 사용하지 않는다.", refine_skill) + self.assertIn("`evaluation_mode=isolated-reassessment`", refine_skill) + self.assertIn("parent 값을 복사하지 않는다", refine_skill) + self.assertIn("미착수 pair의 분할", router) + self.assertIn("eligible unstarted siblings", plan_skill) + self.assertIn("strict-subset children", plan_skill) + self.assertIn("must not retain the parent route", plan_skill) + + local_only_contracts = ( + "refine-local-plans", + "미착수 local pair", + "`PLAN-local-G??.md`", + "Strict-subset local refinement", + "cloud pair 분리", + "eligible unstarted local siblings", + "strict-subset local children", + "기존 build/review lane, G, canonical basename", + ) + for needle in local_only_contracts: + with self.subTest(needle=needle): + self.assertNotIn(needle, refine_skill) + self.assertNotIn(needle, router) + self.assertNotIn(needle, plan_skill) + self.assertNotIn(needle, sync_ui_skill) + def test_request_to_worker_contract_is_ordered_and_consistent(self) -> None: routing_skill = (SKILL_DIR / "SKILL.md").read_text(encoding="utf-8") plan_skill = PLAN_SKILL.read_text(encoding="utf-8") diff --git a/agent-ops/skills/common/plan/SKILL.md b/agent-ops/skills/common/plan/SKILL.md index 00b8911..06355e7 100644 --- a/agent-ops/skills/common/plan/SKILL.md +++ b/agent-ops/skills/common/plan/SKILL.md @@ -102,7 +102,7 @@ Task directory naming rules: - Example: split a refactoring common core plus two app integrations under `agent-task/refactoring/` as `01_core`, `02+01_edge_integration`, `03+01_node_integration`. Both integrations depend only on `01_core` and may run in parallel after `01_core` has `complete.log`. - Example: split three sequential tasks under one task group as `01_schema`, `02+01_migration`, `03+02_api`. - Example: split independent docs/UI plus an integration under one task group as `01_core`, `02+01_db`, `03+02_api`, `04_docs`, `05_ui`, `06+05_integration`; `01_core`, `04_docs`, and `05_ui` can start together, and `06+05_integration` waits only for `05_ui`. -- After a pair is written, preserve its task group and subtask directory name verbatim. Only an explicit `refine-local-plans` run may rename eligible unstarted local siblings by its dependency-order rules. +- After a pair is written, preserve its task group and subtask directory name verbatim. Only an explicit `refine-plans` run may rename eligible unstarted siblings by its dependency-order rules. Final routing boundary: @@ -111,7 +111,7 @@ Final routing boundary: - Execute `finalize-task-routing` once for build/review and use only its lane/G/filenames. Apply it to first-pass, follow-up, USER_REVIEW replan, and each split subtask independently. - Quarantine previous lane/G/score/rationale. Carry only revalidated code, findings, command output, `review_rework_count`, and `evidence_integrity_failure`. - `needs_evidence` names genuinely missing closure evidence; `blocked` stops file creation. Changed plan facts invalidate the route. -- Only `refine-local-plans` may retain an unstarted local pair's route while splitting it into strict-subset local children. +- Only `refine-plans` may replace an unstarted pair with strict-subset children. It must run `finalize-task-routing` in `isolated-reassessment` mode for every completed child packet and must not retain the parent route. Directory states: diff --git a/agent-ops/skills/common/refine-local-plans/SKILL.md b/agent-ops/skills/common/refine-plans/SKILL.md similarity index 75% rename from agent-ops/skills/common/refine-local-plans/SKILL.md rename to agent-ops/skills/common/refine-plans/SKILL.md index 34169c4..6b61cfb 100644 --- a/agent-ops/skills/common/refine-local-plans/SKILL.md +++ b/agent-ops/skills/common/refine-plans/SKILL.md @@ -1,18 +1,18 @@ --- -name: refine-local-plans -description: 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, local plan 분리해 같은 요청에서 이미 생성된 미착수 PLAN-local-G??/CODE_REVIEW pair를 최대 3개의 작은 local sibling pair로 나누고 같은 task group의 미착수 index를 의존성 순서로 함께 정렬할 때 사용한다. +name: refine-plans +description: 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, task 세분화해 같은 요청에서 이미 생성된 미착수 PLAN-*-G??/CODE_REVIEW pair를 lane 구분 없이 최대 3개의 작은 sibling pair로 나누고 같은 task group의 미착수 index를 의존성 순서로 함께 정렬할 때 사용한다. --- -# Refine Local Plans +# Refine Plans ## 목표 -이미 생성된 미착수 local pair를 로컬 모델이 수행하기 쉬운 응집된 단위로 이번 실행에서 한 단계만 나눈다. Source/test를 다시 조사하거나 검증을 실행하지 않는다. +이미 생성된 미착수 pair를 실행 주체와 lane에 관계없이 응집된 단위로 이번 실행에서 한 단계만 나눈다. Source/test를 다시 조사하거나 검증을 실행하지 않는다. ## 대상 -- 사용자가 지정한 active task group, task path, 또는 `PLAN-local-G??.md`를 사용한다. 대상을 생략하면 미착수 local pair가 있는 task group이 정확히 하나일 때만 진행한다. -- `PLAN-local-G??.md`와 matching `CODE_REVIEW-*-G??.md`가 모두 있고 verdict가 없어야 한다. +- 사용자가 지정한 active task group, task path, 또는 `PLAN-*-G??.md`를 사용한다. 대상을 생략하면 미착수 pair가 있는 task group이 정확히 하나일 때만 진행한다. +- `PLAN-*-G??.md`와 matching `CODE_REVIEW-*-G??.md`가 모두 있고 verdict가 없어야 한다. Build lane은 대상 자격에 사용하지 않는다. - Review의 구현 완료표·구현 체크리스트가 모두 미체크이고, 구현 소유 기록과 검증 출력이 아직 채워지지 않은 pair만 미착수로 본다. - `complete.log` 또는 `USER_REVIEW.md`가 있거나 구현이 시작된 pair는 수정하지 않는다. - 대상 pair, 같은 task group의 미착수 active sibling pair, active directory basename과 archived sibling directory basename만 읽는다. Archive 내부 파일은 읽지 않는다. 새 구현 조사를 위해 source/test/roadmap/archive 본문을 읽지 않는다. @@ -44,15 +44,17 @@ description: 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 - Reindex되는 sibling은 directory basename과 PLAN/review 안의 기존 task path·index·dependency 참조를 새 값으로 바꾼다. 구현 scope, checklist, 검증, routing은 바꾸지 않는다. 4. **현재 PLAN/CODE_REVIEW 형식을 유지한다** - - 각 child는 기존 PLAN을 복제한 뒤 자신의 scope만 남긴다. Header/task, title, background, `구현 체크리스트`, plan item, `수정 파일 요약`, `최종 검증`을 child 경계에 맞게 갱신한다. 기존 PLAN에 `분석 결과`가 있으면 읽은 파일·테스트 공백·심볼 참조·분할 판단·범위 결정 근거도 child 범위로 줄인다. + - 각 child는 기존 PLAN을 복제한 뒤 자신의 scope만 남긴다. Header/task, title, background, `구현 체크리스트`, plan item, `수정 파일 요약`, `최종 검증`을 child 경계에 맞게 갱신한다. 기존 PLAN에 `분석 결과`가 있으면 읽은 파일·테스트 공백·심볼 참조·분할 판단·범위 결정 근거도 child 범위로 줄이고 기존 `최종 라우팅`은 제거한다. - `Roadmap Targets`는 전체 결과를 닫는 closure child 하나에만 둔다. + - 각 child PLAN body가 완성되면 parent와 sibling의 이전 lane/G, 점수, route 사유, filename을 입력에서 제거하고 child packet과 기존 PLAN에 이미 있는 사실만 사용해 `finalize-task-routing`을 `evaluation_mode=isolated-reassessment`로 정확히 한 번 실행한다. Routing 때문에 source/test/log를 다시 읽지 않는다. + - `review_rework_count`와 `evidence_integrity_failure`만 route-free 운영 이력으로 전달한다. Child 중 하나라도 `status=routed`가 아니면 원본 pair와 sibling 경로를 바꾸지 않고 중단 사유만 보고한다. + - 각 child의 `최종 라우팅`, build/review lane, G, canonical basename은 finalizer 출력으로 갱신한다. Lane, G, boundary, filename을 수작업으로 만들거나 parent 값을 복사하지 않는다. - 각 review는 기존 CODE_REVIEW를 복제한 뒤 header/task, 완료표, 구현 checklist, checkpoint, 검증 section을 matching PLAN과 맞춘다. 고정 안내와 review 전용 section의 문구는 유지하되 child task path와 future archive suffix 참조는 갱신한다. - PLAN과 review는 입력에 이미 있는 section 구조를 유지하며 없는 section을 새로 만들지 않는다. 첫 task header 외의 HTML metadata comment는 출력에서 제거한다. - PLAN과 review의 첫 줄은 동일한 `task`, `plan`, `tag`를 사용한다. Checklist 문구·순서와 검증 명령을 서로 일치시킨다. - - 기존 build/review lane, G, canonical basename과 `최종 라우팅` 값을 child에 그대로 유지한다. Strict-subset local refinement에서는 `finalize-task-routing`을 다시 실행하지 않는다. 5. **최종 pair로 직접 교체한다** - - 모든 child pair, sibling reindex, directory rename map을 먼저 메모리에서 완성하고 최종 경로·archive log 충돌을 확인한다. + - 모든 child pair, finalizer 출력, sibling reindex, directory rename map을 먼저 메모리에서 완성하고 최종 경로·archive log 충돌을 확인한다. - 원본 active review와 PLAN을 각 파일 basename의 lane/G와 다음 monotonic suffix를 사용해 같은 task directory의 `code_review_*.log`, `plan_*.log`로 archive한다. - Reindex가 필요한 미착수 directory는 목적지가 비는 순서로 최종 basename으로 이동한다. 임시 directory나 별도 상태 파일이 필요한 충돌이면 분리하지 않는다. - Indexed target은 첫 child가 최종 basename으로 재사용한다. Task-group root의 single-plan target은 원본 log를 root에 남기고 모든 child directory를 새로 만든다. @@ -68,10 +70,11 @@ description: 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 ## 출력 ```text -Local plan refinement +Plan refinement - targets: <원본 PLAN 경로> - decisions: <유지 | 원본 -> child 목록> - dependency updates: <변경 내용 또는 없음> +- routing updates: - readiness: - document check: passed ``` @@ -80,5 +83,5 @@ Local plan refinement - Source/test 재분석, compile, build, test, lint, formatter, smoke/E2E, live/remote 검증을 실행하지 않는다. - Package 설치, dependency 다운로드, cache warming을 하지 않는다. -- Child 재귀 분리, cloud pair 분리, 다른 task group 또는 시작·완료 sibling 재인덱싱을 하지 않는다. +- Child 재귀 분리, 다른 task group 또는 시작·완료 sibling 재인덱싱을 하지 않는다. - 별도 상태 파일, 임시 pair, repository 밖 복구 파일을 만들지 않는다. diff --git a/agent-ops/skills/common/router.md b/agent-ops/skills/common/router.md index eae86db..efca5aa 100644 --- a/agent-ops/skills/common/router.md +++ b/agent-ops/skills/common/router.md @@ -15,7 +15,7 @@ - plan 요청에 사용할 테스트 환경 규칙이 있으면 `update-test mode=resolve-context`로 read-only `Verification Context`를 만든 뒤 `plan`에 전달한다. 규칙이 없거나 매칭되지 않으면 파일을 생성하지 않고 plan의 repository-native fallback을 사용한다. - `sync-agent-ui`가 `plan-required`로 라우팅한 작업은 plan pair 생성 뒤 `sync-agent-ui mode=prepare-code-work`로 task/UI 매핑을 기록한다. 일반 code-review PASS와 exact `complete.log` 생성 뒤에는 원래 `task-path`와 `completion-log`를 `sync-agent-ui mode=reconcile-completion`에 전달해 해당 매핑만 정합화한다. - pending UI task가 WARN/FAIL follow-up plan으로 교체되면 새 pair 생성 뒤 `prepare-code-work`를 다시 실행한다. 매핑 범위가 실제로 달라진 경우에만 검증 후 state helper의 `--replace`를 사용한다. -- pending UI task를 `refine-local-plans`로 분할하거나 sibling reindex해 경로를 바꾼 경우에는 refine 완료 뒤 `sync-agent-ui mode=prepare-code-work`를 호출한다. 기존 경로는 `previous-task-path`, status 대상 전체를 닫는 child 하나는 새 `task-path`로 넘겨 매핑을 rebind하고, scope/evidence가 달라질 때만 검증 후 `--replace`를 사용한다. +- pending UI task를 `refine-plans`로 분할하거나 sibling reindex해 경로를 바꾼 경우에는 refine 완료 뒤 `sync-agent-ui mode=prepare-code-work`를 호출한다. 기존 경로는 `previous-task-path`, status 대상 전체를 닫는 child 하나는 새 `task-path`로 넘겨 매핑을 rebind하고, scope/evidence가 달라질 때만 검증 후 `--replace`를 사용한다. - `sync-agent-ui`가 `milestone-required`로 라우팅한 작업은 `update-roadmap`이 exact active Milestone을 확정한 뒤 `sync-agent-ui mode=prepare-milestone-work`로 Milestone/UI 매핑을 기록한다. 일반 Milestone 문서에는 agent-ui 전용 완료 필드를 넣지 않는다. - Milestone 종료 요청에서 exact target이 `.sync-state.json.pending_milestone_work`에 있으면 `complete-milestone mode=check-only`를 먼저 실행한다. 종료 가능 근거를 `sync-agent-ui mode=reconcile-milestone-completion`에 전달해 성공 또는 동일 evidence의 already-reconciled를 확인한 뒤에만 `complete-milestone mode=close`를 실행한다. UI 정합화가 실패하면 close하지 않는다. @@ -45,7 +45,7 @@ | 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` | | 계획 세워줘, 계획 작성해, 계획 만들어줘, 구현 계획, PLAN.md, plan, plan 작성해, plan 만들어줘 | `agent-ops/skills/common/plan/SKILL.md` | -| 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, local plan 분리해 | `agent-ops/skills/common/refine-local-plans/SKILL.md` | +| 현재 plan들 세분화해, 현재 plan 세분화, 기존 plan 더 나눠, task 세분화해, plan 분리해 | `agent-ops/skills/common/refine-plans/SKILL.md` | | 최종 라우팅, task routing, cloud/local 재평가, lane/G 판단, G 등급 재평가, routed filename 결정 | `agent-ops/skills/common/finalize-task-routing/SKILL.md` | | 코드 리뷰해줘, 리뷰 진행해, 리뷰해줘, code review, CODE_REVIEW.md, 리뷰 루프 | `agent-ops/skills/common/code-review/SKILL.md` | | 커밋해줘, 푸시해줘, commit, push, 반영해줘 | `agent-ops/skills/common/commit-push/SKILL.md` | @@ -55,7 +55,7 @@ 라우팅 우선순위: -- 이미 생성된 미착수 local pair의 분할만 요청하면 `refine-local-plans`를 선택한다. 새 plan 작성이나 구현 범위 재분석이 포함되면 `plan`을 선택한다. -- `refine-local-plans` 대상이 아닌 PLAN/CODE_REVIEW 작성 또는 재작성이 요청 범위에 포함되면 `plan`을 선택한다. `plan`이 최종 단계에서 `finalize-task-routing`을 필수 호출한다. +- 이미 생성된 미착수 pair의 분할만 요청하면 lane과 관계없이 `refine-plans`를 선택한다. 새 plan 작성이나 구현 범위 재분석이 포함되면 `plan`을 선택한다. +- `refine-plans` 대상이 아닌 PLAN/CODE_REVIEW 작성 또는 재작성이 요청 범위에 포함되면 `plan`을 선택한다. `plan`이 최종 단계에서 `finalize-task-routing`을 필수 호출한다. - lane/G/canonical filename 판단만 요청되고 plan 문서 작성은 요청되지 않았을 때만 `finalize-task-routing`을 직접 선택한다. - 코드 리뷰 요청은 `code-review`를 선택한다. WARN/FAIL follow-up은 `code-review -> plan -> finalize-task-routing` 순서를 유지한다. diff --git a/agent-ops/skills/common/sync-agent-ui/SKILL.md b/agent-ops/skills/common/sync-agent-ui/SKILL.md index 7c5ce3f..d3fdfda 100644 --- a/agent-ops/skills/common/sync-agent-ui/SKILL.md +++ b/agent-ops/skills/common/sync-agent-ui/SKILL.md @@ -72,7 +72,7 @@ description: 정합화된 agent-ui 변경분을 코드에 직접 반영하거나 - `agent-ui-docs`는 현재 활성 view/component 문서이고 status가 `계획`인지 확인한다. `가정`, `불명확`, 이미 archive 된 문서는 매핑하지 않는다. - `frame-docs`는 visual source가 있는 활성 frame-view 문서인지 확인하고 대응 view가 `agent-ui-docs`에 포함됐는지 확인한다. frame-view 자체에는 status를 요구하거나 `구현됨` 전환을 적용하지 않는다. - `code-paths`는 실제 구현 후보로 좁혀진 경로만 기록한다. 존재하지 않는 새 파일 후보는 경로와 생성 의도가 plan에 명시된 경우에만 허용한다. - - 기존 pending task가 `refine-local-plans`로 분할되거나 sibling reindex로 경로가 바뀌었으면 원래 매핑을 그대로 둘 수 없다. status 대상 전체를 닫는 child를 하나만 고르고 기존 경로를 `previous-task-path`, 그 child 경로를 `task-path`로 전달한다. + - 기존 pending task가 `refine-plans`로 분할되거나 sibling reindex로 경로가 바뀌었으면 원래 매핑을 그대로 둘 수 없다. status 대상 전체를 닫는 child를 하나만 고르고 기존 경로를 `previous-task-path`, 그 child 경로를 `task-path`로 전달한다. 2. **pending entry 기록** - `agent-ui/.sync-state.json`의 SHA-256을 계산한 뒤 bundled helper의 `prepare` 명령에 `--expected-sha256`으로 넘긴다. helper는 agent-ui 디렉터리 잠금을 잡은 다음 digest를 다시 확인한다.