--- name: pre-analyze description: 변경된 소스만 STATIC으로 분석하고 결과 요약을 보여준다 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으로 분석한다. 다음을 실행하라: ```bash python "${SKILL_ROOT}/scripts/run.py" pre-analyze --project-dir "$(pwd)" ``` 출력은 JSON 하나다. 다음 규칙으로 해석해 사용자에게 전달하라. **먼저 `language` 필드를 보라.** 없으면 C/C++ 이고 아래 규칙이 전부 그대로 적용된다. `java` · `kotlin` · `python` · `csharp` 이면 두 가지가 달라진다. - **이 실행은 서버에 업로드하지 않는다.** `analyzer-plugin --no-upload` 로 전량 분석하고 결과를 로컬에 저장한다(`uploaded: false`). 서버 연결은 여전히 필요하다. 사용자가 `/statica:upload` 를 호출하거나 서버 업로드를 명시적으로 요청한 경우에만 upload 스킬을 사용한다. 최초 연결의 `bootstrap-finish` 는 전체 분석·업로드를 함께 수행한다. - **TU 도 재빌드도 없다.** `rebuild` · `rebuildNote` · `analyzerFailures` 는 늘 비어 있으니 언급하지 마라. 대신 `uncapturedNewFiles` 는 "빌드가 캡처하지 못한 파일"이 아니라 **기술서의 소스 루트나 제외 설정에 걸려 분석 범위 밖인 파일**이라는 뜻이다. - `ok: true` 이고 `reason: "NO_CHANGES"` → "변경된 분석 대상이 없습니다"라고 전한다. **이유를 지어내지 마라.** 방금 소스를 고쳤는데 이 답이 나왔다면 원인은 거의 언제나 **직전 응답이 끝날 때 Stop 훅이 이미 그 TU 를 분석해 버린 것**이다(훅은 매 응답마다 돌고 7초쯤 걸린다). 그것이 정상이며 할 일은 없다. 확인은 워크스페이스의 `.staticdata/.app/tu.analyzed.json` 에 적힌 그 TU 의 시각이 소스 mtime 보다 최신인지 보면 된다. **여기서 재빌드나 `/statica:upload` 를 제안하지 마라.** 편집만으로도 증분 분석 대상이 되므로 재빌드는 필요 없다(재빌드가 필요한 것은 **새 파일을 추가**했을 때뿐이고, 그때는 `rebuildNote` 가 따로 나온다). 이미 최신인 결과를 다시 얻겠다고 전체 재분석을 돌리면 라이선스 슬롯을 물고 팀 전체가 보는 revision 을 만든다. - `ok: true` 이고 `analyzed > 0` → `message` 를 그대로 전하고, `defects.topRules` 가 있으면 룰별 건수를 짧게 덧붙인다. 이때 그 건수는 **이번 실행에서 분석한 대상(TU)만의 집계**이지 프로젝트 전체 누적 결함 수가 아니라는 점을 함께 밝혀라. **결함 목록을 파일별로 나열하지 마라** — 이 플러그인의 역할은 분석까지다. `defects.scope` 가 `changedFiles` 면 그 수는 **이번에 변경된 파일에 달린 위반만** 센 것이다. TU 에는 전처리에 딸려 온 시스템 헤더가 수백 개 들어 있고(실측: TU 하나에 161개 중 159개), 그것까지 세면 `.c` 한 줄 고치고 수천 건이 나온다. `allSourceFiles` 면 그 TU 의 전부다. `defects.note` 가 있으면 **그대로 전하라.** C/C++ 에서는 TU 단위 분석이라 여러 번역 단위를 함께 봐야 하는 규칙이 링크 분석에서 달라질 수 있다는 뜻이고, 타 언어에서는 전량 분석 결과의 집계 범위를 설명한다. 결함 파일이 있다는 이유로 업로드됐다고 말하지 마라. - `failures` 배열이 비어 있지 않으면 각 항목의 `hint` 를 함께 알린다. 타 언어에서는 실행이 하나뿐이라 `ok: false` 와 `code: "ANALYZE_FAILED"` 가 같이 온다 — 분석이 통째로 실패한 것이니 결함 수를 보고하지 마라. `hint` 가 "다른 실행이 분석 중" 이면 훅과 커맨드가 겹친 것이니 잠시 뒤 다시 하면 된다. - `rebuildNote` 가 비어 있지 않으면 **그 문장을 반드시 전하라.** `buildCommand` 가 없어(GUI 로만 빌드하는 환경) 재빌드를 돌리지 못했고, 그래서 사용자가 새로 추가한 소스가 캡처되지 않아 분석에서 빠졌다는 뜻이다. `message` 에도 들어 있지만 요약하면서 떨어뜨리지 마라 — 말하지 않으면 사용자는 그 파일이 검사된 줄 안다. IDE 에서 한 번 빌드한 뒤 다시 실행하도록 안내하라. - 부트스트랩 단계(`bootstrap-finish`)의 결과에 `buildCommandWarning` 이 있으면 그 문장도 그대로 전하라. 실패가 아니라 경고다 — 자세한 판단 기준은 `statica-analyze-bootstrap` 스킬 §7 에 있다. - `code: "AGENT_JSON_CORRUPT"` → 이 프로젝트의 워크스페이스는 있으나 그 `agent.json` 이 깨져 읽히지 않는다. 메시지에 적힌 파일을 사용자에게 알리고 고치거나 지우도록 안내하라. **부트스트랩을 새로 시작하지 마라** — 워크스페이스가 둘이 된다. - `ok: true` 이고 `reason: "BOOTSTRAP_IN_PROGRESS"` → 워크스페이스는 있으나 아직 부트스트랩이 끝나지 않았다. `statica-analyze-bootstrap` 스킬의 남은 단계(치환 · 빌드 · `bootstrap-verify` · `bootstrap-finish`)를 이어서 진행하라. - `code: "NEEDS_BOOTSTRAP"` → 이 프로젝트는 아직 STATIC에 연결되지 않았다. **`statica-analyze-bootstrap` 스킬을 읽고 그 절차를 따르라.** 부트스트랩은 한 줄 명령이 아니라 환경 식별부터 서버 등록까지 이어지는 여러 단계이고, 환경에 따라 사용자가 IDE에서 직접 조작해 줄 때까지 기다려야 한다. 부트스트랩은 사용자 프로젝트 파일을 고치고, 전체 빌드를 돌리며, 공용 STATIC 서버에 프로젝트를 생성한다. **반드시 사용자 승인을 먼저 받아라.** 원하지 않으면 그냥 하지 않는다 — Stop 훅은 연결되지 않은 프로젝트에서 아무 말도 하지 않는다. 부트스트랩의 마지막 단계인 `bootstrap-finish` 가 **전체 분석과 서버 업로드까지 같이 끝낸다.** 그 결과가 `fullAnalysis` 에 들어 있으니 그것을 사용자에게 전하라. **맨 위의 `analyze` 를 다시 실행하지 마라** — 방금 돈 전체 빌드 때문에 증분 분석은 언제나 "변경된 대상이 없습니다"로 끝나고, 그러면 분석이 안 된 것처럼 읽힌다. - `code: "NO_ACCESS_KEY"` 또는 `"NO_SERVER_SETTING"` → Arachne 설정에서 서버 주소와 AccessKey를 등록하도록 안내하라. 값을 직접 받아 파일에 쓰려 하지 마라. 컴파일러를 찾지 못했을 때는 추측하지 말고 사용자에게 컴파일러 경로를 물어라.