--- name: ruleset description: 프로젝트에 적용할 룰셋과 룰 표시 언어를 바꾼다 user-invocable: true disable-model-invocation: true --- ## 설치 경로와 호스트 연결 PLUGIN_ROOT는 이 진입점이 속한 설치 플러그인 루트다. skills//SKILL.md에서는 ../..이다. 공용 scripts/assets/tmpa는 플러그인 루트에 한 번만 배치한다. 스킬의 references와 보조 문서는 해당 스킬 파일 기준이다. `${PLUGIN_ROOT}`와 `${PLUGIN_DATA}`가 셸에 자동 설정됐다고 가정하지 않는다. 로드한 파일의 실제 위치로 루트를 확인하고, 실행할 때 실제 절대경로로 대체하거나 동일 셸 호출에서 변수를 설정한다. PLUGIN_DATA는 호스트가 제공하는 영속 데이터 경로를 우선 사용하고, 없으면 사용자 데이터 디렉터리 아래 이 플러그인 전용 경로를 사용한다. 사용자의 분석 대상 작업 디렉터리는 바꾸지 않는다. bash 예제는 bash에서 실행한다. SKILL_ROOT는 지금 읽은 SKILL.md의 부모 디렉터리다. 이 스킬 전용 scripts/assets는 SKILL_ROOT 아래에 있다. `${SKILL_ROOT}`는 설명용 표기이며 자동 설정된 환경변수가 아니다. 스크립트 실행 시 로드한 SKILL.md의 실제 위치로 절대경로를 구성한다. 프로젝트 작업 디렉터리를 스킬 폴더로 바꾸지 않는다. ## 실행 경로 `${SKILL_ROOT}`는 이 SKILL.md가 있는 디렉터리의 절대 경로로 바꿔 실행한다. 작업 디렉터리는 분석 대상 프로젝트에 유지한다. `scripts/run.py`는 이 플러그인의 공용 런타임을 사용하므로 스킬 폴더만 따로 복사하지 않는다. **사용자에게는 한국어로 답하라.** 사용자가 다른 언어로 말을 걸었다면 그 언어를 따른다. 이 프로젝트에 연결된 STATIC 서버 프로젝트의 **룰셋 선택**을 보여주고 바꾼다. 지금까지 웹에서만 할 수 있던 일이다. ## 1. 지금 상태부터 읽는다. 예외 없다. ```bash python "${SKILL_ROOT}/scripts/run.py" ruleset-show --project-dir "$(pwd)" ``` **변경 API 는 전체 교체다.** 지금 켜져 있는 것을 모르는 채 일부만 보내면 **나머지가 조용히 꺼진다.** 그러면 다음 분석부터 결함 수가 줄어드는데, 코드는 그대로라 아무도 이유를 모른다. 그래서 사용자가 "A 룰셋 켜 줘" 라고만 해도 **먼저 이것을 읽고 그 위에 더해야 한다.** 결과 읽기: - `rulesets` 는 이 프로젝트에 쓸 수 있는 **전체 목록**이고, 각 항목의 `enabled` 가 현재 선택 상태다. `id` 는 다음 단계에서 그대로 쓴다. - `catalogComplete: false` 면 **전체 목록을 읽지 못한 것**이다. 그때 `rulesets` 에는 지금 켜져 있는 것만 들어 있다 — 끄는 것과 유지하는 것은 그대로 할 수 있지만 **새로 켤 후보는 보이지 않는다.** 사용자가 없는 룰셋을 켜 달라고 하면 목록이 불완전하다고 말하고 웹에서 확인하도록 안내하라. 목록에 없다고 "그런 룰셋은 없다"고 단정하지 마라. - `localeLanguage` 는 룰 이름·설명을 어느 언어로 보여줄지다 (`ko_KR`, `en_US` …). 룰셋과 **한 번에** 바뀌는 값이라 여기서 함께 보여준다. - `language` · `analyzerVersion` 은 이 목록이 어느 조건에서 유효한지다. 사용자가 묻지 않으면 굳이 말하지 않아도 된다. 사용자에게는 **켜진 것과 꺼진 것을 나눠서** 보여줘라. 목록이 길면 켜진 것을 전부 보이고 꺼진 것은 개수와 대표 몇 개만 보인 뒤 "전체를 보시겠습니까"로 물어라. ## 2. 무엇을 켜고 끌지 사용자에게 확정받는다 **추측해서 바꾸지 마라.** 이 설정은 서버 프로젝트의 것이고 **팀 전체가 보는 결함 목록이 달라진다.** - 사용자가 이름으로 말하면(`MISRA` 처럼) 목록에서 찾아 **어느 룰셋인지 확인시킨 뒤** 진행하라. 이름이 여러 개에 걸리면 물어라. - 최종적으로 **켜질 목록 전체**를 보여주고 승인을 받아라. "3개 추가" 가 아니라 "적용 후 켜진 룰셋은 이 5개" 로 보여주는 것이 요점이다 — 전체 교체이므로 사용자가 확인해야 하는 것도 결과 상태다. ## 3. 적용한다 ```bash python "${SKILL_ROOT}/scripts/run.py" ruleset-set --project-dir "$(pwd)" \ --ruleset-id 1 --ruleset-id 4 --ruleset-id 7 ``` - `--ruleset-id` 는 반복한다. **켜질 것 전부**를 나열해야 한다 (1번에서 읽은 `enabled: true` 중 유지할 것 + 새로 켤 것). - 룰 표시 언어도 바꾸려면 `--locale-language ko_KR` 을 붙인다. **생략하면 현재 값이 유지된다** — CLI 가 알아서 읽어서 다시 넣는다. - 표시 언어만 바꾸고 룰셋은 그대로 두려면, 1번에서 읽은 `enabled: true` 의 id 를 **전부 그대로** 나열하고 `--locale-language` 만 새로 준다. ## 4. 바뀌었으면 전체 재분석을 물어본다 3번이 `ok: true` 이고 **적용 결과가 1번에서 읽은 상태와 실제로 다를 때만** 묻는다. 사용자가 구경만 했거나 같은 집합을 그대로 다시 적용했다면 묻지 마라 : 바뀐 게 없으니 다시 돌릴 이유도 없다. **룰셋 변경은 다음 분석부터 적용된다.** 이미 서버에 올라간 revision 의 결함은 바뀌지 않는다. 지금 전체에 반영하려면 전체 재분석이 필요하다. 물을 때 비용을 함께 말해라. 그래야 사용자가 답을 고를 수 있다. - revision 이 하나 더 생긴다 - 라이선스 슬롯을 점유한다 - 프로젝트 전체를 다시 도는 작업이라 시간이 걸린다 **언어에 따라 권할 이유가 다르다. 이것까지 말해줘야 판단이 선다.** - **C/C++** : `/statica:pre-analyze` 는 바뀐 TU 만 다시 돈다. 그래서 재분석하지 않으면 **손대지 않은 파일에는 새 룰셋이 영영 반영되지 않는다.** 여기서는 권할 이유가 있다. - **java · kotlin · python · csharp** : `pre-analyze` 자체가 전량 분석이라 다음 분석 때 저절로 맞춰진다. 지금 돌릴 이유는 "기다리지 않고 바로 보고 싶다" 뿐이다. **하겠다고 했을 때만 실행한다. 아니라고 하면 아무것도 하지 말고 끝내라.** ```bash python "${PLUGIN_ROOT}/scripts/run.py" upload --project-dir "$(pwd)" ``` - `ok: true` → `message` 를 전한다. 이 결과는 **새 룰셋으로 나온 것**이다. - `returncode: 113` → 같은 프로젝트가 이미 분석 중이다. 잠시 후 다시 시도하도록 안내하되, **룰셋 변경 자체는 이미 저장됐다**는 점을 분명히 해라. - `returncode: 114` → 라이선스 동시 실행 한도 초과다. 위와 같다. - 그 밖의 실패도 `hint` 를 그대로 전하면서 **룰셋 변경은 성공했다**고 말해라. 재분석만 실패한 것이다. ## 결과 해석 - `ok: true` → `message` 를 전하고 **4번으로 간다.** - `code: "EMPTY_RULESET"` → 룰셋을 전부 끄려 한 것이다. 최소 하나는 켜져 있어야 한다. - `code: "FORBIDDEN"` (403) → **권한 문제다.** 룰셋 조회는 프로젝트 멤버, 변경은 **프로젝트 매니저**여야 한다. 이 플러그인이 만든 프로젝트라면 AccessKey 의 주인이 소유자이므로 통과한다 — 403 이 났다면 웹에서 다른 사람이 만든 프로젝트일 가능성이 높다. 그 프로젝트의 매니저에게 요청하도록 안내하라. - `code: "NO_ACCESS_KEY"` (401) → Arachne 설정의 AccessKey 문제다. **키를 사용자에게 묻거나 파일에 쓰지 마라.** - `code: "NOT_FOUND"` (404) → 서버에 그 프로젝트가 없거나, 서버가 Open API v1 을 포함하지 않은 구버전이다. - `code: "NEEDS_BOOTSTRAP"` → 이 프로젝트가 아직 STATIC 에 연결되지 않았다. 룰셋을 바꾸려면 먼저 연결해야 한다 (`statica-analyze-bootstrap` 스킬). **변경 후 결함 수가 달라졌다면 그것은 코드가 아니라 룰셋이 바뀐 결과다.** 4번에서 바로 재분석을 돌렸든 나중에 분석이 돌든 마찬가지다. 결과를 보고할 때 이 사실을 잊지 말고 함께 말하라 — 말하지 않으면 사용자는 자기 코드가 좋아졌거나 나빠졌다고 읽는다.