[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CBAQZQYS0DY0CSEHSRXFSX":3,"skill-same:01M6CBAQZQYS0DY0CSEHSRXFSX":46},{"skillNo":4,"name":5,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":21,"linkOnly":22,"markdownContent":23,"markdownBody":23,"frontMatter":24,"refName":25,"commitSha":26,"skillDirectory":27,"forksCount":13,"repositoryHtmlUrl":28,"repositoryHomepageUrl":6,"ownerHtmlUrl":29,"ownerBlogUrl":6,"ownerDescription":30,"updatedAt":31,"install":32,"resources":45},"01M6CBAQZQYS0DY0CSEHSRXFSX","04-package-policy",null,"devwinsoft\u002Fdevian","devwinsoft","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F22570160?v=4","01M6C6RR8W05NH8NPKQNCE3Q72","maoshy","01M6C6RRDJ5TJJCZXRTY801YDH",0,"MIT","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F04-package-policy\u002FSKILL.md",[],[18,19,20],"policy","package","04 package policy","2026-11-10 10:12:30",false,"# 04-package-policy\n\nStatus: ACTIVE\nAppliesTo: v11\nType: Policy\n\n## Scope\n\nDevian UPM 패키지(`com.devian.*`)의 **package.json 메타데이터 정책**과 **Samples~ 구조\u002F생성\u002F빌드 통합 정책**을 통합 정의한다.\n\n> **Samples~의 역할:**\n> - Samples~는 UPM 표준 방식으로 templates를 배포하는 메커니즘\n> - Templates는 사용자(개발자)가 **Import 후 수정**해서 사용하는 것이 목적 (\"editable source distribution\")\n> - Import된 샘플은 프로젝트 Assets 폴더로 복사됨 (원본은 Packages 내 유지)\n> - sync 동작 시 Packages 내 원본만 갱신됨, Assets로 복사된 사용자 수정본은 보존\n\n**적용 대상:**\n- `framework-cs\u002Fapps\u002FUnityExample\u002FPackages\u002Fcom.devian.*\u002Fpackage.json`\n- `framework-cs\u002Fupm\u002Fcom.devian.foundation\u002FSamples~\u002F`\n\n**Prerequisites:**\n- Unity C# 문법 제한: `skills\u002Fdevian-unity\u002F05-unity-csharp-compat\u002FSKILL.md`를 준수한다 (위반 시 FAIL).\n\n---\n\n## package.json 메타데이터 정책 (강제)\n\n### 필수 필드\n\n| 필드 | 정책 |\n|------|------|\n| `name` | 접두어 `com.devian.` 필수 |\n| `version` | `{projectConfigJson}`의 `foundationVersion`으로 빌더가 동기화 ([03-ssot § foundationVersion](..\u002F03-ssot\u002FSKILL.md)) |\n| `unity` | 최소 Unity 버전 동일 고정 |\n| `displayName` | 사람이 읽기 쉬운 이름 |\n| `description` | 1줄 역할 설명 |\n| `author` | `{ \"name\": \"Devian\" }` 고정 |\n\n> 패키지 통합 정책(com.devian.core\u002Funity 금지)은 [03-ssot](..\u002F03-ssot\u002FSKILL.md) §Base UPM package를 참조한다.\n\n### 권장 필드 (선택)\n\n- `keywords`, `documentationUrl`, `changelogUrl`, `licensesUrl`\n\n### JSON 포맷 규칙\n\n- 2-space indent, trailing comma 없음\n- key 순서: `name` → `version` → `displayName` → `description` → `unity` → `author` → `dependencies` → `samples`\n\n---\n\n## dependencies 정책\n\nruntime 패키지는 필요한 최소 의존만 선언한다:\n\n| 패키지 | dependencies |\n|--------|--------------|\n| `com.devian.foundation` | `com.unity.addressables`, `com.unity.nuget.newtonsoft-json`, `com.unity.inputsystem` |\n\n> 의존 방향 정책은 [02-unity-bundles](..\u002F02-unity-bundles\u002FSKILL.md) §의존 방향 정책을 참조한다.\n> Newtonsoft.Json이 필요한 패키지만 `com.unity.nuget.newtonsoft-json`을 추가한다.\n\n---\n\n## Samples~ 구조 정책 (Hard Rules)\n\n### 샘플 소스 위치 (Hard Rule)\n\n샘플 코드는 **반드시** `framework-cs\u002Fupm\u002F\u003CpackageName>\u002FSamples~\u002F...`에서만 작성한다.\n\n**금지:**\n- `framework-cs\u002Fapps\u002FUnityExample\u002FAssets\u002F**` 아래에 샘플 스크립트 생성\u002F수정 금지\n- `framework-cs\u002Fapps\u002FUnityExample\u002FPackages\u002F**` 직접 수정 금지 (빌드 출력물이므로 덮어씌워짐)\n\n### Runtime\u002FEditor 분리 (Hard Rule)\n\n모든 샘플은 **반드시** `Runtime\u002F`과 `Editor\u002F` 폴더로 분리해야 한다.\n\n**필수 구조:**\n```\nSamples~\u002F\u003CSampleName>\u002F\n├── README.md\n├── Runtime\u002F\n│   └── Devian.Samples.\u003CSampleName>.asmdef\n└── Editor\u002F\n    └── Devian.Samples.\u003CSampleName>.Editor.asmdef  ← includePlatforms: [\"Editor\"]\n```\n\n**금지:**\n- Runtime 코드에 `using UnityEditor;` 사용 금지\n- Editor asmdef에 `includePlatforms: []` 사용 금지 (반드시 `[\"Editor\"]` 지정)\n\n### Editor asmdef 구성\n\nEditor-only asmdef 필수 필드:\n- `name`: `Devian.Samples.\u003CSampleName>.Editor`\n- `rootNamespace`: `Devian`\n- `references`: 최소 `[\"Devian.Samples.\u003CSampleName>\"]`\n- `includePlatforms`: `[\"Editor\"]`\n- `noEngineReferences`: `false`\n\n### 에디터 메뉴 경로\n\n`Devian\u002FSamples\u002F\u003CSampleName>\u002FHow to Use`\n\n---\n\n## Sample 네이밍 컨벤션 (동적 파생, 하드코딩 금지)\n\n| 카테고리 | Suffix | SampleName 규칙 | Assembly 규칙 |\n|----------|--------|----------------|---------------|\n| Domain | `Package` | `{DomainKey}Package` | `Devian.Samples.{DomainKey}Package` |\n| Protocol | `Protocol` | `{ProtocolGroup}Protocol` | `Devian.Samples.{ProtocolGroup}Protocol` |\n| Manual | `Package` | `{Key}Package` | `Devian.Samples.{Key}Package` |\n\n- 빌더 구현: `DevianToolBuilder.getSampleName(key, suffix)` → `${key}${suffix}`\n- 위치: `Samples~\u002F{Key}{Suffix}\u002F`\n\n> 상세 네이밍 규칙: [Builder SSOT § Sample 폴더 네이밍 컨벤션](..\u002F..\u002Fdevian\u002F80-tools\u002F11-builder\u002F03-ssot\u002FSKILL.md)\n\n---\n\n## Hybrid Sample (Builder-generated + Manual addon)\n\n일부 샘플은 수동 addon 코드와 빌더가 생성하는 Generated 코드를 함께 포함한다.\n\n**Hybrid Sample 규칙 (Hard Rule):**\n- 빌더는 `Runtime\u002FGenerated\u002F`와 `Editor\u002FGenerated\u002F` 디렉토리만 clean+copy한다.\n- 수동 addon 코드는 빌더가 touch하지 않는다 (보존).\n- asmdef, README.md는 **초회 빌더 자동 생성, 이후 수동 관리** (빌더가 기존 파일 덮어쓰기 금지).\n- package.json(상위 com.devian.foundation의)은 수동 관리 (빌더 생성\u002F수정 금지).\n- Generated 코드의 C# namespace는 원래 namespace를 유지:\n  - Domain: `Devian.Domain.{DomainKey}`\n  - Protocol: `Devian.Protocol.{ProtocolGroup}`\n- assembly 이름은 `Devian.Samples.{SampleName}` 규약을 따른다.\n\n---\n\n## 빌드 통합 (Build Integration)\n\n### Builder MUST copy Samples~ (Hard Rule)\n\nBuilder는 **반드시** `Samples~` 폴더를 upm에서 UnityExample\u002FPackages로 복사해야 한다.\n\n- Source에 `Samples~`가 존재하면 Target에도 **반드시** 존재해야 함\n- `copyUpmToTarget()` 함수에서 `Samples~` 복사가 `syncSamplesMetadata()` 호출 **전에** 실행되어야 함\n\n### samples metadata sync\n\n`Samples~` 폴더를 제공하는 패키지는 `package.json`에 `samples` 배열을 선언해야 한다.\nBuilder는 `Samples~`가 존재하고 하위 폴더가 있으면 `samples` 필드를 자동 동기화한다.\n\n**samples 항목 필수 필드:**\n\n| 필드 | 필수 | 설명 |\n|------|------|------|\n| `displayName` | **필수** | Package Manager UI에 표시될 샘플 이름 |\n| `description` | 권장 | 샘플 설명 |\n| `path` | **필수** | `Samples~\u002F...` 상대경로 (폴더명과 대소문자 정확히 일치) |\n\n### Sample Package 상수\n\n샘플 패키지 대상은 `com.devian.foundation` 하나뿐이며, 빌더 내부 상수(`UPM_FOUNDATION`)로 고정한다.\n`{projectConfigJson}`에 `samplePackages` 키는 불필요하며 존재하지 않는다.\n`staticUpmPackages` 키는 금지이며 존재 시 빌드 FAIL.\n\n---\n\n## Disconnect 행동 DoD (Hard DoD)\n\n**Disconnect 후 상태 갱신 필수:**\n\n1. Disconnect 호출 시 **1초 이내**에 `OnClose` 이벤트가 발생해야 한다.\n2. `IsConnected`가 `false`로 바뀌어야 한다.\n\n**Hard FAIL 조건:**\n- OnClose 없이 IsConnected만 false로 우회하면 **FAIL**\n- 1초 후에도 OnClose가 발생하지 않으면 **FAIL**\n- Disconnect는 Close 이벤트를 통해 상태가 갱신되어야 하며, Close 이전에 OnClose 핸들러를 제거하면 **FAIL**\n\n### Packages 반영 확인 (Hard Rule)\n\n- `upm`와 `Packages`의 파일이 다르면 **FAIL** (sync 누락)\n- `Packages\u002F`에서 직접 수정한 경우 **정책 위반**\n\n---\n\n## DoD (Definition of Done)\n\n**Hard (반드시 0 위반)**\n- 샘플 원본이 `framework-cs\u002Fupm\u002F**\u002FSamples~\u002F**`에 존재\n- `package.json.samples[]`에 등록되어 UPM Samples UI에서 노출\n- UnityExample `Packages\u002F**` 미러가 생성\u002F동기화되어 일치\n- Runtime\u002FEditor 경계 위반 없음 (Runtime에서 UnityEditor 사용 금지)\n\n---\n\n## 금지\n\n- `author.name`을 임의로 변경 금지\n- 패키지마다 `unity` 최소버전이 달라지게 만들지 말 것\n- `com.devian.*` 외 패키지의 package.json은 수정 금지\n- 의존 방향 위반 금지 ([02-unity-bundles](..\u002F02-unity-bundles\u002FSKILL.md) §의존 방향 정책 참조)\n- `upm` 외부에서 샘플 소스 작성 금지\n- `UnityExample\u002FPackages\u002F**` 직접 수정 금지 (빌드 출력물)\n- Runtime 코드에 `using UnityEditor` 사용 금지\n- Editor asmdef에 `includePlatforms: []` 사용 금지\n- Close 처리에서 이벤트 unhook을 Close 이전에 수행 금지\n- **GameNetwork 샘플 삭제됨** — Networker\u002FSessionHost는 `Samples~\u002FGameProtocol\u002F` 샘플에서 generated code로 제공\n\n---\n\n## Reference\n\n- Related: `skills\u002Fdevian-unity\u002F02-unity-bundles\u002FSKILL.md`\n- Related: `skills\u002Fdevian\u002F20-domain-common\u002F02-module-policy\u002FSKILL.md`\n- Related: `skills\u002Fdevian\u002F10-module\u002F03-ssot\u002FSKILL.md` (Foundation Package SSOT)\n- Related: `skills\u002Fdevian\u002F80-tools\u002F11-builder\u002F03-ssot\u002FSKILL.md` (Builder SSOT — Sample naming)\n- UPM 소스: `framework-cs\u002Fupm\u002Fcom.devian.foundation\u002FRuntime\u002FModule\u002FNet\u002F`\n",{},"main","8cb5bd877a3a7004867d2f55697cb9e4ff2f1734","skills\u002Fdevian-unity\u002F04-package-policy","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft","Kim Hyong Joon","2026-04-12 18:44:10",{"source":7,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add devwinsoft\u002Fdevian --skill 04-package-policy",{"tool":38,"command":39},"bunx","bunx skills add devwinsoft\u002Fdevian --skill 04-package-policy",{"tool":41,"command":42},"pnpm","pnpm dlx skills add devwinsoft\u002Fdevian --skill 04-package-policy","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian-unity\u002F04-package-policy\u002FSKILL.md",true,[],[47,53,61,69,78,85],{"skillNo":48,"name":49,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":50,"categories":51,"keywords":52,"publishedAt":21},"01M6CBX3K2JJV38ANHVGCAT8A0","devian","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002FSKILL.md",[],[49],{"skillNo":54,"name":55,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":56,"categories":57,"keywords":58,"publishedAt":21},"01M6CBX210BFMM8AMN770J9WY8","90-project-archive","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F90-project-archive\u002FSKILL.md",[],[59,60],"archive","90 project archive",{"skillNo":62,"name":63,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":21},"01M6CBWZSGRR9R3YJZB3177667","30-env-management","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F30-env-management\u002FSKILL.md",[],[67,68],"management","30 env management",{"skillNo":70,"name":71,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":21},"01M6CBWYD3TGWBQV7V35551THF","19-page-push-send","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F19-page-push-send\u002FSKILL.md",[],[75,76,77],"push","page","19 page push send",{"skillNo":79,"name":80,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":21},"01M6CBWWRQ05A7604GHJKTPJTF","18-page-savedata","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F18-page-savedata\u002FSKILL.md",[],[76,84],"18 page savedata",{"skillNo":86,"name":87,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":7,"ownerLogin":8,"ownerAvatarUrl":9,"ownerAccountNo":10,"ownerDisplayName":11,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":88,"categories":89,"keywords":90,"publishedAt":21},"01M6CBWVH4S2VF1V7B2GBTESCT","17-page-deobfuscate","https:\u002F\u002Fgithub.com\u002Fdevwinsoft\u002Fdevian\u002Fblob\u002Fmain\u002Fskills\u002Fdevian\u002F80-tools\u002F20-operation\u002F17-page-deobfuscate\u002FSKILL.md",[],[76,91],"17 page deobfuscate"]