aiwf 0.3.21 โ†’ 0.3.23

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 (140) hide show
  1. package/package.json +3 -2
  2. package/src/cli/index.js +39 -336
  3. package/src/lib/installer.js +310 -90
  4. package/src/utils/messages.js +24 -0
  5. package/src/DEPENDENCY_MAP.md +0 -90
  6. package/src/cli/cache-cli.js +0 -459
  7. package/src/cli/checkpoint-cli.js +0 -417
  8. package/src/cli/language-cli.js +0 -286
  9. package/src/cli/sprint-cli.js +0 -287
  10. package/src/commands/ai-tool.js +0 -383
  11. package/src/commands/compress.js +0 -60
  12. package/src/commands/create-project.js +0 -160
  13. package/src/commands/evaluate.js +0 -459
  14. package/src/commands/persona.js +0 -309
  15. package/src/commands/sprint-task.js +0 -262
  16. package/src/commands/token.js +0 -312
  17. package/src/lib/ai-persona-manager.js +0 -711
  18. package/src/lib/cache-system.js +0 -332
  19. package/src/lib/context-engine.js +0 -568
  20. package/src/lib/github-integration.js +0 -402
  21. package/src/lib/memory-profiler.js +0 -471
  22. package/src/lib/metrics-collector.js +0 -885
  23. package/src/lib/offline-detector.js +0 -386
  24. package/src/lib/resource-loader-enhanced.js +0 -399
  25. package/src/lib/resource-loader.js +0 -250
  26. package/src/lib/resources/commands/ai-persona.js +0 -602
  27. package/src/lib/resources/commands/compress-context.js +0 -389
  28. package/src/lib/resources/commands/evaluate.js +0 -246
  29. package/src/lib/resources/commands/persona-context-apply.js +0 -562
  30. package/src/lib/resources/commands/token-tracking.js +0 -443
  31. package/src/lib/resources/config/commit-patterns.js +0 -103
  32. package/src/lib/resources/config/language.json +0 -6
  33. package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
  34. package/src/lib/resources/personas/analyst.json +0 -44
  35. package/src/lib/resources/personas/architect/best_practices.md +0 -136
  36. package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
  37. package/src/lib/resources/personas/architect.json +0 -44
  38. package/src/lib/resources/personas/backend/best_practices.md +0 -766
  39. package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
  40. package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
  41. package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
  42. package/src/lib/resources/personas/developer.json +0 -44
  43. package/src/lib/resources/personas/developer.md +0 -37
  44. package/src/lib/resources/personas/evaluation_criteria.json +0 -137
  45. package/src/lib/resources/personas/frontend/best_practices.md +0 -445
  46. package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
  47. package/src/lib/resources/personas/persona-index.json +0 -31
  48. package/src/lib/resources/personas/reviewer.json +0 -44
  49. package/src/lib/resources/personas/security/best_practices.md +0 -307
  50. package/src/lib/resources/personas/security/knowledge_base.md +0 -498
  51. package/src/lib/resources/personas/tester.json +0 -44
  52. package/src/lib/resources/templates/README.md +0 -78
  53. package/src/lib/resources/templates/api-server/config.json +0 -64
  54. package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
  55. package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
  56. package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
  57. package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
  58. package/src/lib/resources/templates/api-server/template/.env.example +0 -29
  59. package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
  60. package/src/lib/resources/templates/api-server/template/README.md +0 -171
  61. package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
  62. package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
  63. package/src/lib/resources/templates/api-server/template/package.json +0 -61
  64. package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
  65. package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
  66. package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
  67. package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
  68. package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
  69. package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
  70. package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
  71. package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
  72. package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
  73. package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
  74. package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
  75. package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
  76. package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
  77. package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
  78. package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
  79. package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
  80. package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
  81. package/src/lib/resources/templates/npm-library/config.json +0 -61
  82. package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
  83. package/src/lib/resources/templates/npm-library/template/README.md +0 -201
  84. package/src/lib/resources/templates/npm-library/template/package.json +0 -78
  85. package/src/lib/resources/templates/web-app/config.json +0 -53
  86. package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
  87. package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
  88. package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
  89. package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
  90. package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
  91. package/src/lib/resources/templates/web-app/template/README.md +0 -151
  92. package/src/lib/resources/templates/web-app/template/index.html +0 -14
  93. package/src/lib/resources/templates/web-app/template/package.json +0 -44
  94. package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
  95. package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
  96. package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
  97. package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
  98. package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
  99. package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
  100. package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
  101. package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
  102. package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
  103. package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
  104. package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
  105. package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
  106. package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
  107. package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
  108. package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
  109. package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
  110. package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
  111. package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
  112. package/src/lib/resources/utils/background-monitor.js +0 -223
  113. package/src/lib/resources/utils/compression-metrics.js +0 -1031
  114. package/src/lib/resources/utils/compression-strategies.js +0 -557
  115. package/src/lib/resources/utils/content-normalizer.js +0 -455
  116. package/src/lib/resources/utils/context-compressor.js +0 -583
  117. package/src/lib/resources/utils/context-rule-parser.js +0 -180
  118. package/src/lib/resources/utils/context-token-monitor.js +0 -463
  119. package/src/lib/resources/utils/context-update-manager.js +0 -502
  120. package/src/lib/resources/utils/git-utils.js +0 -220
  121. package/src/lib/resources/utils/importance-classifier.js +0 -645
  122. package/src/lib/resources/utils/information-filter.js +0 -710
  123. package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
  124. package/src/lib/resources/utils/prompt-injector.js +0 -242
  125. package/src/lib/resources/utils/simplified-evaluator.js +0 -119
  126. package/src/lib/resources/utils/text-summarizer.js +0 -492
  127. package/src/lib/resources/utils/token-counter.js +0 -177
  128. package/src/lib/resources/utils/token-monitor.js +0 -484
  129. package/src/lib/resources/utils/token-reporter.js +0 -452
  130. package/src/lib/resources/utils/token-storage.js +0 -433
  131. package/src/lib/resources/utils/token-tracker.js +0 -283
  132. package/src/lib/state/priority-calculator.js +0 -217
  133. package/src/lib/state/state-index.js +0 -155
  134. package/src/lib/state/task-scanner.js +0 -328
  135. package/src/lib/task-analyzer.js +0 -599
  136. package/src/lib/template-cache-system.js +0 -559
  137. package/src/lib/template-downloader.js +0 -467
  138. package/src/lib/template-version-manager.js +0 -491
  139. package/src/lib/token-optimizer.js +0 -517
  140. package/src/utils/engineering-guard.js +0 -399
@@ -1,402 +0,0 @@
1
- /**
2
- * AIWF GitHub Integration
3
- * GitHub Issues์™€ Pull Requests ํ†ตํ•ฉ ๊ด€๋ฆฌ
4
- */
5
-
6
- import { execSync } from 'child_process';
7
- import fs from 'fs/promises';
8
- import path from 'path';
9
- import chalk from 'chalk';
10
- import ora from 'ora';
11
- import { StateIndexManager } from './state/state-index.js';
12
-
13
- export class GitHubIntegration {
14
- constructor() {
15
- this.projectRoot = null;
16
- this.aiwfPath = null;
17
- this.stateIndexManager = null;
18
- }
19
-
20
- /**
21
- * ์ดˆ๊ธฐํ™”
22
- */
23
- async init() {
24
- this.projectRoot = await this.findProjectRoot();
25
- this.aiwfPath = path.join(this.projectRoot, '.aiwf');
26
- this.stateIndexManager = new StateIndexManager(this.aiwfPath);
27
- }
28
-
29
- async findProjectRoot(startDir = process.cwd()) {
30
- let currentDir = startDir;
31
-
32
- while (currentDir !== path.parse(currentDir).root) {
33
- try {
34
- const aiwfPath = path.join(currentDir, '.aiwf');
35
- await fs.access(aiwfPath);
36
- return currentDir;
37
- } catch {
38
- currentDir = path.dirname(currentDir);
39
- }
40
- }
41
-
42
- throw new Error('.aiwf directory not found. Are you in an AIWF project?');
43
- }
44
-
45
- /**
46
- * GitHub CLI ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ
47
- */
48
- checkGitHubCLI() {
49
- try {
50
- execSync('gh --version', { stdio: 'ignore' });
51
- return true;
52
- } catch {
53
- throw new Error('GitHub CLI (gh) is not installed. Please install it first: https://cli.github.com/');
54
- }
55
- }
56
-
57
- /**
58
- * ํƒœ์Šคํฌ์—์„œ GitHub ์ด์Šˆ ์ƒ์„ฑ
59
- */
60
- async createIssue(taskId) {
61
- const spinner = ora('Creating GitHub issue...').start();
62
-
63
- try {
64
- await this.init();
65
- this.checkGitHubCLI();
66
-
67
- // ์ƒํƒœ ์ธ๋ฑ์Šค์—์„œ ํƒœ์Šคํฌ ์ •๋ณด ๋กœ๋“œ
68
- const stateIndex = await this.stateIndexManager.loadIndex();
69
- if (!stateIndex) {
70
- throw new Error('State index not found. Run "aiwf state update" first.');
71
- }
72
-
73
- const task = stateIndex.tasks[taskId];
74
- if (!task) {
75
- throw new Error(`Task ${taskId} not found in state index.`);
76
- }
77
-
78
- spinner.text = 'Generating issue template...';
79
-
80
- // ์ด์Šˆ ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ
81
- const issueBody = this.generateIssueTemplate(task);
82
- const issueTitle = `${taskId}: ${task.title}`;
83
-
84
- // GitHub CLI๋กœ ์ด์Šˆ ์ƒ์„ฑ
85
- spinner.text = 'Creating issue on GitHub...';
86
- const labels = this.generateLabels(task);
87
-
88
- const createCommand = [
89
- 'gh', 'issue', 'create',
90
- '--title', `"${issueTitle}"`,
91
- '--body', `"${issueBody}"`,
92
- '--label', `"${labels.join(',')}"`,
93
- '--assignee', '@me'
94
- ].join(' ');
95
-
96
- const result = execSync(createCommand, {
97
- encoding: 'utf8',
98
- cwd: this.projectRoot
99
- });
100
-
101
- // ์ด์Šˆ URL ์ถ”์ถœ
102
- const issueUrl = result.trim();
103
- const issueNumber = this.extractIssueNumber(issueUrl);
104
-
105
- // ํƒœ์Šคํฌ ํŒŒ์ผ์— GitHub ์ด์Šˆ ์ •๋ณด ์ถ”๊ฐ€
106
- if (task.file_path) {
107
- await this.updateTaskWithIssue(task.file_path, issueNumber, issueUrl);
108
- }
109
-
110
- spinner.succeed(`GitHub issue created successfully: ${issueUrl}`);
111
-
112
- console.log(chalk.cyan('\n๐Ÿ“‹ Issue Details:'));
113
- console.log(` Title: ${issueTitle}`);
114
- console.log(` URL: ${issueUrl}`);
115
- console.log(` Labels: ${labels.join(', ')}`);
116
-
117
- } catch (error) {
118
- spinner.fail(`Failed to create GitHub issue: ${error.message}`);
119
- throw error;
120
- }
121
- }
122
-
123
- /**
124
- * Pull Request ์ƒ์„ฑ
125
- */
126
- async createPullRequest(taskId) {
127
- const spinner = ora('Creating pull request...').start();
128
-
129
- try {
130
- await this.init();
131
- this.checkGitHubCLI();
132
-
133
- // ํ˜„์žฌ ๋ธŒ๋žœ์น˜ ํ™•์ธ
134
- const currentBranch = execSync('git branch --show-current', {
135
- encoding: 'utf8',
136
- cwd: this.projectRoot
137
- }).trim();
138
-
139
- if (currentBranch === 'main' || currentBranch === 'master') {
140
- throw new Error('Cannot create PR from main/master branch. Please create a feature branch first.');
141
- }
142
-
143
- spinner.text = 'Checking branch status...';
144
-
145
- // ๋ณ€๊ฒฝ์‚ฌํ•ญ ํ™•์ธ
146
- const diffStat = execSync('git diff main...HEAD --stat', {
147
- encoding: 'utf8',
148
- cwd: this.projectRoot
149
- });
150
-
151
- if (!diffStat.trim()) {
152
- throw new Error('No changes found between current branch and main.');
153
- }
154
-
155
- // ์ปค๋ฐ‹ ํžˆ์Šคํ† ๋ฆฌ ํ™•์ธ
156
- const commits = execSync('git log main..HEAD --oneline', {
157
- encoding: 'utf8',
158
- cwd: this.projectRoot
159
- });
160
-
161
- spinner.text = 'Generating PR template...';
162
-
163
- // PR ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ
164
- const prBody = this.generatePRTemplate(taskId, commits, diffStat);
165
- const prTitle = taskId ? `${taskId}: Complete task implementation` : `Complete feature implementation`;
166
-
167
- // GitHub CLI๋กœ PR ์ƒ์„ฑ
168
- spinner.text = 'Creating pull request on GitHub...';
169
-
170
- const createCommand = [
171
- 'gh', 'pr', 'create',
172
- '--title', `"${prTitle}"`,
173
- '--body', `"${prBody}"`,
174
- '--base', 'main',
175
- '--head', currentBranch
176
- ].join(' ');
177
-
178
- const result = execSync(createCommand, {
179
- encoding: 'utf8',
180
- cwd: this.projectRoot
181
- });
182
-
183
- const prUrl = result.trim();
184
-
185
- spinner.succeed(`Pull request created successfully: ${prUrl}`);
186
-
187
- console.log(chalk.cyan('\n๐Ÿ”€ Pull Request Details:'));
188
- console.log(` Title: ${prTitle}`);
189
- console.log(` URL: ${prUrl}`);
190
- console.log(` Base: main โ† ${currentBranch}`);
191
-
192
- } catch (error) {
193
- spinner.fail(`Failed to create pull request: ${error.message}`);
194
- throw error;
195
- }
196
- }
197
-
198
- /**
199
- * GitHub ์ด์Šˆ์™€ AIWF ํƒœ์Šคํฌ ๋™๊ธฐํ™”
200
- */
201
- async syncIssues() {
202
- const spinner = ora('Syncing GitHub issues...').start();
203
-
204
- try {
205
- await this.init();
206
- this.checkGitHubCLI();
207
-
208
- // GitHub์—์„œ ์ด์Šˆ ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
209
- spinner.text = 'Fetching GitHub issues...';
210
- const issuesJson = execSync('gh issue list --json number,title,state,labels,assignees', {
211
- encoding: 'utf8',
212
- cwd: this.projectRoot
213
- });
214
-
215
- const issues = JSON.parse(issuesJson);
216
-
217
- // AIWF ํƒœ์Šคํฌ์™€ ์—ฐ๊ฒฐ๋œ ์ด์Šˆ๋“ค ํ™•์ธ
218
- const stateIndex = await this.stateIndexManager.loadIndex();
219
- if (!stateIndex) {
220
- throw new Error('State index not found. Run "aiwf state update" first.');
221
- }
222
-
223
- spinner.text = 'Analyzing synchronization...';
224
-
225
- let syncCount = 0;
226
- const syncResults = [];
227
-
228
- for (const issue of issues) {
229
- // ์ด์Šˆ ์ œ๋ชฉ์—์„œ ํƒœ์Šคํฌ ID ์ถ”์ถœ
230
- const taskIdMatch = issue.title.match(/^([A-Z]\d+):/);
231
- if (taskIdMatch) {
232
- const taskId = taskIdMatch[1];
233
- const task = stateIndex.tasks[taskId];
234
-
235
- if (task) {
236
- // ์ƒํƒœ ๋™๊ธฐํ™” ํ™•์ธ
237
- const issueState = issue.state.toLowerCase();
238
- const taskState = task.status;
239
-
240
- let needsSync = false;
241
- if (issueState === 'closed' && taskState !== 'completed') {
242
- needsSync = true;
243
- } else if (issueState === 'open' && taskState === 'completed') {
244
- needsSync = true;
245
- }
246
-
247
- if (needsSync) {
248
- syncResults.push({
249
- taskId,
250
- issueNumber: issue.number,
251
- issueState,
252
- taskState,
253
- needsSync
254
- });
255
- syncCount++;
256
- }
257
- }
258
- }
259
- }
260
-
261
- spinner.succeed(`GitHub sync completed. Found ${syncCount} items needing attention.`);
262
-
263
- if (syncResults.length > 0) {
264
- console.log(chalk.cyan('\n๐Ÿ”„ Sync Status:'));
265
- for (const result of syncResults) {
266
- console.log(` ${result.taskId}: Issue #${result.issueNumber} (${result.issueState}) โ†” Task (${result.taskState})`);
267
- }
268
- console.log(chalk.yellow('\nNote: Manual review recommended for state mismatches.'));
269
- } else {
270
- console.log(chalk.green('\nโœ… All GitHub issues are in sync with AIWF tasks.'));
271
- }
272
-
273
- } catch (error) {
274
- spinner.fail(`Failed to sync GitHub issues: ${error.message}`);
275
- throw error;
276
- }
277
- }
278
-
279
- /**
280
- * ์ด์Šˆ ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ
281
- */
282
- generateIssueTemplate(task) {
283
- return `## ๐Ÿ“‹ Task: ${task.title}
284
-
285
- ### Description
286
- ${task.description || 'No description provided.'}
287
-
288
- ### Acceptance Criteria
289
- - [ ] Task implementation completed
290
- - [ ] Tests written and passing
291
- - [ ] Documentation updated
292
- - [ ] Code reviewed
293
-
294
- ### Additional Information
295
- - **Task ID**: ${task.id}
296
- - **Sprint**: ${task.sprint_id || 'N/A'}
297
- - **Priority**: ${task.priority_score?.toFixed(2) || 'N/A'}
298
- - **Estimated Hours**: ${task.estimated_hours || 'N/A'}
299
- - **Complexity**: ${task.complexity || 'N/A'}
300
-
301
- ### Task File
302
- \`${task.file_path || 'N/A'}\`
303
-
304
- ---
305
- *This issue was automatically created by AIWF*`;
306
- }
307
-
308
- /**
309
- * PR ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ
310
- */
311
- generatePRTemplate(taskId, commits, diffStat) {
312
- return `## ๐ŸŽฏ Overview
313
- ${taskId ? `Completed implementation of ${taskId}.` : 'Completed feature implementation.'}
314
-
315
- ## ๐Ÿ“ Changes
316
- \`\`\`
317
- ${commits}
318
- \`\`\`
319
-
320
- ## ๐Ÿ“Š Changed Files
321
- \`\`\`
322
- ${diffStat}
323
- \`\`\`
324
-
325
- ## โœ… Checklist
326
- - [ ] Tests pass
327
- - [ ] Code review completed
328
- - [ ] Documentation updated
329
-
330
- ## ๐Ÿ”— Related Information
331
- ${taskId ? `- Related Task: ${taskId}` : '- No specific task linked'}
332
-
333
- ---
334
- *This pull request was automatically created by AIWF*`;
335
- }
336
-
337
- /**
338
- * ํƒœ์Šคํฌ ํƒ€์ž…๊ณผ ์ƒํƒœ์— ๋”ฐ๋ฅธ ๋ผ๋ฒจ ์ƒ์„ฑ
339
- */
340
- generateLabels(task) {
341
- const labels = ['aiwf-task'];
342
-
343
- if (task.type) {
344
- labels.push(task.type);
345
- }
346
-
347
- if (task.sprint_id && task.sprint_id !== 'general') {
348
- labels.push('sprint-task');
349
- }
350
-
351
- if (task.priority_score && task.priority_score > 0.8) {
352
- labels.push('high-priority');
353
- }
354
-
355
- if (task.complexity === 'high' || task.complexity === 'very-high') {
356
- labels.push('complex');
357
- }
358
-
359
- return labels;
360
- }
361
-
362
- /**
363
- * ์ด์Šˆ URL์—์„œ ์ด์Šˆ ๋ฒˆํ˜ธ ์ถ”์ถœ
364
- */
365
- extractIssueNumber(issueUrl) {
366
- const match = issueUrl.match(/\/issues\/(\d+)$/);
367
- return match ? match[1] : null;
368
- }
369
-
370
- /**
371
- * ํƒœ์Šคํฌ ํŒŒ์ผ์— GitHub ์ด์Šˆ ์ •๋ณด ์ถ”๊ฐ€
372
- */
373
- async updateTaskWithIssue(filePath, issueNumber, issueUrl) {
374
- try {
375
- const content = await fs.readFile(filePath, 'utf8');
376
-
377
- // ์ด๋ฏธ GitHub ์ •๋ณด๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
378
- if (content.includes('github_issue:') || content.includes('GitHub Issue:')) {
379
- return; // ์ด๋ฏธ ์žˆ์œผ๋ฉด ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์Œ
380
- }
381
-
382
- // YAML frontmatter๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
383
- const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
384
-
385
- let updatedContent;
386
- if (frontmatterMatch) {
387
- // YAML frontmatter์— ์ถ”๊ฐ€
388
- const frontmatter = frontmatterMatch[1];
389
- const body = frontmatterMatch[2];
390
- const updatedFrontmatter = `${frontmatter}\ngithub_issue: ${issueNumber}\ngithub_url: ${issueUrl}`;
391
- updatedContent = `---\n${updatedFrontmatter}\n---\n${body}`;
392
- } else {
393
- // ํŒŒ์ผ ์‹œ์ž‘ ๋ถ€๋ถ„์— GitHub ์ •๋ณด ์ถ”๊ฐ€
394
- updatedContent = `<!-- GitHub Issue: #${issueNumber} - ${issueUrl} -->\n\n${content}`;
395
- }
396
-
397
- await fs.writeFile(filePath, updatedContent, 'utf8');
398
- } catch (error) {
399
- console.warn(`Failed to update task file with GitHub issue: ${error.message}`);
400
- }
401
- }
402
- }