Skip to main content

deleting-inert-config-row-disables-hidden-feature

설정 행(룰·바인딩·커넥터·플래그 테이블)을 "한 번도 발화한 적 없으니 중복/불필요"라며 지우기 전에 — 그 행의 *존재*를 `has_any`/`exists`/`count>0` 로 읽는 코드가 있는지 세라. 한 용도에서의 비활성이 다른 용도에서의 무해함을 뜻하지 않는다. 증상: 무관해 보이는 기능이 삭제 직후 조용히 꺼지고, 아무 에러도 안 난다.

Jump to install

Source facts

Repository
blas1n/claude-skills
Last source activity
August 18, 2026 at 04:32
Detected SKILL.md language
Korean
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
deleting-inert-config-row-disables-hidden-feature
description
설정 행(룰·바인딩·커넥터·플래그 테이블)을 "한 번도 발화한 적 없으니 중복/불필요"라며 지우기 전에 — 그 행의 *존재*를 `has_any`/`exists`/`count>0` 로 읽는 코드가 있는지 세라. 한 용도에서의 비활성이 다른 용도에서의 무해함을 뜻하지 않는다. 증상: 무관해 보이는 기능이 삭제 직후 조용히 꺼지고, 아무 에러도 안 난다.
# 지워도 되는 줄 알았던 설정 행이 다른 기능의 스위치였다 ## Problem 설정 테이블의 한 행이 **두 가지 목적**을 겸한다: 1. **내용**이 쓰이는 목적 — 그 행이 *무엇을 말하는가* (라우팅 대상, 임계값, 매핑) 2. **존재**가 쓰이는 목적 — 그 행이 *있는가 없는가* (= 암묵적 피처 플래그) 2번은 대개 **어디에도 적혀 있지 않다.** 그래서 1번 기준으로 "이 행은 죽었다"를 정확히 측정하고도, 지우면 2번이 같이 꺼진다. - **증상**: 설정 하나를 정리한 다음날, **무관해 보이는 기능**이 동작을 멈춘다. 에러 없음 · 로그 없음 · 테스트 green. 그 기능은 그냥 **조용히 no-op** 이 된다. - **근본 원인**: `if not await repo.has_any(workspace_id): return` 같은 **존재만 묻는 호출**이 그 테이블을 피처 게이트로 쓰고 있다. - **흔한 오해**: *"이 룰은 한 번도 발화한 적 없다 → 지워도 아무 일도 안 일어난다."* 전제는 참인데 결론이 거짓이다. **발화 = 내용 사용**이고, 게이트는 **존재**를 읽는다. 둘은 서로 다른 관측량이다. ### 실제 사례 (BSVibe, 2026-08-18) `design (plan) → opus` 라우팅 룰이 프로덕션에서 한 번도 resolve 되지 않음을 **정식으로 확인**하고(별도 PR 로 근본 원인까지 규명) 중복으로 판단해 삭제했다. 그런데 `agent_runner._maybe_spawn_impl_run` 이: ```python if not await self._workspace_has_routing_rules(design_run.workspace_id): return # ← 룰이 하나라도 있어야 design→impl 체이닝이 발화 ``` 그 룰이 **해당 워크스페이스의 마지막 룰**이었다(전체 런의 73%가 도는 곳). 결과가 최악의 모양이다 — 프레이머는 여전히 런을 `design_then_impl` 로 표시하므로 루프는 **빌드가 아니라 SPEC** 을 하라고 지시받고, 명세가 떨어지고, **아무도 구현하지 않고**, 런은 `verified` 로 **완료 보고**된다. 사용자는 코드를 요청하고 명세를 받으면서 "완료" 를 듣는다. 체이닝된 하위 런: 삭제 전날 1건 → 삭제 당일 **0건**. ## Solution ### 1. 삭제 전 — 테이블/리포지토리 이름으로 전수 grep 행의 *내용* 필드가 아니라 **테이블·리포지토리·모델 이름**으로 찾아야 한다. 게이트는 내용을 안 읽으므로 필드명으로는 안 걸린다. ```bash # 내용 기준 (이것만 하면 놓친다) grep -rn "artifact_type_hint\|target_model" --include="*.py" . # 존재 기준 — 이쪽이 진짜 위험한 곳 grep -rnE "has_any|exists\(|\.count\(|is not None|len\(.*rules" --include="*.py" . \ | grep -i "<table_or_repo_name>" ``` **`has_any` · `exists` · `count() > 0` · `if rows:` 는 전부 "존재를 읽는다"는 신호**이고, 곧 **피처 플래그**라는 뜻이다. ### 2. 삭제 전 — "이 테이블이 비면 무엇이 달라지나"를 한 문장으로 답하라 답할 수 없으면 아직 지울 준비가 안 된 것이다. ### 3. 삭제 후 — 무관해 보이는 기능 하나를 실제로 돌려라 유닛 테스트는 이걸 못 잡는다. 게이트가 꺼지면 코드 경로가 **일찍 return** 할 뿐이라 아무것도 실패하지 않는다. **프로덕션에서 한 번 돌려 산출물을 세는 것**만이 증거다. ```sql -- 삭제 전/후로 같은 축을 세라 (날짜별 파생 산출물 수) select created_at::date, count(*) from <downstream_rows> where <chained_marker> is not null group by 1 order by 1; ``` ### 4. 수정 — 존재를 플래그로 쓰지 말고 게이트를 자기 근거로 세워라 ```python # Before — 룰 테이블이 파이프라인 스위치를 겸한다 if not await self._repo.has_any(workspace_id): return # After — 파이프라인 결정은 파이프라인 신호가 한다 if frame.get("pipeline") != "design_then_impl": return ``` ⚠️ 게이트를 지울 때 **그 결함 동작을 명세로 박아둔 기존 테스트**가 거의 항상 있다 (`test_no_chaining_without_routing_rules` 같은 이름). 지우지 말고 **뒤집어서** 새 계약을 고정하라 — 그 테스트가 왜 존재했는지가 커밋 기록에 남는다. ## Key Insights - **"발화한 적 없다" ≠ "지워도 무해하다".** 한 값이 두 목적을 겸하면, 한 목적에서의 비활성은 다른 목적에서의 무해함을 **전혀** 함의하지 않는다. 측정이 정확해도 결론은 틀릴 수 있다 — 측정한 관측량이 결론이 필요로 하는 관측량과 다르면. - **존재를 읽는 호출이 가장 위험하다.** 내용을 읽는 코드는 필드명으로 grep 에 걸리지만, `has_any`/`exists` 는 **아무 필드도 언급하지 않아서** 안 걸린다. 삭제 영향 조사는 반드시 **테이블/리포지토리 이름**으로 한 번 더 돌려라. - **가장 나쁜 실패는 에러가 아니라 조용한 조기 완료다.** 게이트가 꺼지면 예외가 아니라 `return` 이 나고, 상류는 아무것도 모른 채 "성공" 을 보고한다. 사용자는 요청한 것과 다른 산출물을 받으면서 **완료 알림**을 듣는다. 실패보다 나쁘다. - **에이전트가 게으른 것처럼 보이면 다음 단계를 의심하라.** 다단계 파이프라인에서 "요청은 코드였는데 명세만 나왔다"는 대개 에이전트의 회피가 아니라 **이어졌어야 할 하류 단계가 안 돈 것**이다. 상류 단계는 제 일을 정확히 했다. → [[agent-degraded-output-suspect-execution-environment]] - **삭제의 사후 검증은 프로덕션에서만 된다.** 게이트 삭제/추가는 유닛 테스트가 구조적으로 못 잡는 변경이다(경로가 실패하는 게 아니라 사라진다). 같은 축으로 **삭제 전후 산출물 수**를 세라. ## Related - `config-menu-offers-options-nothing-implements` — 반대 방향: 메뉴에 있는데 주방에 없다. 이 스킬은 **주방에서 쓰는데 메뉴에 안 적혀 있다.** - `absence-measurement-validity-check` — 0을 재기 전에 생산자가 도는지 확인하라. - `feedback_queue_apply_step_never_wired` — 유닛 통과하나 프로덕션 호출자 0.
View on GitHub