@yuaone/core 0.3.2 → 0.4.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 (129) hide show
  1. package/dist/agent-loop.d.ts +62 -0
  2. package/dist/agent-loop.d.ts.map +1 -1
  3. package/dist/agent-loop.js +705 -18
  4. package/dist/agent-loop.js.map +1 -1
  5. package/dist/background-agent.d.ts +110 -0
  6. package/dist/background-agent.d.ts.map +1 -0
  7. package/dist/background-agent.js +255 -0
  8. package/dist/background-agent.js.map +1 -0
  9. package/dist/coding-standards.d.ts +45 -0
  10. package/dist/coding-standards.d.ts.map +1 -0
  11. package/dist/coding-standards.js +1152 -0
  12. package/dist/coding-standards.js.map +1 -0
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +2 -6
  15. package/dist/constants.js.map +1 -1
  16. package/dist/context-manager.d.ts +6 -0
  17. package/dist/context-manager.d.ts.map +1 -1
  18. package/dist/context-manager.js +23 -4
  19. package/dist/context-manager.js.map +1 -1
  20. package/dist/index.d.ts +28 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +26 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/llm-client.d.ts +8 -3
  25. package/dist/llm-client.d.ts.map +1 -1
  26. package/dist/llm-client.js +64 -13
  27. package/dist/llm-client.js.map +1 -1
  28. package/dist/plugin-auto-loader.d.ts +108 -0
  29. package/dist/plugin-auto-loader.d.ts.map +1 -0
  30. package/dist/plugin-auto-loader.js +743 -0
  31. package/dist/plugin-auto-loader.js.map +1 -0
  32. package/dist/plugin-registry.d.ts +112 -0
  33. package/dist/plugin-registry.d.ts.map +1 -0
  34. package/dist/plugin-registry.js +319 -0
  35. package/dist/plugin-registry.js.map +1 -0
  36. package/dist/plugin-types.d.ts +388 -0
  37. package/dist/plugin-types.d.ts.map +1 -0
  38. package/dist/plugin-types.js +8 -0
  39. package/dist/plugin-types.js.map +1 -0
  40. package/dist/plugin-validator.d.ts +54 -0
  41. package/dist/plugin-validator.d.ts.map +1 -0
  42. package/dist/plugin-validator.js +129 -0
  43. package/dist/plugin-validator.js.map +1 -0
  44. package/dist/repo-knowledge-graph.d.ts +112 -0
  45. package/dist/repo-knowledge-graph.d.ts.map +1 -0
  46. package/dist/repo-knowledge-graph.js +561 -0
  47. package/dist/repo-knowledge-graph.js.map +1 -0
  48. package/dist/role-registry.js +1 -1
  49. package/dist/role-registry.js.map +1 -1
  50. package/dist/self-debug-loop.d.ts +257 -0
  51. package/dist/self-debug-loop.d.ts.map +1 -0
  52. package/dist/self-debug-loop.js +870 -0
  53. package/dist/self-debug-loop.js.map +1 -0
  54. package/dist/skill-learner.d.ts +136 -0
  55. package/dist/skill-learner.d.ts.map +1 -0
  56. package/dist/skill-learner.js +382 -0
  57. package/dist/skill-learner.js.map +1 -0
  58. package/dist/skill-loader.d.ts +90 -0
  59. package/dist/skill-loader.d.ts.map +1 -0
  60. package/dist/skill-loader.js +309 -0
  61. package/dist/skill-loader.js.map +1 -0
  62. package/dist/specialist-registry.d.ts +132 -0
  63. package/dist/specialist-registry.d.ts.map +1 -0
  64. package/dist/specialist-registry.js +413 -0
  65. package/dist/specialist-registry.js.map +1 -0
  66. package/dist/sub-agent-prompts.d.ts +45 -0
  67. package/dist/sub-agent-prompts.d.ts.map +1 -0
  68. package/dist/sub-agent-prompts.js +177 -0
  69. package/dist/sub-agent-prompts.js.map +1 -0
  70. package/dist/sub-agent-router.d.ts +75 -0
  71. package/dist/sub-agent-router.d.ts.map +1 -0
  72. package/dist/sub-agent-router.js +174 -0
  73. package/dist/sub-agent-router.js.map +1 -0
  74. package/dist/sub-agent.d.ts +48 -0
  75. package/dist/sub-agent.d.ts.map +1 -1
  76. package/dist/sub-agent.js +108 -5
  77. package/dist/sub-agent.js.map +1 -1
  78. package/dist/system-prompt.d.ts +26 -0
  79. package/dist/system-prompt.d.ts.map +1 -1
  80. package/dist/system-prompt.js +177 -7
  81. package/dist/system-prompt.js.map +1 -1
  82. package/dist/task-classifier.d.ts +25 -1
  83. package/dist/task-classifier.d.ts.map +1 -1
  84. package/dist/task-classifier.js +171 -1
  85. package/dist/task-classifier.js.map +1 -1
  86. package/dist/tool-planner.d.ts +160 -0
  87. package/dist/tool-planner.d.ts.map +1 -0
  88. package/dist/tool-planner.js +501 -0
  89. package/dist/tool-planner.js.map +1 -0
  90. package/dist/types.d.ts +1 -1
  91. package/dist/types.d.ts.map +1 -1
  92. package/dist/world-state.d.ts.map +1 -1
  93. package/dist/world-state.js +8 -1
  94. package/dist/world-state.js.map +1 -1
  95. package/package.json +2 -1
  96. package/plugins/git/patterns/branch-patterns.json +101 -0
  97. package/plugins/git/patterns/commit-patterns.json +186 -0
  98. package/plugins/git/plugin.yaml +128 -0
  99. package/plugins/git/skills/branch-strategy.md +172 -0
  100. package/plugins/git/skills/commit-conv.md +178 -0
  101. package/plugins/git/skills/conflict-resolve.md +159 -0
  102. package/plugins/git/skills/history-clean.md +199 -0
  103. package/plugins/git/skills/pr-review.md +196 -0
  104. package/plugins/git/strategies/conflict-resolve.json +244 -0
  105. package/plugins/git/strategies/release-flow.json +292 -0
  106. package/plugins/git/validators/rules.json +348 -0
  107. package/plugins/react/patterns/anti-patterns.json +88 -0
  108. package/plugins/react/patterns/components.json +80 -0
  109. package/plugins/react/patterns/hooks.json +72 -0
  110. package/plugins/react/plugin.yaml +229 -0
  111. package/plugins/react/skills/bugfix.md +208 -0
  112. package/plugins/react/skills/component-gen.md +206 -0
  113. package/plugins/react/skills/hook-extract.md +208 -0
  114. package/plugins/react/skills/ssr.md +256 -0
  115. package/plugins/react/skills/test.md +273 -0
  116. package/plugins/react/strategies/build-fix.json +43 -0
  117. package/plugins/react/strategies/hook-loop-fix.json +36 -0
  118. package/plugins/react/strategies/hydration-fix.json +42 -0
  119. package/plugins/react/validators/rules.json +92 -0
  120. package/plugins/typescript/patterns/best-practices.json +25 -0
  121. package/plugins/typescript/patterns/common-errors.json +32 -0
  122. package/plugins/typescript/plugin.yaml +74 -0
  123. package/plugins/typescript/skills/debug.md +23 -0
  124. package/plugins/typescript/skills/migration.md +24 -0
  125. package/plugins/typescript/skills/refactor.md +22 -0
  126. package/plugins/typescript/skills/strict-mode.md +23 -0
  127. package/plugins/typescript/strategies/strict-migration.json +37 -0
  128. package/plugins/typescript/strategies/type-error-fix.json +37 -0
  129. package/plugins/typescript/validators/rules.json +28 -0
@@ -0,0 +1,292 @@
1
+ {
2
+ "id": "release-flow",
3
+ "name": "Release Flow Strategy",
4
+ "description": "릴리스 브랜치 생성부터 태그 배포까지의 표준 릴리스 플로우.",
5
+ "phases": [
6
+ {
7
+ "id": "create-release-branch",
8
+ "name": "Create Release Branch",
9
+ "order": 1,
10
+ "description": "릴리스 준비를 위한 전용 브랜치를 생성한다.",
11
+ "preconditions": [
12
+ "develop 브랜치(또는 main)가 릴리스 가능 상태",
13
+ "모든 target 기능이 merge 완료",
14
+ "CI가 green 상태"
15
+ ],
16
+ "steps": [
17
+ {
18
+ "command": "git fetch origin",
19
+ "purpose": "최신 원격 상태 동기화"
20
+ },
21
+ {
22
+ "command": "git checkout {baseBranch}",
23
+ "purpose": "릴리스 기반 브랜치로 이동",
24
+ "baseBranch": "develop (Git Flow) 또는 main (Trunk-based)"
25
+ },
26
+ {
27
+ "command": "git pull origin {baseBranch}",
28
+ "purpose": "최신 상태 확인"
29
+ },
30
+ {
31
+ "command": "git checkout -b release/{version}",
32
+ "purpose": "릴리스 브랜치 생성"
33
+ },
34
+ {
35
+ "command": "git push -u origin release/{version}",
36
+ "purpose": "원격에 릴리스 브랜치 푸시"
37
+ }
38
+ ],
39
+ "versionScheme": {
40
+ "format": "semver",
41
+ "pattern": "{major}.{minor}.{patch}",
42
+ "examples": ["1.2.0", "2.0.0", "0.3.1"],
43
+ "prerelease": {
44
+ "rc": "{version}-rc.{n}",
45
+ "beta": "{version}-beta.{n}",
46
+ "alpha": "{version}-alpha.{n}"
47
+ }
48
+ },
49
+ "outputs": {
50
+ "releaseBranch": "release/{version}",
51
+ "previousVersion": "이전 릴리스 버전"
52
+ }
53
+ },
54
+ {
55
+ "id": "version-bump",
56
+ "name": "Version Bump",
57
+ "order": 2,
58
+ "description": "패키지 버전을 올리고 관련 파일을 업데이트한다.",
59
+ "steps": [
60
+ {
61
+ "tool": "file_read",
62
+ "target": "package.json",
63
+ "purpose": "현재 버전 확인"
64
+ },
65
+ {
66
+ "tool": "file_edit",
67
+ "target": "package.json",
68
+ "purpose": "version 필드 업데이트"
69
+ },
70
+ {
71
+ "tool": "file_edit",
72
+ "target": "모노레포 내 의존 패키지들의 package.json",
73
+ "purpose": "workspace 의존성 버전 업데이트 (해당 시)",
74
+ "conditional": "모노레포일 때"
75
+ },
76
+ {
77
+ "command": "pnpm install --lockfile-only",
78
+ "purpose": "lock file 업데이트 (의존성 재설치 없이)",
79
+ "conditional": "lock file이 버전을 반영할 때"
80
+ }
81
+ ],
82
+ "bumpRules": {
83
+ "major": {
84
+ "trigger": "BREAKING CHANGE가 포함된 커밋이 있을 때",
85
+ "description": "호환성이 깨지는 변경"
86
+ },
87
+ "minor": {
88
+ "trigger": "feat 타입 커밋이 있고 breaking change가 없을 때",
89
+ "description": "새 기능 추가 (하위 호환)"
90
+ },
91
+ "patch": {
92
+ "trigger": "fix 타입 커밋만 있을 때",
93
+ "description": "버그 수정"
94
+ }
95
+ },
96
+ "monorepoStrategy": {
97
+ "independent": "각 패키지가 독립적으로 버전 관리",
98
+ "fixed": "모든 패키지가 동일 버전 사용",
99
+ "recommendation": "core 패키지는 independent, 앱 패키지는 fixed"
100
+ },
101
+ "outputs": {
102
+ "newVersion": "업데이트된 버전",
103
+ "bumpType": "major | minor | patch",
104
+ "updatedFiles": "버전이 변경된 파일 목록"
105
+ }
106
+ },
107
+ {
108
+ "id": "changelog",
109
+ "name": "Generate Changelog",
110
+ "order": 3,
111
+ "description": "커밋 히스토리 기반으로 CHANGELOG를 생성하거나 업데이트한다.",
112
+ "steps": [
113
+ {
114
+ "command": "git log --oneline {previousTag}..HEAD",
115
+ "purpose": "이전 릴리스 이후 커밋 목록 수집"
116
+ },
117
+ {
118
+ "tool": "file_read",
119
+ "target": "CHANGELOG.md",
120
+ "purpose": "기존 CHANGELOG 확인",
121
+ "optional": true
122
+ },
123
+ {
124
+ "action": "generate",
125
+ "purpose": "커밋을 카테고리별로 분류하여 CHANGELOG 섹션 생성"
126
+ },
127
+ {
128
+ "tool": "file_edit",
129
+ "target": "CHANGELOG.md",
130
+ "purpose": "새 릴리스 섹션을 CHANGELOG 최상단에 추가"
131
+ }
132
+ ],
133
+ "changelogFormat": {
134
+ "template": "## [{version}] - {date}\n\n### Added\n{feats}\n\n### Fixed\n{fixes}\n\n### Changed\n{refactors}\n\n### Breaking Changes\n{breaking}\n",
135
+ "categories": [
136
+ {
137
+ "heading": "Added",
138
+ "types": ["feat"],
139
+ "description": "새 기능"
140
+ },
141
+ {
142
+ "heading": "Fixed",
143
+ "types": ["fix"],
144
+ "description": "버그 수정"
145
+ },
146
+ {
147
+ "heading": "Changed",
148
+ "types": ["refactor", "perf"],
149
+ "description": "기존 기능 변경"
150
+ },
151
+ {
152
+ "heading": "Documentation",
153
+ "types": ["docs"],
154
+ "description": "문서 변경"
155
+ },
156
+ {
157
+ "heading": "Breaking Changes",
158
+ "types": [],
159
+ "filter": "BREAKING CHANGE footer 또는 ! 표기가 있는 커밋",
160
+ "description": "호환성 깨지는 변경"
161
+ },
162
+ {
163
+ "heading": "Internal",
164
+ "types": ["chore", "ci", "build", "test"],
165
+ "description": "내부 변경 (선택적 포함)"
166
+ }
167
+ ],
168
+ "entryFormat": "- {scope}: {description} ({commitShort})",
169
+ "dateFormat": "YYYY-MM-DD"
170
+ },
171
+ "outputs": {
172
+ "changelogEntry": "생성된 CHANGELOG 섹션",
173
+ "commitCount": "포함된 커밋 수"
174
+ }
175
+ },
176
+ {
177
+ "id": "tag-and-merge",
178
+ "name": "Tag & Merge",
179
+ "order": 4,
180
+ "description": "릴리스를 태그하고 main/develop 브랜치에 병합한다.",
181
+ "steps": [
182
+ {
183
+ "command": "git add -A",
184
+ "purpose": "버전 bump 및 CHANGELOG 변경 staging"
185
+ },
186
+ {
187
+ "command": "git commit -m \"chore(release): {version}\"",
188
+ "purpose": "릴리스 커밋 생성"
189
+ },
190
+ {
191
+ "command": "git checkout main",
192
+ "purpose": "main 브랜치로 이동"
193
+ },
194
+ {
195
+ "command": "git merge --no-ff release/{version}",
196
+ "purpose": "릴리스 브랜치를 main에 병합 (merge commit 생성)"
197
+ },
198
+ {
199
+ "command": "git tag -a v{version} -m \"Release v{version}\"",
200
+ "purpose": "annotated 태그 생성"
201
+ },
202
+ {
203
+ "command": "git checkout develop",
204
+ "purpose": "develop 브랜치로 이동 (Git Flow만)",
205
+ "conditional": "Git Flow 사용 시"
206
+ },
207
+ {
208
+ "command": "git merge --no-ff release/{version}",
209
+ "purpose": "릴리스 브랜치를 develop에도 병합 (Git Flow만)",
210
+ "conditional": "Git Flow 사용 시"
211
+ },
212
+ {
213
+ "command": "git push origin main develop --tags",
214
+ "purpose": "main, develop, 태그를 원격에 푸시"
215
+ },
216
+ {
217
+ "command": "git branch -d release/{version}",
218
+ "purpose": "릴리스 브랜치 삭제 (로컬)"
219
+ },
220
+ {
221
+ "command": "git push origin --delete release/{version}",
222
+ "purpose": "릴리스 브랜치 삭제 (원격)"
223
+ }
224
+ ],
225
+ "tagConventions": {
226
+ "format": "v{major}.{minor}.{patch}",
227
+ "examples": ["v1.2.0", "v2.0.0", "v0.3.1"],
228
+ "annotated": true,
229
+ "signed": false,
230
+ "message": "Release v{version}"
231
+ },
232
+ "postRelease": {
233
+ "actions": [
234
+ {
235
+ "name": "GitHub Release",
236
+ "command": "gh release create v{version} --title \"v{version}\" --notes-file RELEASE_NOTES.md",
237
+ "description": "GitHub Release 생성 (CHANGELOG에서 해당 버전 섹션 추출)",
238
+ "optional": true
239
+ },
240
+ {
241
+ "name": "npm Publish",
242
+ "command": "pnpm publish --no-git-checks",
243
+ "description": "npm 레지스트리에 패키지 배포",
244
+ "conditional": "npm 패키지일 때",
245
+ "requiresApproval": true
246
+ },
247
+ {
248
+ "name": "Notify",
249
+ "description": "팀/채널에 릴리스 알림",
250
+ "optional": true
251
+ }
252
+ ]
253
+ },
254
+ "outputs": {
255
+ "tag": "생성된 태그",
256
+ "mergedTo": "병합된 브랜치 목록",
257
+ "releaseUrl": "GitHub Release URL (생성 시)"
258
+ }
259
+ }
260
+ ],
261
+ "config": {
262
+ "defaultBaseBranch": "main",
263
+ "gitFlowBaseBranch": "develop",
264
+ "requireCI": true,
265
+ "requireReview": true,
266
+ "autoDeleteReleaseBranch": true,
267
+ "signTags": false,
268
+ "publishToNpm": false,
269
+ "createGitHubRelease": true
270
+ },
271
+ "hotfix": {
272
+ "description": "긴급 프로덕션 버그 수정을 위한 축약 릴리스 플로우",
273
+ "steps": [
274
+ "git checkout main",
275
+ "git checkout -b hotfix/{version}",
276
+ "버그 수정 + 테스트 추가",
277
+ "version bump (patch)",
278
+ "CHANGELOG 업데이트",
279
+ "git checkout main && git merge --no-ff hotfix/{version}",
280
+ "git tag -a v{version}",
281
+ "git checkout develop && git merge --no-ff hotfix/{version}",
282
+ "git push origin main develop --tags",
283
+ "git branch -d hotfix/{version}"
284
+ ],
285
+ "urgencyLevels": {
286
+ "P0": "즉시 — 서비스 다운, 데이터 손실",
287
+ "P1": "4시간 내 — 주요 기능 장애",
288
+ "P2": "24시간 내 — 부분 기능 장애",
289
+ "P3": "다음 정기 릴리스 — 경미한 이슈"
290
+ }
291
+ }
292
+ }
@@ -0,0 +1,348 @@
1
+ {
2
+ "validators": {
3
+ "pre": [
4
+ {
5
+ "id": "commit-message-format",
6
+ "name": "Commit Message Format",
7
+ "description": "커밋 메시지가 Conventional Commits 형식을 따르는지 검증",
8
+ "when": "before-commit",
9
+ "check": {
10
+ "pattern": "^(feat|fix|chore|docs|style|refactor|perf|test|build|ci|revert)(\\([a-z0-9._-]+\\))?!?: .{3,}",
11
+ "flags": "i",
12
+ "target": "commit-message",
13
+ "multiline": false
14
+ },
15
+ "severity": "error",
16
+ "message": "Commit message must follow Conventional Commits format: <type>[scope]: <description>",
17
+ "autoFix": {
18
+ "enabled": true,
19
+ "strategy": "prompt-rewrite",
20
+ "description": "분석된 diff를 기반으로 올바른 커밋 메시지를 제안"
21
+ },
22
+ "examples": {
23
+ "pass": [
24
+ "feat: add user authentication",
25
+ "fix(api): resolve null pointer in session handler",
26
+ "chore(deps): bump typescript to 5.7",
27
+ "feat(core)!: redesign plugin loading API"
28
+ ],
29
+ "fail": [
30
+ "added stuff",
31
+ "WIP",
32
+ "fix",
33
+ "Update file",
34
+ "Feat: Wrong Casing"
35
+ ]
36
+ }
37
+ },
38
+ {
39
+ "id": "commit-message-length",
40
+ "name": "Commit Subject Length",
41
+ "description": "커밋 메시지 subject가 적절한 길이인지 검증",
42
+ "when": "before-commit",
43
+ "check": {
44
+ "type": "length",
45
+ "target": "commit-message-subject",
46
+ "min": 10,
47
+ "max": 72
48
+ },
49
+ "severity": "warning",
50
+ "message": "Commit subject should be between 10 and 72 characters (current: {length})",
51
+ "autoFix": {
52
+ "enabled": true,
53
+ "strategy": "truncate-to-body",
54
+ "description": "72자 초과 시 subject를 줄이고 나머지를 body로 이동"
55
+ }
56
+ },
57
+ {
58
+ "id": "branch-name-format",
59
+ "name": "Branch Name Format",
60
+ "description": "브랜치명이 네이밍 컨벤션을 따르는지 검증",
61
+ "when": "before-push",
62
+ "check": {
63
+ "pattern": "^(main|master|develop|feature/|feat/|fix/|bugfix/|hotfix/|release/|chore/|docs/|refactor/|ci/|test/|perf/|build/)",
64
+ "target": "branch-name"
65
+ },
66
+ "severity": "warning",
67
+ "message": "Branch name should start with a recognized prefix (feature/, fix/, release/, hotfix/, etc.)",
68
+ "exclude": ["main", "master", "develop"],
69
+ "autoFix": {
70
+ "enabled": false,
71
+ "description": "브랜치 rename은 위험하므로 수동 처리 권장"
72
+ }
73
+ },
74
+ {
75
+ "id": "no-direct-push-to-protected",
76
+ "name": "No Direct Push to Protected Branches",
77
+ "description": "main/develop 브랜치에 직접 push하지 않도록 검증",
78
+ "when": "before-push",
79
+ "check": {
80
+ "type": "branch-protection",
81
+ "protectedBranches": ["main", "master", "develop"],
82
+ "target": "current-branch"
83
+ },
84
+ "severity": "error",
85
+ "message": "Direct push to {branch} is not allowed. Create a feature branch and open a PR.",
86
+ "autoFix": {
87
+ "enabled": true,
88
+ "strategy": "create-branch",
89
+ "description": "현재 커밋을 새 feature 브랜치로 이동"
90
+ }
91
+ },
92
+ {
93
+ "id": "no-secrets-in-commit",
94
+ "name": "No Secrets in Commit",
95
+ "description": "커밋에 시크릿/크레덴셜이 포함되지 않았는지 검증",
96
+ "when": "before-commit",
97
+ "check": {
98
+ "type": "pattern-scan",
99
+ "target": "staged-diff",
100
+ "patterns": [
101
+ {
102
+ "name": "AWS Access Key",
103
+ "pattern": "AKIA[0-9A-Z]{16}"
104
+ },
105
+ {
106
+ "name": "AWS Secret Key",
107
+ "pattern": "[0-9a-zA-Z/+]{40}"
108
+ },
109
+ {
110
+ "name": "GitHub Token",
111
+ "pattern": "gh[ps]_[A-Za-z0-9_]{36,}"
112
+ },
113
+ {
114
+ "name": "Generic API Key",
115
+ "pattern": "(api[_-]?key|apikey|api[_-]?secret)\\s*[:=]\\s*['\"][^'\"]{8,}"
116
+ },
117
+ {
118
+ "name": "Private Key",
119
+ "pattern": "-----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----"
120
+ },
121
+ {
122
+ "name": "JWT Token",
123
+ "pattern": "eyJ[A-Za-z0-9-_]+\\.eyJ[A-Za-z0-9-_]+"
124
+ },
125
+ {
126
+ "name": "Database URL with Credentials",
127
+ "pattern": "(postgres|mysql|mongodb)://[^:]+:[^@]+@"
128
+ }
129
+ ]
130
+ },
131
+ "severity": "error",
132
+ "message": "Potential secret detected: {secretType}. Remove the secret and use environment variables instead.",
133
+ "autoFix": {
134
+ "enabled": false,
135
+ "description": "시크릿은 자동 수정 불가 — 수동으로 제거하고 .env로 이동"
136
+ }
137
+ }
138
+ ],
139
+ "post": [
140
+ {
141
+ "id": "no-conflict-markers",
142
+ "name": "No Conflict Markers Remaining",
143
+ "description": "merge 후 conflict 마커가 코드에 남아있지 않은지 검증",
144
+ "when": "after-merge",
145
+ "check": {
146
+ "type": "pattern-scan",
147
+ "target": "working-tree",
148
+ "patterns": [
149
+ {
150
+ "name": "Conflict Start",
151
+ "pattern": "^<{7} "
152
+ },
153
+ {
154
+ "name": "Conflict Separator",
155
+ "pattern": "^={7}$"
156
+ },
157
+ {
158
+ "name": "Conflict End",
159
+ "pattern": "^>{7} "
160
+ }
161
+ ],
162
+ "exclude": ["*.md", "*.txt", "*.json"]
163
+ },
164
+ "severity": "error",
165
+ "message": "Conflict markers found in {file}:{line}. Resolve all conflicts before committing.",
166
+ "autoFix": {
167
+ "enabled": false,
168
+ "description": "conflict-resolve 스킬로 위임"
169
+ }
170
+ },
171
+ {
172
+ "id": "build-passes-after-merge",
173
+ "name": "Build Passes After Merge",
174
+ "description": "merge 후 빌드가 정상적으로 통과하는지 검증",
175
+ "when": "after-merge",
176
+ "check": {
177
+ "type": "command",
178
+ "commands": [
179
+ {
180
+ "command": "tsc --noEmit",
181
+ "description": "TypeScript 컴파일 체크",
182
+ "conditional": "tsconfig.json exists"
183
+ },
184
+ {
185
+ "command": "pnpm build",
186
+ "description": "전체 빌드"
187
+ }
188
+ ],
189
+ "timeout": 300000
190
+ },
191
+ "severity": "error",
192
+ "message": "Build failed after merge. Fix build errors before pushing.",
193
+ "autoFix": {
194
+ "enabled": true,
195
+ "strategy": "error-based-fix",
196
+ "maxRetries": 3,
197
+ "description": "빌드 에러 메시지를 분석하여 자동 수정 시도"
198
+ }
199
+ },
200
+ {
201
+ "id": "tests-pass-after-merge",
202
+ "name": "Tests Pass After Merge",
203
+ "description": "merge 후 테스트가 통과하는지 검증",
204
+ "when": "after-merge",
205
+ "check": {
206
+ "type": "command",
207
+ "commands": [
208
+ {
209
+ "command": "pnpm test",
210
+ "description": "전체 테스트 실행"
211
+ }
212
+ ],
213
+ "timeout": 300000
214
+ },
215
+ "severity": "warning",
216
+ "message": "Tests failed after merge. Review failing tests.",
217
+ "autoFix": {
218
+ "enabled": false,
219
+ "description": "테스트 실패는 의도 파악이 필요하므로 수동 처리"
220
+ }
221
+ }
222
+ ],
223
+ "quality": [
224
+ {
225
+ "id": "pr-has-description",
226
+ "name": "PR Has Description",
227
+ "description": "PR에 의미 있는 설명이 포함되어 있는지 검증",
228
+ "when": "pr-create",
229
+ "check": {
230
+ "type": "content",
231
+ "target": "pr-body",
232
+ "minLength": 50,
233
+ "requiredSections": ["Summary", "Changes"],
234
+ "forbiddenPatterns": ["TODO: fill in", "WIP", "TBD"]
235
+ },
236
+ "severity": "warning",
237
+ "message": "PR description is too short or missing required sections. Use the PR template.",
238
+ "autoFix": {
239
+ "enabled": true,
240
+ "strategy": "generate-description",
241
+ "description": "커밋 히스토리와 diff를 분석하여 PR description 자동 생성"
242
+ }
243
+ },
244
+ {
245
+ "id": "pr-includes-tests",
246
+ "name": "PR Includes Tests",
247
+ "description": "기능 변경 PR에 테스트가 포함되어 있는지 검증",
248
+ "when": "pr-create",
249
+ "check": {
250
+ "type": "file-pattern",
251
+ "target": "pr-diff",
252
+ "requirePattern": "\\.(test|spec)\\.(ts|tsx|js|jsx)$",
253
+ "whenChanged": "\\.(ts|tsx|js|jsx)$",
254
+ "excludeTypes": ["docs", "style", "chore", "ci"]
255
+ },
256
+ "severity": "info",
257
+ "message": "This PR changes source files but does not include test changes. Consider adding tests.",
258
+ "autoFix": {
259
+ "enabled": false,
260
+ "description": "테스트 작성은 자동화 대상이 아님 — 리마인더만 제공"
261
+ }
262
+ },
263
+ {
264
+ "id": "pr-size-check",
265
+ "name": "PR Size Check",
266
+ "description": "PR 크기가 적절한지 검증",
267
+ "when": "pr-create",
268
+ "check": {
269
+ "type": "diff-stats",
270
+ "target": "pr-diff",
271
+ "thresholds": {
272
+ "additions": {
273
+ "warn": 400,
274
+ "error": 1000
275
+ },
276
+ "filesChanged": {
277
+ "warn": 15,
278
+ "error": 30
279
+ }
280
+ },
281
+ "excludePatterns": ["*.lock", "*.snap", "*.generated.*"]
282
+ },
283
+ "severity": "warning",
284
+ "message": "PR is large ({additions} additions, {filesChanged} files). Consider splitting into smaller PRs.",
285
+ "autoFix": {
286
+ "enabled": false,
287
+ "description": "PR 분리 전략을 제안 (stacked PRs)"
288
+ }
289
+ },
290
+ {
291
+ "id": "no-fixup-commits",
292
+ "name": "No Fixup/WIP Commits",
293
+ "description": "PR에 WIP/fixup 커밋이 남아있지 않은지 검증",
294
+ "when": "pr-create",
295
+ "check": {
296
+ "type": "commit-messages",
297
+ "target": "pr-commits",
298
+ "forbiddenPatterns": [
299
+ "^(WIP|wip|Wip)[: ]",
300
+ "^fixup!",
301
+ "^squash!",
302
+ "^(temp|tmp|test123|asdf|xxx)"
303
+ ]
304
+ },
305
+ "severity": "warning",
306
+ "message": "PR contains WIP/fixup commits. Squash or clean up history before requesting review.",
307
+ "autoFix": {
308
+ "enabled": true,
309
+ "strategy": "suggest-rebase",
310
+ "description": "history-clean 스킬로 위임하여 rebase 제안"
311
+ }
312
+ },
313
+ {
314
+ "id": "changelog-updated",
315
+ "name": "Changelog Updated",
316
+ "description": "사용자 대면 변경 시 CHANGELOG가 업데이트되었는지 검증",
317
+ "when": "pr-create",
318
+ "check": {
319
+ "type": "file-changed",
320
+ "target": "pr-diff",
321
+ "requiredFile": "CHANGELOG.md",
322
+ "whenCommitTypes": ["feat", "fix"],
323
+ "whenBreakingChange": true
324
+ },
325
+ "severity": "info",
326
+ "message": "This PR includes user-facing changes but CHANGELOG.md was not updated.",
327
+ "autoFix": {
328
+ "enabled": true,
329
+ "strategy": "generate-changelog-entry",
330
+ "description": "release-flow 전략의 changelog phase를 활용하여 엔트리 생성"
331
+ }
332
+ }
333
+ ]
334
+ },
335
+ "config": {
336
+ "enablePre": true,
337
+ "enablePost": true,
338
+ "enableQuality": true,
339
+ "strictMode": false,
340
+ "treatWarningsAsErrors": false,
341
+ "excludePaths": [
342
+ "node_modules/",
343
+ "dist/",
344
+ ".git/",
345
+ "*.lock"
346
+ ]
347
+ }
348
+ }