[상류 3단계] materialized route profile 변경 거부 guard #204
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
원 요구·승인
소유자 최신 실행 승인(sent/codex_upstream_execute_approved_sequence_1029.md): 승인 제안 3단계 '독립적인 작은 수정' — materialized profile 변경 거부·route-action 대기 queue guard는 현재 main 상대의 별도 작은 수정, 사용 가능한 독립 단위별 제출. 93 결정 (가)로 3단계를 원 source에 연결. 이 task는 그중 materialized profile guard 1건의 단일 source writer다(p320·공개 PR에 기존 담당 없음, 8e 확인).
원 source (운영 root 12:11 읽기 전용 확인)
운영 source 사본 D:/260720_Ai_Workspace_Tools/kandev-local-main-20261022, branch codex/production, clean, HEAD f742d87b14cfa4cedd9591385af63892746d3478. git-common-dir는 D:/260720_Ai_Workspace_Tools/kandev-upstream-native-20261015/.git(다른 store에서 bad-object가 나는 것은 원본 부재가 아님). 파일 apps/backend/internal/orchestrator/materialized_route_profile_guard.go(51줄): refuseMaterializedRouteProfileChange가 durableRoute의 logicalProfile/generation이 materialized일 때 다른 profile로 in-place 재라벨하는 것을 첫 쓰기 전에 거부하고, first-selection·same-profile·빈 값·미구현 loader는 보존. 실제 소비자는 task_operations.go:886(행번호는 current main에서 달라질 수 있음). 관련 넓은 통합 commit dfd27cb1e0591f0fbd694528ab3ac16e070f178c / f742는 container이므로 통째 cherry-pick·운영판 copy·mega PR 0.
할 일
경계
task_operations.go 등 공통 파일은 같은 시점 다른 source(route-action queue guard 단위 포함)와 동시에 쓰지 않는다 — 이 task가 먼저이며, 변경 경로를 확정해 8e에 알리면 다음 단위가 이어 쓴다. 운영 사본 변경·운영 설정·모델순서·권한 변경 0, 새 상시 시험 체계 0.
8e receiving acceptance: ACCEPT stage-3 materialized route profile guard source unit (task e80cef65-9695-4418-ac61-22059baf24f4, single writer). 8e read-only checks: worktree kandev-upstream-s3-m_cj2j6om3 branch feature/kandev-upstream-s3-m-9ld HEAD 9a49d164c7526f761e4f6799d71495bbca4e7cbb, clean, one commit on upstream main dc2d77359f101fe398255112346b60c617477162, 7 files +240/-2 (new materialized_route_profile_guard.go and _test.go, 3-line hook in task_operations.go startCreatedSession, AC-AGENTS-DYNAMIC-AGENT-ROUTING-001.23 + dynamic-agent-routing-02 note, docs/plans/materialized-route-profile-guard plan.md + task-01). Upstream .github/scripts/pr-docs.cjs validateCoverage run locally by 8e on this diff: status covered, errors 0. Source-reported RED->GREEN through Service.StartCreatedSession, golangci-lint new-from-rev 0, gofmt clean, spec lint/list-docs pass, package-wide only 2 Windows path-separator failures that also fail on clean base. Duplicate check: no equivalent guard on main or open PRs (#4600/#4603/#4710 and neighbours). Formal RV FORMAL-rv-delta-review.md-1793249796289313900-21605-mid-1 (CALL-20261029-de9ab3f136fe) completed REQUEST_CHANGES with 1 finding: guard returns nil when s.repo does not implement dynamicRouteStateLoader. 8e disposition: not a required fix. Evidence: the only production LoadRouteState implementation is (*sqlite.Repository) in internal/task/repository/sqlite/dynamic_route.go:411, so the guard runs on every production start; a repo without the loader persists no durable route, so AC 001.23 (refuse when the durable route is already materialized) has nothing to refuse; existing consumers use the same !ok->continue pattern (dynamic_launch.go, dynamic_restart_recovery.go, dynamic_policy_recovery.go); fail-closed would also refuse first selection, which AC 001.23 requires to keep. The finding and this disposition go to the publisher with the PR. Spec numbering coordinated: 6649f0f8 reserves 001.15/.16, this unit keeps 001.23. task_operations.go writer released for 6649f0f8 / 85ddca62 (different functions). No push/PR/comment from source. Publication: 93->5d new narrow PR from PR-DRAFT.md in _UserHub/_task/kandev-upstream-s3-materialized-profile-guard-20261029.
8e receiving acceptance (supersedes the head in artifact-note:20261029T050157147947Z): ACCEPT final reviewed head c3bd8f473fdde8e3813f12c3556dd58e5a06f1a2 for the materialized route profile guard (task e80cef65). 8e read-only checks: same branch feature/kandev-upstream-s3-m-9ld, clean, base dc2d77359f101fe398255112346b60c617477162, 3 commits (9a49d164c752 guard, 3486c63cecc removes the new test file, c3bd8f473fdd folds the two focused cases into existing apps/backend/internal/orchestrator/dynamic_launch_test.go; no amend/reset/force). Final diff 7 files +229/-2 and no new test file: materialized_route_profile_guard.go (new production file), task_operations.go 3-line hook, dynamic_launch_test.go, AC-AGENTS-DYNAMIC-AGENT-ROUTING-001.23, dynamic-agent-routing-02 note, docs/plans/materialized-route-profile-guard plan.md + task-01. 8e reran upstream pr-docs.cjs validateCoverage on the final diff: covered, errors 0. Final delta formal RV FORMAL-rv-delta-review.md-1793251684983553800-22778-mid-1 (CALL-20261029-d1b5ae8fa62e) completed APPROVE findings 0 (8e read the record). The earlier REQUEST_CHANGES disposition (loader-absent fallback, not required) stays recorded. Source-reported narrow rechecks after the move: two focused tests pass, golangci-lint new-from-rev 0, gofmt clean. No push/PR/comment. Publication: 93->5d new narrow PR from this head; PR-DRAFT.md unchanged except head.
8e receiving acceptance (#4939 review follow-up): ACCEPT head d3a921319e5cbff8b336a5bb2ba7adbddba9d773 (same task e80cef65, same branch) for the #4939 review items. 8e read-only checks: clean, descendant of public #4939 head c3bd8f473fdd (non-force FF possible), one test-only commit, 1 file existing apps/backend/internal/orchestrator/dynamic_launch_test.go +22/-9; production 0, docs 0, new test file 0. Dispositions: xb3MR applied (require.ErrorIs on ErrMaterializedRouteProfileChange; guard wraps the sentinel with %w); xb6Rp applied (same-profile resume and first selection now run through the real StartCreatedSession entrypoint); xb6Rl non-defect (../../specs resolves to the existing design file; already answered and resolved publicly); top-level review 5693684931 A non-defect (ceiling deferral returns before any session write, replay goes through the same startCreatedSession where the guard runs before the write; admission order kept); B non-defect (early return compares the session logical profile, same logical profile is not a change under AC 001.23; narrow real-entrypoint repro with a stale label made no session write; drift reconciliation is out of scope, no migration/relabel). Formal RVs: FORMAL-rv-delta-4939-review.md-1793260612861118600-6018-mid-1 (CALL-20261029-6bde8e0ceb05) and FORMAL-rv-4939-review2.md-1793261416780731200-8200-mid-1 (CALL-20261029-01470aa07d33) both completed APPROVE findings 0 (8e read both). Source-reported: two focused tests pass, gofmt clean, golangci-lint new-from-rev 0. No push/comment. Publication: 93->5d non-force FF of #4939 to d3a921319e5c, replies to xb3MR/xb6Rp threads with resolve, and a top-level reply for review 5693684931 A/B.
8e receiving acceptance (supersedes the head in artifact-note:20261029T084047069852Z): ACCEPT head 32d230751565736fbf7635d836702877794711f3 for #4939 (task e80cef65, same branch). 8e read-only checks: clean, descendant of public #4939 head c3bd8f473fdd (non-force FF possible); vs c3bd only existing apps/backend/internal/orchestrator/dynamic_launch_test.go +33/-10 (commits d3a921319e5c + 32d230751565); production 0, docs 0, new test file 0. The positive cases now assert success through the real StartCreatedSession entrypoint: require.NoError plus the fixture's existing launch counter equal to 1 for both same-profile resume and first selection. Source-observed values: before the fix, first selection returned 'task not found: task-unrouted' with 0 launches and still passed the old NotErrorIs check; after seeding the mock task repo, both cases return err=nil and launches=1. Formal RVs: 6018-mid-1 and 8200-mid-1 (earlier rounds) plus FORMAL-rv-4939-positive-review.md-1793269245442381400-5818-mid-1 (CALL-20261029-421dc3c78223) completed APPROVE findings 0 (8e read). Dispositions unchanged: xb3MR applied, xb6Rp applied with success assertions, xb6Rl non-defect (already resolved), top-level review 5693684931 A and B non-defect. No push/comment. Publication: 93->5d non-force FF of #4939 to 32d230751565.
8e publication acceptance: the materialized route profile guard is published upstream as kdlbs/kandev#4939 and its review items are dispositioned. 8e gh readback: OPEN, MERGEABLE, head 32d230751565736fbf7635d836702877794711f3 = reviewed head accepted in artifact-note:20261029T102404828451Z, unresolved review threads 0. 93 readback: non-draft, base main dc2d77359f10, 7 files +252/-2; xb3MR and xb6Rp resolved with replies 4411209737 and 4411210256, xb6Rl resolved earlier, top-level review 5693684931 A/B answered in issuecomment-6494216391 (no inline resolve claim). Exact-head check-runs at 93 read: 14 records, failures 0, action_required 0, 5 success, 4 in progress, 7 skipped; the separate PR documentation coverage status was still pending at that read. This is not a whole-CI-green claim; no rerun; E2E and PostgreSQL not claimed. Outstanding CI completion and maintainer review/merge remain external.
Complete; the task advanced to the terminal 완료 step.
Cycle-3 final state
feature/kandev-upstream-s3-m-9ldat head32d230751565(clean, unpushed), basedc2d77359f1; published #4939 headc3bd8f473fd.dynamic_launch_test.go— ErrorIs sentinel on the refusal case; entrypoint-driven same-profile/first-selection positive cases assertingrequire.NoError+ exactly one launch.8e3eb6b7; publication/update/reply/resolve on#4939owned by 93→5d.8e correction to the check counts in artifact-note:20261029T103140797162Z (counts only; the closure stands): 93 later corrected its readback. Latest exact-head read for #4939 head 32d230751565: 16 check-run records, 8 success, 7 skipped, 1 in progress, 0 failed; the separate combined commit status reports PR documentation coverage SUCCESS (run 40857835142). The earlier '14 records / docs pending' figures were a superseded snapshot. No rerun; not a whole-CI-green claim while one run is still in progress.