diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 541b0d7..4bbebe0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,9 @@ # 기여·릴리스 기준 +[설치·사용 안내](README.md) · [동작 평가](evals/README.md) + +## 작성 원칙 + - 사용자-facing 문서와 Skill은 간결한 한국어로 작성하고 API 식별자는 그대로 사용합니다. - Skill `description`은 발동 조건을 명확하게 쓰고, 특정 업무의 상세 절차는 필요할 때 읽는 reference로 분리합니다. - 프로젝트·모델·배포 범위와 기존 사용자 승인을 보존합니다. 일반 작업마다 새로운 승인 단계를 추가하지 않습니다. @@ -7,14 +11,52 @@ - Input schema와 실제 결과는 현재 MCP가 기준입니다. `tests/fixtures/ennoia-tools.json`은 작성 시점의 tool-name 회귀 검사 자료이며 runtime schema를 대체하지 않습니다. MCP 계약 변경 시 확인한 server revision과 snapshot을 함께 갱신합니다. - Skill/reference는 `plugins/ennoia` 내부에서만 상대 경로로 참조합니다. ZIP 생성과 host별 Skill 복제는 필요하지 않습니다. +## 저장소 구조 + +```text +.agents/plugins/marketplace.json # Codex Marketplace +.claude-plugin/marketplace.json # Claude Marketplace +plugins/ennoia/ + plugin.json # Portable metadata 원본 + mcp.json # Remote MCP 설정 원본 + .codex-plugin/plugin.json # Codex 호환 manifest + .claude-plugin/plugin.json # Claude manifest + .mcp.json # 두 host의 호환 MCP 설정 + skills/ # 공유 Skill 원본 7개 + references/ # 공통 응답 해석·표시 규칙 + assets/ # 공식 아이콘·로고, 다크 모드용 로고 +scripts/ # 작성자용 sync·검증 도구 +tests/ # 배포 회귀 검증과 tool 계약 snapshot +evals/ # 모델 동작 검증 시나리오 +``` + +두 Marketplace는 동일한 `./plugins/ennoia`를 설치합니다. Marketplace와 Plugin 이름은 모두 `ennoia`이며 설치 식별자는 `ennoia@ennoia`입니다. MCP는 `https://mcp.ennoia.so/mcp`에 원격 연결합니다. Plugin 밖의 파일이나 symlink를 참조하지 않아 host cache로 복사해도 필요한 자료가 유지됩니다. 사용자는 Python이나 로컬 서버를 실행할 필요가 없습니다. + +## 변경하기 + +Metadata·version은 `plugins/ennoia/plugin.json`, MCP 설정은 `plugins/ennoia/mcp.json`, Skill은 `plugins/ennoia/skills/` 원본에서 수정합니다. 호환 파일을 직접 수정하지 말고 아래 명령으로 생성합니다. + +```bash +python3 -m pip install -r requirements-dev.txt +python3 scripts/sync_manifests.py +``` + +이 명령은 공식 asset 원본에서 다크 모드 로고와 Skill별 아이콘 복사본도 생성합니다. 배포할 Plugin 내용이 바뀌면 version을 올려 host cache가 갱신되게 합니다. README 등 패키지 밖의 안내 문서만 바뀐 경우에는 Plugin version을 올리지 않습니다. + ## 검증 -README의 Python 검증에 더해 설치된 native client로 아래를 확인합니다. +먼저 패키지와 회귀 검사를 실행합니다. ```bash +python3 scripts/sync_manifests.py --check +python3 scripts/validate.py +python3 -m unittest discover -s tests -v python3 scripts/validate_results.py +git diff --check ``` +CI는 credential 없이 패키지 구조와 회귀 테스트를 실행합니다. 설치된 native client의 검증, OAuth, 실제 MCP 업무 결과와 latency는 별도로 확인합니다. + 공개 결과 case는 [`evals/results/2026-09-15-dogfooding-schema.json`](evals/results/2026-09-15-dogfooding-schema.json)의 필수 field와 host·surface·Plugin/source SHA·Skill 로딩/연결 source를 따릅니다. 미측정 수치는 `null`, 미실행 호출 수는 0으로 기록하고 합성 판정을 실제 host `pass`로 재분류하지 않습니다. Host 원본 log·UI·credential은 commit에서 제외합니다. Native Git 설치, 새 세션 Skill 로딩, 인증/연결 source, App/CLI 실행, 성능을 각기 독립 gate로 기록합니다. [`독립 필수 행렬`](evals/results/2026-09-15-mandatory-host-cases.json)의 각 업무·신구 계약 case를 별도로 판정합니다. Composite case는 여러 경로의 성공을 대체하지 않습니다. 성능 `pass`에는 실제 관측된 전체 시간·MCP 시간·응답 크기·모델/cache token 및 reference/추가 확인/재시도 수를 요구하고, 실패 sample의 결측은 이유를 기록합니다. 한 arm이나 무측정 결과에서 비교 우위를 주장하지 않습니다. @@ -39,3 +81,14 @@ Claude validator의 성공은 Skill 행동이나 OAuth 성공을 증명하지 5. 검증한 client 버전, repo commit, MCP 환경, 완료 범위와 제한을 로컬 `docs/`에 기록합니다. 이 디렉터리는 Git에 포함하지 않습니다. Ennoia MCP의 model 실행·저장·배포 검증은 별도 승인된 테스트 프로젝트에서 수행합니다. 로컬 validator 통과를 운영 배포 승인으로 표현하지 않습니다. + +### 자동 발행과 복구 + +`main` 변경은 **Validate plugin** workflow의 검증 성공 후 manifest version으로 `v` 태그와 GitHub Release를 자동 생성합니다. 릴리스 노트는 병합 PR을 기준으로 생성하며, 사전 버전은 prerelease로 표시합니다. 별도 PAT 없이 발행 job의 `GITHUB_TOKEN`에만 `contents: write` 권한을 부여합니다. + +- 이미 발행된 버전의 태그와 Release는 변경하지 않습니다. +- 태그 생성 후 Release 생성이 실패했다면 Actions → **Validate plugin** → **Run workflow**에서 `main`을 선택해 복구합니다. +- 기존 태그의 version·main 이력이 맞지 않거나 기존 draft Release가 있으면 중단합니다. 태그를 강제로 이동하지 않습니다. +- PR·다른 branch·tag push에서는 발행하지 않으며, 자동화 도입 전 태그를 일괄 발행하지 않습니다. + +앱 설치는 계속 Git repo Marketplace를 사용합니다. diff --git a/README.md b/README.md index a85dcc1..f845b89 100644 --- a/README.md +++ b/README.md @@ -5,138 +5,171 @@ Ennoia -Ennoia에서 에이전트를 만들고, 문서를 지식으로 연결하고, App에 업무를 요청하고, 배포·실행 상태를 관리하는 Plugin입니다. +**대화로 Ennoia 에이전트를 만들고, 문서를 연결하고, 업무를 실행하세요.** -**하나의 repo, 하나의 Skill 원본을 Codex App·Claude App·Codex CLI·Claude CLI에서 사용합니다.** 앱은 ZIP 업로드 없이 GitHub repo를 Marketplace로 추가합니다. +Codex App · Claude App · Codex CLI · Claude Code에서 같은 플러그인을 사용합니다. 작업별 Skill 7개와 Ennoia MCP를 함께 설치하며, 별도 서버 실행이나 ZIP 업로드는 필요하지 않습니다. -- Marketplace: `ennoia` -- Plugin: `ennoia` · 설치 식별자: `ennoia@ennoia` -- Repo: `wanteddev/ennoia-plugin` -- Ennoia MCP: `https://mcp.ennoia.so/mcp` -- Runtime 설치 의존성: 없음. Plugin에는 Skill·설정·참고자료만 포함하며 MCP는 원격으로 연결합니다. +[설치](#설치) · [사용 예시](#사용-예시) · [업데이트](#업데이트) · [문제 해결](#문제-해결) · [릴리스 내역](https://github.com/wanteddev/ennoia-plugin/releases) -## 앱에서 설치 +## 설치 -### Codex App +사용하는 환경을 펼쳐 안내를 따라주세요. 설치 후 Ennoia에 로그인하고 **새 대화·작업**에서 시작합니다. -플러그인 → 마켓플레이스 추가에서 아래 값을 입력합니다. +> 이 저장소는 GitHub Internal 저장소입니다. 저장소 읽기 권한이 있는 GitHub 계정과 사용할 프로젝트에 접근할 수 있는 Ennoia 계정이 필요합니다. 두 계정의 인증은 별개입니다. -| 필드 | 값 | -| --- | --- | -| 출처 | `wanteddev/ennoia-plugin` | -| Git ref | `main` | -| Sparse 경로 | **비워 둡니다** | +
+Codex App + +1. **플러그인 → 마켓플레이스 추가**를 엽니다. +2. 아래 값을 입력합니다. + + | 필드 | 값 | + | --- | --- | + | 출처 | `wanteddev/ennoia-plugin` | + | Git ref | `main` | + | Sparse 경로 | **비워 둡니다** | -마켓플레이스를 추가한 뒤 **Ennoia → 설치**를 선택합니다. 요청되는 Ennoia 로그인을 완료하고 새 작업에서 사용합니다. repo 전체가 작으므로 Sparse checkout이 필요하지 않습니다. 다른 예시의 `plugins/codex` 경로를 입력하면 이 repo의 설치 구성을 누락하게 됩니다. +3. 마켓플레이스에서 **Ennoia → 설치**를 선택하고, 요청되는 Ennoia 로그인을 완료합니다. -### Claude App +
-Plugin을 지원하는 Claude App의 마켓플레이스 추가 화면에서 **URL에 `wanteddev/ennoia-plugin`** 또는 `https://github.com/wanteddev/ennoia-plugin.git`을 입력하고 **동기화**합니다. Ennoia Marketplace에서 Ennoia Plugin을 설치합니다. Ennoia 연결의 OAuth 로그인도 완료합니다. +
+Claude App -일반 채팅의 파일 첨부·ZIP 업로드 메뉴가 아닌 **Plugin Marketplace**를 사용합니다. 앱의 Code/Cowork 등 Plugin 지원 작업 환경에서 사용하며, 일반 채팅의 MCP connector와 Plugin Skill 지원은 구분합니다. 앱의 계정·조직 정책에 따라 Marketplace와 connector를 허용해야 할 수 있습니다. +1. Code/Cowork 등 **Plugin을 지원하는 작업 환경**에서 마켓플레이스 추가를 엽니다. +2. URL에 아래 저장소를 입력하고 **동기화**합니다. -### 비공개 repo 접근 + ```text + wanteddev/ennoia-plugin + ``` -현재 이 repo는 비공개입니다. 설치 계정에 `wanteddev/ennoia-plugin` 읽기 권한이 필요합니다. Claude App의 GitHub 연결이 저장소를 표시하지 않으면 해당 GitHub App/조직 연결에 repo 접근을 허용해야 합니다. CLI는 사용자의 Git/SSH credential을 사용합니다. repo를 public으로 바꾸거나 token을 URL·manifest에 넣을 필요가 없습니다. **GitHub repo 접근과 Ennoia OAuth는 별도의 인증입니다.** +3. Ennoia Marketplace에서 **Ennoia Plugin**을 설치하고 Ennoia 연결에 로그인합니다. -## CLI에서 설치 +일반 채팅의 파일 첨부가 아닌 Plugin Marketplace를 사용합니다. 메뉴나 저장소가 보이지 않으면 계정·조직의 Plugin 허용 설정과 GitHub 연결의 저장소 접근 권한을 확인하세요. -### Codex CLI +
+ +
+Codex CLI ```bash codex plugin marketplace add wanteddev/ennoia-plugin --ref main codex plugin add ennoia@ennoia ``` -새 세션에서 `/skills` 또는 `$ennoia-connect`로 시작합니다. MCP 인증이 요구되면 설치된 Ennoia 서버에 대해 host가 제시하는 로그인 흐름을 완료합니다. Plugin이 관리하는 서버를 별도 `codex mcp add`로 중복 등록하지 않습니다. +새 세션에서 `$ennoia-connect`를 실행합니다. 인증이 필요하면 설치된 Plugin의 Ennoia 서버에 대해 Codex가 안내하는 로그인 절차를 따릅니다. + +
-### Claude CLI (Claude Code) +
+Claude CLI · Claude Code ```bash claude plugin marketplace add https://github.com/wanteddev/ennoia-plugin.git claude plugin install ennoia@ennoia ``` -새 세션에서 `/ennoia:ennoia-connect`를 실행합니다. `/mcp`에서 Plugin의 Ennoia 서버를 선택해 로그인합니다. GitHub shorthand `wanteddev/ennoia-plugin`도 지원하지만 SSH 설정이 없는 환경에서는 위 HTTPS URL이 편리합니다. +새 세션에서 `/ennoia:ennoia-connect`를 실행합니다. `/mcp`에서 Plugin의 Ennoia 서버를 선택해 로그인합니다. + +
-오래된 CLI에 `plugin add` 또는 `plugin install` 명령이 없다면 해당 제품을 먼저 업데이트합니다. +설치를 마쳤다면 이렇게 요청하세요. 팀·프로젝트 이름은 실제 사용할 대상으로 바꿉니다. -## 사용하기 +```text +Ennoia에 연결하고, A팀의 업무 자동화 프로젝트를 선택해줘. +사용할 수 있는 에이전트 목록도 보여줘. +``` + +## 사용 예시 -자연어로 Ennoia 작업을 요청하면 관련 Skill을 선택합니다. Skill을 명시하려면 Codex에서 `$스킬이름`, Claude Code에서 `/ennoia:스킬이름`을 사용하거나 앱의 Skill 선택기를 이용합니다. +Skill 이름을 외우지 않아도 자연어로 요청할 수 있습니다. -| Skill | 요청 예시 | +| 하고 싶은 일 | 이렇게 요청하세요 | | --- | --- | -| `ennoia-connect` | “Ennoia에 연결하고 A팀 운영 프로젝트를 선택해줘.” | -| `ennoia-build-agent` | “Ennoia 고객응대봇을 수정하고 검증한 뒤 draft까지만 저장해줘.” | -| `ennoia-knowledge` | “이 문서를 지식 컬렉션에 등록하고 검색 가능한 상태인지 확인해줘.” | -| `ennoia-run` | “Ennoia App으로 이 업무를 처리하고 기존 대화에서 이어가줘.” | -| `ennoia-diagnose` | “Ennoia 고객응대봇의 실패 원인과 사용량을 확인해줘.” | -| `ennoia-publish` | “저장된 Ennoia 에이전트를 배포하고 배포 상태를 확인해줘.” | -| `ennoia-integrations` | “Ennoia에서 data-gateway 등록 여부와 내 연결 상태를 확인해줘.” | +| 에이전트 만들기·수정 | “업무 매뉴얼을 참고해 답하는 고객응대봇을 만들고, 검증한 뒤 초안으로 저장해줘.” | +| 문서·RAG 연결 | “이 문서를 Ennoia 지식 컬렉션에 등록하고 검색 가능한 상태인지 확인해줘.” | +| App으로 업무 처리 | “Ennoia App으로 이 업무를 처리하고, 기존 대화에서 이어가줘.” | +| 오류·사용량 확인 | “고객응대봇의 실행 실패 원인과 사용량을 확인해줘.” | +| 배포 | “저장된 고객응대봇을 배포하고 배포 상태를 확인해줘.” | +| 외부 MCP 연결 확인 | “Ennoia에서 Slack·Atlassian MCP의 등록 여부와 내 연결 상태를 확인해줘.” | -작업은 로그인 사용자의 Ennoia 권한과 프로젝트 범위에서 수행합니다. 기본 프로젝트가 자동 선택됐다면 변경 전에 대상을 명시해야 합니다. 이미 지정한 대상과 승인한 작업은 반복 승인하지 않습니다. Credential은 host의 인증 저장소에 두고 Plugin repo에 저장하지 않습니다. +**저장 후 바로 확인:** 에이전트를 생성·수정해 저장하면 **에이전트 열기** 링크로 Studio 편집 화면을 안내합니다. 실제 저장된 대상이 확인되어야 링크를 제공하며, 테스트·배포 상태는 별도로 알려줍니다. -결과는 그룹·프로젝트 이름으로 안내합니다. 현재 설정과 이번 요청 대상이 다르면 둘을 구분하고, 코드·ID는 기술 상세 요청이나 대상 구분·조회 재개에 필요할 때 표시합니다. 진행 중·부분 실패·미확인 비용을 완료나 0으로 바꾸지 않으며, 실제 App 답변은 관리 요약으로 대체하지 않습니다. 이 규칙은 7개 Skill이 [공통 참고자료](plugins/ennoia/references/response-guide.md)를 함께 사용합니다. +문서는 업로드와 검색 준비가 끝나야 에이전트에서 사용할 수 있습니다. 사용하는 앱에서 파일을 전송할 수 없으면 Ennoia 업로드 화면을 안내합니다. -에이전트를 생성·수정하고 저장하면 **에이전트 열기** 링크를 함께 제공합니다. 실제 저장된 그룹·프로젝트와 에이전트 ID로 Studio 편집 화면에 연결합니다. 저장된 초안은 바로 열어볼 수 있으며, 테스트·배포 상태는 별도로 안내합니다. +
+Skill을 직접 지정하려면 + +Codex에서는 `$스킬이름`, Claude Code에서는 `/ennoia:스킬이름`을 사용합니다. 앱에 Skill 선택기가 있으면 거기서 선택할 수도 있습니다. + +| Skill | 역할 | +| --- | --- | +| `ennoia-connect` | 로그인·프로젝트 선택 | +| `ennoia-build-agent` | 에이전트 생성·수정·검증·테스트·저장 | +| `ennoia-knowledge` | 문서 등록·검색 준비·RAG 연결 | +| `ennoia-run` | App·SuperApp 업무 실행·대화 이어가기 | +| `ennoia-diagnose` | 실행 실패·Trace·사용량·비용 진단 | +| `ennoia-publish` | 배포·App 관리 | +| `ennoia-integrations` | 외부 MCP 등록·연결 관리 | -이미 같은 endpoint를 수동 MCP로 사용 중이라면 각 항목의 source·scope와 실제 요청 연결을 확인합니다. host마다 수동 서버·Plugin·connector가 항상 하나로 합쳐진다고 가정하지 않습니다. 기존 수동 연결의 정리는 사용자가 이전을 요청한 경우에만 선택적으로 진행하며 credential을 다른 source로 복사하지 않습니다. +
-파일 첨부가 곧 Ennoia 업로드 완료를 의미하지 않습니다. 문서는 업로드·인덱싱 준비·에이전트 연결을 각각 확인합니다. host에 binary 전송 기능이 없는 경우 Skill이 Ennoia 업로드 화면 경로를 안내합니다. +## 업데이트 -## 업데이트·제거 +**앱:** Marketplace를 동기화한 뒤 Ennoia Plugin을 업데이트하고 새 대화·작업을 엽니다. -앱에서는 Marketplace 동기화/업데이트 후 Ennoia Plugin을 업데이트하고 새 작업에서 확인합니다. +
+CLI 업데이트 명령 + +Codex CLI: ```bash -# Codex codex plugin marketplace upgrade ennoia codex plugin add ennoia@ennoia +``` -# Claude Code +Claude Code: + +```bash claude plugin marketplace update ennoia claude plugin update ennoia@ennoia ``` -업데이트 뒤 새 세션을 열어 Plugin과 7개 Skill 발견 → 실제 Ennoia MCP 서버 인증 → 현재 그룹·프로젝트 선택 확인 → 읽기 도구 1건의 성공 순서로 확인합니다. Claude CLI에서는 `/mcp`에서 Plugin 서버를 선택합니다. Codex CLI에서는 설치 inventory의 실제 서버 이름을 확인하고 host가 제공하는 그 서버의 인증 안내를 따릅니다. 수동 `ennoia` 등록이 없는 계정에 `codex mcp login ennoia`가 반드시 적용되는 것은 아닙니다. Skill이 보이는데 Ennoia tool이 없다면 먼저 Plugin MCP 활성화와 서버 연결을 확인합니다. +업데이트 후 새 세션을 시작합니다. -제거는 `codex plugin remove ennoia@ennoia` 또는 `claude plugin uninstall ennoia@ennoia`를 사용합니다. Plugin 제거와 Ennoia 계정의 OAuth 권한 철회는 별개이므로 연결 철회까지 필요하면 host의 연결 관리에서 처리합니다. +
-## 저장소 구조 +업데이트 후 “Ennoia 연결 상태와 현재 프로젝트를 확인해줘”라고 요청해 연결을 확인합니다. 변경 사항은 [릴리스 내역](https://github.com/wanteddev/ennoia-plugin/releases)에서 볼 수 있습니다. -```text -.agents/plugins/marketplace.json # Codex Marketplace -.claude-plugin/marketplace.json # Claude Marketplace -plugins/ennoia/ - plugin.json # Portable metadata 원본 - mcp.json # Remote MCP 설정 원본 - .codex-plugin/plugin.json # Codex 호환 manifest - .claude-plugin/plugin.json # Claude manifest - .mcp.json # 두 host의 호환 MCP 설정 - skills/ # 공유 Skill 원본 7개 - references/ # 공통 응답 해석·표시 규칙 - assets/ # 공식 아이콘·로고, 다크 모드용 로고 -scripts/ # 작성자용 sync·검증 도구 -tests/ # 배포 회귀 검증과 tool 계약 snapshot -evals/ # 모델 동작 검증 시나리오 -``` +## 문제 해결 + +| 증상 | 확인할 내용 | +| --- | --- | +| 저장소를 찾을 수 없음 | GitHub 저장소 읽기 권한과 앱의 GitHub 연결 권한을 확인합니다. CLI에서는 Git 인증 상태를 확인합니다. | +| CLI에 `plugin` 명령이 없음 | Codex CLI 또는 Claude Code를 업데이트합니다. | +| 설치했는데 Skill이 안 보임 | Plugin 활성화를 확인하고 새 대화·세션을 시작합니다. | +| Skill은 보이는데 Ennoia에 연결되지 않음 | Plugin의 MCP 활성화와 Ennoia 로그인을 확인합니다. Claude Code에서는 `/mcp`를 사용합니다. | +| 이미 Ennoia MCP를 수동 등록함 | Plugin과 기존 연결이 함께 있을 수 있습니다. 별도 MCP를 추가 등록하지 말고 실제 사용하는 연결부터 확인합니다. | -두 Marketplace는 동일한 `./plugins/ennoia`를 설치합니다. Plugin 밖을 참조하는 파일이나 symlink가 없어 host cache로 복사된 뒤에도 동일하게 동작하도록 구성했습니다. End user가 Python이나 스크립트를 실행할 필요는 없습니다. +
+플러그인 제거 -## 개발·릴리스 +앱에서는 Plugin 관리 화면에서 Ennoia를 제거합니다. CLI에서는 해당 명령을 사용합니다. ```bash -python3 -m pip install -r requirements-dev.txt -python3 scripts/sync_manifests.py --check -python3 scripts/validate.py -python3 -m unittest discover -s tests -v +# Codex CLI +codex plugin remove ennoia@ennoia + +# Claude Code +claude plugin uninstall ennoia@ennoia ``` -Metadata·version은 `plugins/ennoia/plugin.json`, MCP 설정은 `plugins/ennoia/mcp.json`에서 수정한 뒤 `python3 scripts/sync_manifests.py`로 호환 파일을 생성합니다. 이 명령은 공식 asset 원본에서 다크 모드 로고와 Skill별 아이콘 복사본도 생성합니다. Skill은 `plugins/ennoia/skills` 원본에서 수정합니다. 동일한 버전을 덮어쓰지 말고 릴리스 시 version을 올려 host cache를 갱신합니다. +Plugin 제거와 Ennoia OAuth 권한 철회는 별개입니다. 연결 권한도 해제하려면 해당 앱·CLI의 연결 관리에서 처리합니다. -`main`에 반영되면 **Validate plugin** workflow의 검증 성공 후 manifest version으로 `v` 태그와 GitHub Release를 자동 생성합니다. 현재 `1.1.0`이면 `v1.1.0`을 발행하며, 릴리스 노트는 [GitHub Release API](https://docs.github.com/en/rest/releases/releases#create-a-release)가 병합 PR 기준으로 생성합니다. `1.2.0-rc.1` 같은 사전 버전은 prerelease로 표시합니다. 별도 PAT 없이 발행 job의 `GITHUB_TOKEN`에만 `contents: write` 권한을 부여합니다. +
-이미 발행된 버전은 태그와 Release를 변경하지 않습니다. 태그만 생성되고 Release 생성이 실패했다면 Actions → **Validate plugin** → **Run workflow**에서 `main`을 선택해 같은 태그의 Release를 복구할 수 있습니다. 기존 태그의 version·main 이력이 맞지 않거나 기존 draft Release가 있으면 중단합니다. PR·다른 branch·tag push에서는 발행하지 않으며, 자동화 도입 전 태그를 일괄 발행하지 않습니다. 앱 설치는 계속 Git repo Marketplace를 사용합니다. +## 개발 및 기여 -[기여·검증 기준](CONTRIBUTING.md)과 [동작 평가](evals/README.md)를 따라 검증합니다. CI는 credential 없이 패키지 구조와 회귀 테스트를 실행합니다. Native client 검증, OAuth, 실제 MCP 업무 결과와 latency 개선은 별도로 확인해야 합니다. +- [개발·검증·릴리스 안내](CONTRIBUTING.md): 저장소 구조, manifest 생성, 검사 명령, 릴리스 절차 +- [Skill 동작 평가](evals/README.md): 평가 시나리오와 실제 확인된 범위 +- [공통 응답 규칙](plugins/ennoia/references/response-guide.md): 프로젝트 표시, 작업 상태, 에이전트 링크