timsquad 3.3.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.ko.md +288 -0
  2. package/README.md +158 -151
  3. package/dist/commands/compile.d.ts +3 -0
  4. package/dist/commands/compile.d.ts.map +1 -0
  5. package/dist/commands/compile.js +170 -0
  6. package/dist/commands/compile.js.map +1 -0
  7. package/dist/commands/daemon.d.ts.map +1 -1
  8. package/dist/commands/daemon.js +95 -5
  9. package/dist/commands/daemon.js.map +1 -1
  10. package/dist/commands/full.js +1 -0
  11. package/dist/commands/full.js.map +1 -1
  12. package/dist/commands/git/pr.js +6 -5
  13. package/dist/commands/git/pr.js.map +1 -1
  14. package/dist/commands/git/release.js +2 -7
  15. package/dist/commands/git/release.js.map +1 -1
  16. package/dist/commands/improve.js +2 -2
  17. package/dist/commands/improve.js.map +1 -1
  18. package/dist/commands/init.d.ts.map +1 -1
  19. package/dist/commands/init.js +12 -3
  20. package/dist/commands/init.js.map +1 -1
  21. package/dist/commands/log.d.ts.map +1 -1
  22. package/dist/commands/log.js +2 -2
  23. package/dist/commands/log.js.map +1 -1
  24. package/dist/commands/metrics.d.ts.map +1 -1
  25. package/dist/commands/metrics.js +6 -2
  26. package/dist/commands/metrics.js.map +1 -1
  27. package/dist/commands/retro.js +8 -8
  28. package/dist/commands/retro.js.map +1 -1
  29. package/dist/commands/session.js +3 -3
  30. package/dist/commands/session.js.map +1 -1
  31. package/dist/commands/skills.d.ts +12 -0
  32. package/dist/commands/skills.d.ts.map +1 -0
  33. package/dist/commands/skills.js +228 -0
  34. package/dist/commands/skills.js.map +1 -0
  35. package/dist/commands/status.js +1 -1
  36. package/dist/commands/status.js.map +1 -1
  37. package/dist/commands/upgrade.d.ts.map +1 -1
  38. package/dist/commands/upgrade.js +23 -1
  39. package/dist/commands/upgrade.js.map +1 -1
  40. package/dist/daemon/entry.js +3 -3
  41. package/dist/daemon/entry.js.map +1 -1
  42. package/dist/daemon/event-queue.d.ts.map +1 -1
  43. package/dist/daemon/event-queue.js +2 -2
  44. package/dist/daemon/event-queue.js.map +1 -1
  45. package/dist/daemon/index.d.ts +4 -2
  46. package/dist/daemon/index.d.ts.map +1 -1
  47. package/dist/daemon/index.js +214 -52
  48. package/dist/daemon/index.js.map +1 -1
  49. package/dist/daemon/jsonl-watcher.d.ts +1 -0
  50. package/dist/daemon/jsonl-watcher.d.ts.map +1 -1
  51. package/dist/daemon/jsonl-watcher.js.map +1 -1
  52. package/dist/daemon/meta-cache.d.ts +1 -0
  53. package/dist/daemon/meta-cache.d.ts.map +1 -1
  54. package/dist/daemon/meta-cache.js +9 -0
  55. package/dist/daemon/meta-cache.js.map +1 -1
  56. package/dist/daemon/session-notes.d.ts +33 -0
  57. package/dist/daemon/session-notes.d.ts.map +1 -0
  58. package/dist/daemon/session-notes.js +74 -0
  59. package/dist/daemon/session-notes.js.map +1 -0
  60. package/dist/daemon/session-state.d.ts +27 -0
  61. package/dist/daemon/session-state.d.ts.map +1 -0
  62. package/dist/daemon/session-state.js +165 -0
  63. package/dist/daemon/session-state.js.map +1 -0
  64. package/dist/daemon/shutdown.d.ts.map +1 -1
  65. package/dist/daemon/shutdown.js +9 -1
  66. package/dist/daemon/shutdown.js.map +1 -1
  67. package/dist/index.js +4 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/lib/agent-generator.d.ts +4 -0
  70. package/dist/lib/agent-generator.d.ts.map +1 -1
  71. package/dist/lib/agent-generator.js +52 -3
  72. package/dist/lib/agent-generator.js.map +1 -1
  73. package/dist/lib/compile-rules.d.ts +66 -0
  74. package/dist/lib/compile-rules.d.ts.map +1 -0
  75. package/dist/lib/compile-rules.js +114 -0
  76. package/dist/lib/compile-rules.js.map +1 -0
  77. package/dist/lib/compiler.d.ts +105 -0
  78. package/dist/lib/compiler.d.ts.map +1 -0
  79. package/dist/lib/compiler.js +368 -0
  80. package/dist/lib/compiler.js.map +1 -0
  81. package/dist/lib/config.d.ts +1 -0
  82. package/dist/lib/config.d.ts.map +1 -1
  83. package/dist/lib/config.js +8 -1
  84. package/dist/lib/config.js.map +1 -1
  85. package/dist/lib/project.d.ts.map +1 -1
  86. package/dist/lib/project.js +8 -3
  87. package/dist/lib/project.js.map +1 -1
  88. package/dist/lib/skill-generator.d.ts.map +1 -1
  89. package/dist/lib/skill-generator.js +22 -1
  90. package/dist/lib/skill-generator.js.map +1 -1
  91. package/dist/lib/template.d.ts.map +1 -1
  92. package/dist/lib/template.js +6 -0
  93. package/dist/lib/template.js.map +1 -1
  94. package/dist/types/config.d.ts +1 -0
  95. package/dist/types/config.d.ts.map +1 -1
  96. package/dist/types/config.js +12 -1
  97. package/dist/types/config.js.map +1 -1
  98. package/dist/types/project.d.ts +1 -1
  99. package/dist/types/project.d.ts.map +1 -1
  100. package/dist/types/project.js +2 -0
  101. package/dist/types/project.js.map +1 -1
  102. package/package.json +4 -4
  103. package/templates/base/agents/base/tsq-architect.md +2 -2
  104. package/templates/base/agents/overlays/domain/mobile/_common.md +13 -0
  105. package/templates/base/knowledge/checklists/plan-quality.md +31 -0
  106. package/templates/base/knowledge/checklists/stability-verification.md +14 -0
  107. package/templates/base/skills/controller/SKILL.md +111 -0
  108. package/templates/base/skills/controller/references/README.md +35 -0
  109. package/templates/base/skills/controller/rules/README.md +18 -0
  110. package/templates/base/skills/mobile/dart/SKILL.md +69 -0
  111. package/templates/base/skills/mobile/dart/rules/async-patterns.md +112 -0
  112. package/templates/base/skills/mobile/dart/rules/code-style.md +96 -0
  113. package/templates/base/skills/mobile/dart/rules/null-safety.md +84 -0
  114. package/templates/base/skills/mobile/dart/rules/type-system.md +111 -0
  115. package/templates/base/skills/mobile/flutter/SKILL.md +89 -0
  116. package/templates/base/skills/mobile/flutter/ci-cd/SKILL.md +82 -0
  117. package/templates/base/skills/mobile/flutter/ci-cd/references/ci-cd-pipeline.md +314 -0
  118. package/templates/base/skills/mobile/flutter/ci-cd/rules/code-signing.md +106 -0
  119. package/templates/base/skills/mobile/flutter/ci-cd/rules/codemagic-setup.md +116 -0
  120. package/templates/base/skills/mobile/flutter/ci-cd/rules/fastlane-setup.md +105 -0
  121. package/templates/base/skills/mobile/flutter/ci-cd/rules/github-actions.md +112 -0
  122. package/templates/base/skills/mobile/flutter/ci-cd/rules/store-deployment.md +106 -0
  123. package/templates/base/skills/mobile/flutter/ci-cd/rules/versioning.md +107 -0
  124. package/templates/base/skills/mobile/flutter/i18n/SKILL.md +78 -0
  125. package/templates/base/skills/mobile/flutter/i18n/references/i18n-architecture.md +225 -0
  126. package/templates/base/skills/mobile/flutter/i18n/rules/arb-files.md +182 -0
  127. package/templates/base/skills/mobile/flutter/i18n/rules/locale-switching.md +226 -0
  128. package/templates/base/skills/mobile/flutter/i18n/rules/localization-setup.md +137 -0
  129. package/templates/base/skills/mobile/flutter/i18n/rules/plural-gender.md +159 -0
  130. package/templates/base/skills/mobile/flutter/i18n/rules/text-direction.md +199 -0
  131. package/templates/base/skills/mobile/flutter/monitoring/SKILL.md +81 -0
  132. package/templates/base/skills/mobile/flutter/monitoring/references/monitoring-architecture.md +269 -0
  133. package/templates/base/skills/mobile/flutter/monitoring/rules/analytics.md +227 -0
  134. package/templates/base/skills/mobile/flutter/monitoring/rules/crashlytics-setup.md +195 -0
  135. package/templates/base/skills/mobile/flutter/monitoring/rules/logging.md +258 -0
  136. package/templates/base/skills/mobile/flutter/monitoring/rules/performance-monitoring.md +248 -0
  137. package/templates/base/skills/mobile/flutter/monitoring/rules/sentry-integration.md +249 -0
  138. package/templates/base/skills/mobile/flutter/networking/SKILL.md +88 -0
  139. package/templates/base/skills/mobile/flutter/networking/references/api-client-architecture.md +305 -0
  140. package/templates/base/skills/mobile/flutter/networking/rules/caching.md +212 -0
  141. package/templates/base/skills/mobile/flutter/networking/rules/connectivity.md +213 -0
  142. package/templates/base/skills/mobile/flutter/networking/rules/dio-setup.md +159 -0
  143. package/templates/base/skills/mobile/flutter/networking/rules/error-handling.md +209 -0
  144. package/templates/base/skills/mobile/flutter/networking/rules/interceptors.md +205 -0
  145. package/templates/base/skills/mobile/flutter/networking/rules/retrofit-patterns.md +194 -0
  146. package/templates/base/skills/mobile/flutter/push-notifications/SKILL.md +87 -0
  147. package/templates/base/skills/mobile/flutter/push-notifications/references/notification-architecture.md +340 -0
  148. package/templates/base/skills/mobile/flutter/push-notifications/references/platform-setup.md +286 -0
  149. package/templates/base/skills/mobile/flutter/push-notifications/rules/background-processing.md +308 -0
  150. package/templates/base/skills/mobile/flutter/push-notifications/rules/deep-linking.md +217 -0
  151. package/templates/base/skills/mobile/flutter/push-notifications/rules/fcm-setup.md +164 -0
  152. package/templates/base/skills/mobile/flutter/push-notifications/rules/local-notifications.md +262 -0
  153. package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-handling.md +210 -0
  154. package/templates/base/skills/mobile/flutter/push-notifications/rules/notification-permissions.md +246 -0
  155. package/templates/base/skills/mobile/flutter/push-notifications/rules/rich-notifications.md +320 -0
  156. package/templates/base/skills/mobile/flutter/references/freezed-patterns.md +162 -0
  157. package/templates/base/skills/mobile/flutter/references/project-structure.md +170 -0
  158. package/templates/base/skills/mobile/flutter/rules/animations.md +112 -0
  159. package/templates/base/skills/mobile/flutter/rules/architecture.md +121 -0
  160. package/templates/base/skills/mobile/flutter/rules/navigation-routing.md +117 -0
  161. package/templates/base/skills/mobile/flutter/rules/performance.md +112 -0
  162. package/templates/base/skills/mobile/flutter/rules/platform-adaptive.md +126 -0
  163. package/templates/base/skills/mobile/flutter/rules/state-management.md +110 -0
  164. package/templates/base/skills/mobile/flutter/rules/testing.md +131 -0
  165. package/templates/base/skills/mobile/flutter/rules/widget-conventions.md +122 -0
  166. package/templates/base/skills/mobile/flutter/security/SKILL.md +86 -0
  167. package/templates/base/skills/mobile/flutter/security/references/mobile-security-checklist.md +168 -0
  168. package/templates/base/skills/mobile/flutter/security/rules/api-key-protection.md +206 -0
  169. package/templates/base/skills/mobile/flutter/security/rules/authentication.md +248 -0
  170. package/templates/base/skills/mobile/flutter/security/rules/data-protection.md +271 -0
  171. package/templates/base/skills/mobile/flutter/security/rules/obfuscation.md +213 -0
  172. package/templates/base/skills/mobile/flutter/security/rules/secure-storage.md +171 -0
  173. package/templates/base/skills/mobile/flutter/security/rules/ssl-pinning.md +197 -0
  174. package/templates/base/skills/stability-verification/SKILL.md +64 -0
  175. package/templates/base/skills/stability-verification/references/release-checklist.md +34 -0
  176. package/templates/base/skills/stability-verification/references/security-fix-patterns.md +112 -0
  177. package/templates/base/skills/stability-verification/rules/verification-layers.md +67 -0
  178. package/templates/base/skills/stability-verification/rules/verification-workflow.md +69 -0
  179. package/templates/base/skills/stability-verification/scripts/verify.sh +294 -0
  180. package/templates/platforms/claude-code/CLAUDE.md.template +25 -0
  181. package/templates/platforms/claude-code/rules/build-gate.md +28 -0
  182. package/templates/platforms/claude-code/rules/completion-verification.md +30 -0
  183. package/templates/platforms/claude-code/rules/context-monitor.md +23 -0
  184. package/templates/platforms/claude-code/rules/plan-review.md +45 -0
  185. package/templates/platforms/claude-code/rules/quality-guards.md +43 -0
  186. package/templates/platforms/claude-code/rules/session-notes.md +18 -0
  187. package/templates/platforms/claude-code/rules/skill-suggest.md +27 -0
  188. package/templates/platforms/claude-code/scripts/build-gate.sh +73 -0
  189. package/templates/platforms/claude-code/scripts/completion-guard.sh +93 -0
  190. package/templates/platforms/claude-code/scripts/phase-guard.sh +79 -0
  191. package/templates/platforms/claude-code/scripts/safe-guard.sh +83 -0
  192. package/templates/platforms/claude-code/scripts/skill-rules.json +85 -0
  193. package/templates/platforms/claude-code/scripts/skill-suggest.sh +105 -0
  194. package/templates/platforms/claude-code/settings.json +111 -3
  195. package/templates/project-types/mobile-app/config.yaml +123 -0
  196. package/templates/project-types/mobile-app/process/workflow.xml +191 -0
@@ -0,0 +1,112 @@
1
+ ---
2
+ title: GitHub Actions
3
+ impact: HIGH
4
+ impactDescription: "CI 없음 → 릴리스 품질 불안정, GitHub Actions → 코드 변경마다 자동 검증"
5
+ tags: github-actions, ci, workflow, flutter-action, cache, artifact
6
+ ---
7
+
8
+ ## GitHub Actions
9
+
10
+ **Impact: HIGH (CI 없음 → 릴리스 품질 불안정, GitHub Actions → 코드 변경마다 자동 검증)**
11
+
12
+ Flutter 빌드 워크플로우, flutter-action, 테스트-빌드-업로드 파이프라인, 캐시.
13
+
14
+ ### 테스트 워크플로우
15
+
16
+ **Incorrect (Flutter 수동 설치, 캐시 없음):**
17
+ ```yaml
18
+ on: push
19
+ jobs:
20
+ test:
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - run: git clone https://github.com/flutter/flutter.git
24
+ - run: flutter test # 매번 전체 다운로드 → 느림
25
+ ```
26
+
27
+ **Correct (flutter-action + 캐시):**
28
+ ```yaml
29
+ # .github/workflows/test.yml
30
+ name: Test & Analyze
31
+ on:
32
+ pull_request:
33
+ branches: [main, develop]
34
+ concurrency:
35
+ group: ${{ github.workflow }}-${{ github.ref }}
36
+ cancel-in-progress: true
37
+ jobs:
38
+ test:
39
+ runs-on: ubuntu-latest
40
+ timeout-minutes: 15
41
+ steps:
42
+ - uses: actions/checkout@v4
43
+ - uses: subosito/flutter-action@v2
44
+ with:
45
+ flutter-version: "3.27.0"
46
+ cache: true
47
+ - uses: actions/cache@v4
48
+ with:
49
+ path: ${{ env.PUB_CACHE }}
50
+ key: pub-${{ runner.os }}-${{ hashFiles('**/pubspec.lock') }}
51
+ - run: flutter pub get
52
+ - run: flutter analyze --no-fatal-infos
53
+ - run: flutter test --coverage
54
+ ```
55
+
56
+ ### 릴리스 워크플로우 (iOS + Android)
57
+
58
+ ```yaml
59
+ # .github/workflows/ios-release.yml — 태그 푸시 트리거
60
+ name: iOS Release
61
+ on: { push: { tags: ["v*"] } }
62
+ jobs:
63
+ ios-build:
64
+ runs-on: macos-latest
65
+ timeout-minutes: 45
66
+ steps:
67
+ - uses: actions/checkout@v4
68
+ - uses: subosito/flutter-action@v2
69
+ with: { flutter-version: "3.27.0", cache: true }
70
+ - uses: ruby/setup-ruby@v1
71
+ with: { ruby-version: "3.2", bundler-cache: true, working-directory: ios }
72
+ - run: |
73
+ VERSION=${GITHUB_REF#refs/tags/v}
74
+ flutter build ipa --release --build-name=$VERSION --build-number=$GITHUB_RUN_NUMBER
75
+ cd ios && bundle exec fastlane beta
76
+ env:
77
+ MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }}
78
+ MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
79
+ ```
80
+
81
+ ```yaml
82
+ # .github/workflows/android-release.yml
83
+ name: Android Release
84
+ on: { push: { tags: ["v*"] } }
85
+ jobs:
86
+ android-build:
87
+ runs-on: ubuntu-latest
88
+ timeout-minutes: 30
89
+ steps:
90
+ - uses: actions/checkout@v4
91
+ - uses: actions/setup-java@v4
92
+ with: { distribution: "temurin", java-version: "17" }
93
+ - uses: subosito/flutter-action@v2
94
+ with: { flutter-version: "3.27.0", cache: true }
95
+ - run: echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/release.keystore
96
+ - run: flutter build appbundle --release --build-number=${{ github.run_number }}
97
+ - uses: r0adkll/upload-google-play@v1
98
+ with:
99
+ serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT }}
100
+ packageName: com.yourapp.id
101
+ releaseFiles: build/app/outputs/bundle/release/app-release.aab
102
+ track: internal
103
+ ```
104
+
105
+ ### 규칙
106
+
107
+ - `subosito/flutter-action@v2` — Flutter SDK 설치 + `cache: true`
108
+ - pub 캐시 — `actions/cache@v4` + `pubspec.lock` 해시 키
109
+ - `concurrency` — 동일 PR 중복 빌드 취소
110
+ - `timeout-minutes` — 테스트 15분, iOS 45분, Android 30분
111
+ - 태그 `v*` 트리거 — 릴리스 빌드, PR → 테스트만
112
+ - 시크릿 — `${{ secrets.* }}` 로 주입, 하드코딩 금지
@@ -0,0 +1,106 @@
1
+ ---
2
+ title: Store Deployment
3
+ impact: HIGH
4
+ impactDescription: "배포 실수 → 심사 거절/사용자 불만, 체계적 배포 → 안정적 출시"
5
+ tags: app-store, play-store, testflight, deployment, rollout, metadata
6
+ ---
7
+
8
+ ## Store Deployment
9
+
10
+ **Impact: HIGH (배포 실수 → 심사 거절/사용자 불만, 체계적 배포 → 안정적 출시)**
11
+
12
+ TestFlight 업로드, Play Store 트랙 관리, 메타데이터, 단계적 출시 전략.
13
+
14
+ ### TestFlight (iOS) 배포
15
+
16
+ **Incorrect (Xcode에서 수동 업로드):**
17
+ ```
18
+ Xcode > Archive > Distribute App → 수동 반복, 재현 불가
19
+ ```
20
+
21
+ **Correct (Fastlane + API Key):**
22
+ ```ruby
23
+ lane :beta do
24
+ api_key = app_store_connect_api_key(
25
+ key_id: ENV["ASC_KEY_ID"],
26
+ issuer_id: ENV["ASC_ISSUER_ID"],
27
+ key_filepath: ENV["ASC_KEY_PATH"],
28
+ )
29
+ build_app(workspace: "Runner.xcworkspace", scheme: "Runner",
30
+ export_method: "app-store")
31
+ upload_to_testflight(
32
+ api_key: api_key,
33
+ skip_waiting_for_build_processing: true,
34
+ groups: ["Internal Testers"],
35
+ changelog: ENV["RELEASE_NOTES"] || "Bug fixes and improvements",
36
+ )
37
+ end
38
+ ```
39
+
40
+ ### Play Store 트랙 전략
41
+
42
+ **Incorrect (바로 production):**
43
+ ```ruby
44
+ supply(track: "production", aab: "app-release.aab")
45
+ # → 테스트 없이 전체 배포 → 크래시 위험
46
+ ```
47
+
48
+ **Correct (단계적 트랙 승격):**
49
+ ```ruby
50
+ lane :internal do
51
+ supply(track: "internal", aab: "app-release.aab",
52
+ json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"])
53
+ end
54
+
55
+ lane :promote_production do |options|
56
+ supply(track: "internal", track_promote_to: "production",
57
+ rollout: options[:rollout] || "0.01",
58
+ json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"])
59
+ end
60
+
61
+ lane :increase_rollout do |options|
62
+ supply(track: "production", rollout: options[:rollout],
63
+ json_key: ENV["GOOGLE_PLAY_JSON_KEY_PATH"])
64
+ end
65
+ ```
66
+
67
+ ### 단계적 출시 전략
68
+
69
+ ```
70
+ Day 0: internal (팀) → 크래시율/기능 확인
71
+ Day 1: closed testing → 소규모 외부 테스터
72
+ Day 3: production 1% → 크래시 모니터링
73
+ Day 5: production 5% → ANR 비율 확인
74
+ Day 7: production 20% → 사용자 피드백
75
+ Day 10: production 50%
76
+ Day 14: production 100%
77
+
78
+ 중단 기준: 크래시율 > 1%, ANR > 0.5%, 평점 급락
79
+ ```
80
+
81
+ ### 메타데이터 관리
82
+
83
+ ```
84
+ fastlane/metadata/
85
+ ├── android/en-US/ # title.txt, short_description.txt, full_description.txt
86
+ ├── android/ko/
87
+ ├── ios/en-US/ # name.txt, subtitle.txt, description.txt, keywords.txt
88
+ ├── ios/ko/
89
+ └── screenshots/en-US/ # iPhone6.5/, iPhone5.5/, iPad12.9/
90
+ ```
91
+
92
+ ```ruby
93
+ lane :update_metadata do
94
+ deliver(skip_binary_upload: true, skip_screenshots: false,
95
+ overwrite_screenshots: true, api_key_path: "fastlane/api_key.json")
96
+ end
97
+ ```
98
+
99
+ ### 규칙
100
+
101
+ - TestFlight 자동 업로드 — `upload_to_testflight` + API Key, 수동 금지
102
+ - Play Store 트랙 순서 — internal → closed → open → production
103
+ - 단계적 출시 — 1%부터 시작, 크래시율 모니터링 후 확대
104
+ - 메타데이터 코드 관리 — `fastlane/metadata/` 텍스트 파일
105
+ - 릴리스 노트 — CHANGELOG에서 추출, 수동 작성 금지
106
+ - 크래시율 1% 초과 → 즉시 rollout 중단
@@ -0,0 +1,107 @@
1
+ ---
2
+ title: Versioning
3
+ impact: MEDIUM
4
+ impactDescription: "버전 관리 부재 → 빌드 추적 불가, 체계적 버전 → 출시 이력 완전 추적"
5
+ tags: versioning, semver, build-number, changelog, git-tag, pubspec
6
+ ---
7
+
8
+ ## Versioning
9
+
10
+ **Impact: MEDIUM (버전 관리 부재 → 빌드 추적 불가, 체계적 버전 → 출시 이력 완전 추적)**
11
+
12
+ pubspec.yaml 시맨틱 버저닝, 빌드 넘버 자동 증가, CHANGELOG 생성, git 태그 연동.
13
+
14
+ ### pubspec.yaml 버전 형식
15
+
16
+ **Incorrect (빌드 넘버 누락):**
17
+ ```yaml
18
+ version: 1.0.0 # → 스토어 업로드 시 구분 불가, 수동 관리 실수
19
+ ```
20
+
21
+ **Correct (시맨틱 버전 + 빌드 넘버):**
22
+ ```yaml
23
+ version: 1.2.3+45
24
+ # major(1) — 호환 불가 변경
25
+ # minor(2) — 새 기능 (하위 호환)
26
+ # patch(3) — 버그 수정
27
+ # build(45) — CI 빌드 넘버 (스토어 구분용, 항상 증가)
28
+ ```
29
+
30
+ ### 빌드 넘버 자동 증가
31
+
32
+ ```bash
33
+ # 전략 1: CI 빌드 넘버 (권장)
34
+ flutter build appbundle --build-number=${{ github.run_number }} # GitHub Actions
35
+ flutter build ipa --build-number=$PROJECT_BUILD_NUMBER # Codemagic
36
+
37
+ # 전략 2: 타임스탬프 (YYYYMMDDNN)
38
+ BUILD_NUMBER=$(date +%Y%m%d)$(printf "%02d" $BUILD_COUNT)
39
+
40
+ # 전략 3: Git 커밋 카운트
41
+ BUILD_NUMBER=$(git rev-list --count HEAD)
42
+ ```
43
+
44
+ ### CI에서 버전 오버라이드
45
+
46
+ ```bash
47
+ TAG=${GITHUB_REF#refs/tags/v} # v1.2.3 → 1.2.3
48
+ flutter build ipa --release \
49
+ --build-name=$TAG \
50
+ --build-number=${{ github.run_number }}
51
+ ```
52
+
53
+ ### 런타임 버전 접근
54
+
55
+ ```dart
56
+ import 'package:package_info_plus/package_info_plus.dart';
57
+
58
+ class AppVersion {
59
+ static Future<String> getFullVersion() async {
60
+ final info = await PackageInfo.fromPlatform();
61
+ return '${info.version}+${info.buildNumber}'; // "1.2.3+45"
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### CHANGELOG 자동 생성
67
+
68
+ ```yaml
69
+ # .github/workflows/changelog.yml (태그 푸시 시)
70
+ - uses: orhun/git-cliff-action@v3
71
+ with:
72
+ config: cliff.toml
73
+ args: --verbose
74
+ env:
75
+ OUTPUT: CHANGELOG.md
76
+ - uses: softprops/action-gh-release@v2
77
+ with:
78
+ body_path: CHANGELOG.md
79
+ ```
80
+
81
+ ### Git 태그 전략
82
+
83
+ ```bash
84
+ git tag -a v1.2.3 -m "Release v1.2.3"
85
+ git push origin v1.2.3
86
+
87
+ # 태그 규칙:
88
+ # v1.2.3 → production
89
+ # v1.2.3-rc1 → release candidate
90
+ # v1.2.3-beta.1 → beta (TestFlight/Internal)
91
+ ```
92
+
93
+ ### 플랫폼별 주의
94
+
95
+ ```
96
+ iOS: CFBundleVersion = build-number, 동일 버전 재업로드 불가
97
+ Android: versionCode = 정수, 감소 불가 (한번 올리면 되돌릴 수 없음)
98
+ ```
99
+
100
+ ### 규칙
101
+
102
+ - `version: major.minor.patch+buildNumber` 형식 유지
103
+ - 빌드 넘버는 CI에서 자동 증가 — 수동 관리 금지
104
+ - `--build-name` + `--build-number` CI 오버라이드
105
+ - git 태그 `v*` — 릴리스와 1:1 매핑
106
+ - CHANGELOG 자동 생성 — conventional commits 기반
107
+ - 빌드 넘버 절대 감소 불가 — 스토어 거부
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: i18n
3
+ description: |
4
+ Flutter 국제화(i18n) 가이드라인.
5
+ flutter_localizations, intl, ARB 파일 관리,
6
+ RTL 레이아웃, 복수형/성별 처리, 런타임 로캘 전환.
7
+ version: "1.0.0"
8
+ tags: [flutter, i18n, l10n, localization, arb, intl, rtl]
9
+ user-invocable: false
10
+ ---
11
+
12
+ # Internationalization (i18n) & Localization
13
+
14
+ Flutter 다국어 지원 통합 가이드.
15
+ ARB 파일 기반 번역 관리, ICU MessageFormat, RTL 대응, 런타임 로캘 전환.
16
+
17
+ ## Philosophy
18
+
19
+ - 텍스트는 코드에 없다 — 모든 사용자 노출 문자열은 ARB 파일에
20
+ - 로캘은 상태 — Riverpod provider로 관리, SharedPreferences로 영속화
21
+ - RTL은 기본 — Directionality 위젯 활용, 하드코딩된 padding/margin 금지
22
+ - 번역은 프로세스 — 개발자 → 번역가 → 검수, CI에서 누락 키 자동 감지
23
+
24
+ ## Resources
25
+
26
+ 5개 규칙 + 1개 참조. i18n 파이프라인 전체를 커버.
27
+
28
+ | Priority | Type | Resource | Description |
29
+ |----------|------|----------|-------------|
30
+ | CRITICAL | rule | [localization-setup](rules/localization-setup.md) | flutter_localizations, intl, l10n.yaml, pubspec generate |
31
+ | CRITICAL | rule | [arb-files](rules/arb-files.md) | ARB 파일 구조, @placeholder, 네이밍 컨벤션, gen-l10n |
32
+ | HIGH | rule | [text-direction](rules/text-direction.md) | RTL 대응, EdgeInsetsDirectional, AlignmentDirectional |
33
+ | HIGH | rule | [plural-gender](rules/plural-gender.md) | ICU MessageFormat, plural, select, ordinal |
34
+ | MEDIUM | rule | [locale-switching](rules/locale-switching.md) | LocaleNotifier, SharedPreferences, 런타임 전환 |
35
+ | — | ref | [i18n-architecture](references/i18n-architecture.md) | 디렉토리 구조, 번역 워크플로우, CI 검증 |
36
+
37
+ ## Quick Rules
38
+
39
+ ### 설정
40
+ - `pubspec.yaml` 에 `generate: true` + `flutter_localizations`, `intl` 의존성
41
+ - `l10n.yaml` 로 ARB 디렉토리, 출력 클래스, 기본 로캘 지정
42
+ - `MaterialApp.localizationsDelegates` + `supportedLocales` 필수 설정
43
+
44
+ ### ARB 파일
45
+ - `app_en.arb` 가 기본 (template ARB), `app_ko.arb` 등 로캘별 추가
46
+ - 키 네이밍: `featureName_context` (예: `matchDetail_inviteButton`)
47
+ - `@placeholder` 메타데이터로 동적 값 타입 명시
48
+ - `flutter gen-l10n` 으로 자동 생성 (`AppLocalizations` 클래스)
49
+
50
+ ### RTL 대응
51
+ - `EdgeInsetsDirectional.only(start: 16)` (left/right 대신 start/end)
52
+ - `AlignmentDirectional.centerStart` (centerLeft 대신)
53
+ - 아이콘 미러링: `Directionality` 감지 후 조건부 Transform
54
+
55
+ ### 복수형/성별
56
+ - ICU `{count, plural, =0{no items} =1{1 item} other{{count} items}}`
57
+ - `{gender, select, male{his} female{her} other{their}}`
58
+ - ARB 파일에 직접 ICU 구문 작성, intl이 자동 파싱
59
+
60
+ ### 로캘 전환
61
+ - `LocaleNotifier` (Riverpod StateNotifier) → 현재 로캘 관리
62
+ - `SharedPreferences` 로 선택 로캘 영속화
63
+ - 앱 재시작 없이 `MaterialApp.locale` 변경으로 즉시 반영
64
+
65
+ ## Checklist
66
+
67
+ | Priority | Item |
68
+ |----------|------|
69
+ | CRITICAL | `pubspec.yaml` 에 `generate: true` 설정 |
70
+ | CRITICAL | `l10n.yaml` 생성 (arb-dir, template-arb-file, output-localization-file) |
71
+ | CRITICAL | `MaterialApp.localizationsDelegates` 3종 등록 |
72
+ | CRITICAL | 모든 사용자 노출 문자열이 ARB 파일에 존재 |
73
+ | HIGH | `@placeholder` 메타데이터 완전성 (타입, 예시, 설명) |
74
+ | HIGH | RTL 레이아웃에서 Directional 위젯 사용 |
75
+ | HIGH | 복수형/성별 표현이 ICU MessageFormat 사용 |
76
+ | MEDIUM | SharedPreferences 로캘 영속화 |
77
+ | MEDIUM | CI에서 누락 키 자동 감지 |
78
+ | MEDIUM | 번역 워크플로우 문서화 (개발자 → 번역가 → 검수) |
@@ -0,0 +1,225 @@
1
+ ---
2
+ title: i18n Architecture & Translation Workflow
3
+ category: reference
4
+ source: internal
5
+ tags: architecture, directory, workflow, ci, missing-keys, translation
6
+ ---
7
+
8
+ # i18n Architecture & Translation Workflow
9
+
10
+ i18n 서비스 아키텍처. 디렉토리 구조, 번역 워크플로우, CI 자동 검증, 누락 키 감지.
11
+
12
+ ## Key Concepts
13
+
14
+ - **ARB 중심**: 모든 번역의 원본은 ARB 파일 (코드에 문자열 하드코딩 금지)
15
+ - **코드 생성**: `flutter gen-l10n` → 타입 안전한 `AppLocalizations` 클래스 자동 생성
16
+ - **CI 검증**: 빌드 파이프라인에서 누락 키, 미사용 키, 포맷 오류 자동 감지
17
+ - **번역 프로세스**: 개발자 (키 추가) → 번역가 (번역) → 검수 (QA) → 머지
18
+
19
+ ## Directory Structure
20
+
21
+ ```
22
+ lib/
23
+ ├── l10n/
24
+ │ ├── app_en.arb # 기본 (template) — 모든 키 + 메타데이터
25
+ │ ├── app_ko.arb # 한국어
26
+ │ ├── app_ms.arb # 말레이어
27
+ │ ├── app_id.arb # 인도네시아어
28
+ │ └── app_zh.arb # 중국어 (간체)
29
+
30
+ ├── core/
31
+ │ └── l10n/
32
+ │ ├── locale_notifier.dart # LocaleNotifier (Riverpod)
33
+ │ ├── app_locale.dart # AppLocale enum (지원 로캘 목록)
34
+ │ ├── l10n_extension.dart # BuildContext.l10n extension
35
+ │ └── locale_observer.dart # 시스템 로캘 변경 감지
36
+
37
+ ├── features/
38
+ │ └── settings/
39
+ │ └── presentation/
40
+ │ └── screens/
41
+ │ └── language_settings_screen.dart # 언어 설정 UI
42
+
43
+ └── .dart_tool/
44
+ └── flutter_gen/
45
+ └── gen_l10n/ # 자동 생성 (커밋 X)
46
+ ├── app_localizations.dart
47
+ ├── app_localizations_en.dart
48
+ ├── app_localizations_ko.dart
49
+ └── ...
50
+ ```
51
+
52
+ ## Translation Workflow
53
+
54
+ ```
55
+ ┌──────────────────────────────────────────────────────────┐
56
+ │ 번역 워크플로우 │
57
+ ├──────────┬────────────────┬──────────────┬───────────────┤
58
+ │ 1. 개발자 │ 2. 번역가 │ 3. 검수 │ 4. 머지 │
59
+ ├──────────┼────────────────┼──────────────┼───────────────┤
60
+ │ app_en.arb│ app_ko.arb │ 화면 확인 │ PR 승인 │
61
+ │ 키 추가 │ app_ms.arb │ 문맥 확인 │ CI 통과 │
62
+ │ @메타데이터│ app_id.arb │ 길이 확인 │ 머지 │
63
+ │ 설명 작성 │ 번역 작성 │ RTL 확인 │ 배포 │
64
+ ├──────────┼────────────────┼──────────────┼───────────────┤
65
+ │ PR 생성 │ 번역 PR 생성 │ 리뷰 코멘트 │ gen-l10n 실행 │
66
+ └──────────┴────────────────┴──────────────┴───────────────┘
67
+ ```
68
+
69
+ ### 단계별 상세
70
+
71
+ ```
72
+ 1. 개발자 (키 추가)
73
+ - app_en.arb에 새 키 + @메타데이터 추가
74
+ - description에 화면 위치, 용도, 맥락 설명
75
+ - placeholder에 type, example 명시
76
+ - 스크린샷/화면 위치 정보 첨부 (번역가 맥락 전달)
77
+
78
+ 2. 번역가 (번역)
79
+ - 각 로캘 ARB 파일에 번역 추가
80
+ - ICU 복수형/성별 규칙 적용 (언어별)
81
+ - placeholder 위치 조정 (언어 어순에 맞게)
82
+
83
+ 3. 검수 (QA)
84
+ - 실제 화면에서 번역 확인 (텍스트 잘림, 줄바꿈)
85
+ - RTL 레이아웃 확인 (해당 시)
86
+ - 복수형/성별 변형 모두 확인
87
+ - 문화적 적절성 확인
88
+
89
+ 4. 머지
90
+ - CI 자동 검증 통과 확인
91
+ - flutter gen-l10n 빌드 성공 확인
92
+ - 머지 후 릴리스 포함
93
+ ```
94
+
95
+ ## CI Automated Verification
96
+
97
+ ### 누락 키 감지 스크립트
98
+
99
+ ```bash
100
+ #!/bin/bash
101
+ # scripts/check_l10n.sh — CI에서 실행
102
+
103
+ set -e
104
+
105
+ echo "=== i18n Key Verification ==="
106
+
107
+ # 1. gen-l10n 빌드 테스트
108
+ flutter gen-l10n
109
+ echo "✓ gen-l10n succeeded"
110
+
111
+ # 2. 누락 키 체크 (template ARB 기준)
112
+ TEMPLATE="lib/l10n/app_en.arb"
113
+ ERRORS=0
114
+
115
+ for ARB in lib/l10n/app_*.arb; do
116
+ if [ "$ARB" = "$TEMPLATE" ]; then continue; fi
117
+
118
+ LOCALE=$(basename "$ARB" .arb | sed 's/app_//')
119
+
120
+ # template의 비-메타 키 추출
121
+ TEMPLATE_KEYS=$(grep -oP '^\s*"(?!@|@@)\K[^"]+' "$TEMPLATE" | sort)
122
+ LOCALE_KEYS=$(grep -oP '^\s*"(?!@|@@)\K[^"]+' "$ARB" | sort)
123
+
124
+ # 누락 키 찾기
125
+ MISSING=$(comm -23 <(echo "$TEMPLATE_KEYS") <(echo "$LOCALE_KEYS"))
126
+ if [ -n "$MISSING" ]; then
127
+ echo "✗ $LOCALE: Missing keys:"
128
+ echo "$MISSING" | sed 's/^/ /'
129
+ ERRORS=$((ERRORS + 1))
130
+ else
131
+ echo "✓ $LOCALE: All keys present"
132
+ fi
133
+ done
134
+
135
+ if [ $ERRORS -gt 0 ]; then
136
+ echo "FAIL: $ERRORS locale(s) have missing keys"
137
+ exit 1
138
+ fi
139
+
140
+ echo "=== All i18n checks passed ==="
141
+ ```
142
+
143
+ ### 미사용 키 감지
144
+
145
+ ```bash
146
+ #!/bin/bash
147
+ # scripts/check_unused_l10n.sh
148
+
149
+ TEMPLATE="lib/l10n/app_en.arb"
150
+ UNUSED=0
151
+
152
+ # template의 키 목록 추출
153
+ KEYS=$(grep -oP '^\s*"(?!@|@@)\K[^"]+' "$TEMPLATE")
154
+
155
+ for KEY in $KEYS; do
156
+ # Dart 코드에서 사용 여부 확인 (.l10n.$KEY 또는 l10n.$KEY)
157
+ if ! grep -rq "\.$KEY" lib/ --include="*.dart" 2>/dev/null; then
158
+ echo "⚠ Potentially unused: $KEY"
159
+ UNUSED=$((UNUSED + 1))
160
+ fi
161
+ done
162
+
163
+ if [ $UNUSED -gt 0 ]; then
164
+ echo "WARNING: $UNUSED potentially unused key(s)"
165
+ fi
166
+ ```
167
+
168
+ ## ARB Key Organization
169
+
170
+ ```json
171
+ // 키 그룹화 전략 (featureName_ 접두사로 자연 정렬)
172
+ {
173
+ "@@locale": "en",
174
+
175
+ // === Common (공통) ===
176
+ "common_cancelButton": "Cancel",
177
+ "common_confirmButton": "Confirm",
178
+ "common_deleteButton": "Delete",
179
+ "common_loadingMessage": "Loading...",
180
+ "common_retryButton": "Retry",
181
+
182
+ // === Error (에러) ===
183
+ "error_networkTimeout": "Network timeout. Please try again.",
184
+ "error_serverError": "Server error. Please try later.",
185
+ "error_unauthorized": "Please log in again.",
186
+
187
+ // === Match (매치) ===
188
+ "matchDetail_inviteButton": "Invite to Match",
189
+ "matchDetail_playerCount": "{count, plural, =0{No players} =1{1 player} other{{count} players}}",
190
+ "matchList_emptyState": "No matches available",
191
+ "matchList_title": "Available Matches",
192
+
193
+ // === Settings (설정) ===
194
+ "settings_languageTitle": "Language",
195
+ "settings_systemLanguage": "System Language"
196
+ }
197
+ ```
198
+
199
+ ## Common Pitfalls
200
+
201
+ 1. **gen-l10n 미실행**: ARB 수정 후 코드 생성 안 하면 IDE 자동완성 미반영
202
+ 2. **@@locale 누락**: ARB 파일에 로캘 코드 없으면 파일명에서 유추 (명시 권장)
203
+ 3. **ICU 구문 오류**: 중괄호 불일치, other 누락 → gen-l10n 빌드 실패
204
+ 4. **텍스트 길이**: 독일어 등 긴 번역 → UI 레이아웃 깨짐 (Expanded/Flexible 사용)
205
+ 5. **날짜/숫자 포맷**: ARB placeholder format 미지정 → 로캘별 포맷 미적용
206
+ 6. **컨텍스트 없는 description**: 번역가가 맥락 모르면 오역 → 화면 위치/용도 필수
207
+ 7. **하드코딩된 문자열**: 로그, 에러 메시지도 ARB로 (사용자 노출 가능성)
208
+ 8. **synthetic-package 이해**: `.dart_tool/` 에 생성 → `.gitignore` 에 이미 포함 (커밋 X)
209
+
210
+ ## Examples
211
+
212
+ ### 최소 구현 체크리스트
213
+
214
+ ```
215
+ [ ] pubspec.yaml: flutter_localizations + intl + generate: true
216
+ [ ] l10n.yaml: arb-dir, template-arb-file, output-localization-file
217
+ [ ] lib/l10n/app_en.arb: 기본 키 + @메타데이터
218
+ [ ] lib/l10n/app_ko.arb (등): 번역 ARB
219
+ [ ] MaterialApp: localizationsDelegates (4종) + supportedLocales
220
+ [ ] core/l10n/: LocaleNotifier + AppLocale enum
221
+ [ ] main.dart: SharedPreferences 초기화 + ProviderScope override
222
+ [ ] 설정 화면: 언어 선택 UI
223
+ [ ] CI: 누락 키 검증 스크립트
224
+ [ ] 위젯 테스트: RTL 레이아웃 확인
225
+ ```