@shin1ohno/sage 0.1.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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +168 -0
  3. package/dist/config/loader.d.ts +37 -0
  4. package/dist/config/loader.d.ts.map +1 -0
  5. package/dist/config/loader.js +95 -0
  6. package/dist/config/loader.js.map +1 -0
  7. package/dist/config/storage/file-storage.d.ts +35 -0
  8. package/dist/config/storage/file-storage.d.ts.map +1 -0
  9. package/dist/config/storage/file-storage.js +76 -0
  10. package/dist/config/storage/file-storage.js.map +1 -0
  11. package/dist/config/storage/index.d.ts +8 -0
  12. package/dist/config/storage/index.d.ts.map +1 -0
  13. package/dist/config/storage/index.js +8 -0
  14. package/dist/config/storage/index.js.map +1 -0
  15. package/dist/config/storage/session-storage.d.ts +35 -0
  16. package/dist/config/storage/session-storage.d.ts.map +1 -0
  17. package/dist/config/storage/session-storage.js +44 -0
  18. package/dist/config/storage/session-storage.js.map +1 -0
  19. package/dist/config/storage/storage-factory.d.ts +32 -0
  20. package/dist/config/storage/storage-factory.d.ts.map +1 -0
  21. package/dist/config/storage/storage-factory.js +78 -0
  22. package/dist/config/storage/storage-factory.js.map +1 -0
  23. package/dist/core/index.d.ts +6 -0
  24. package/dist/core/index.d.ts.map +1 -0
  25. package/dist/core/index.js +6 -0
  26. package/dist/core/index.js.map +1 -0
  27. package/dist/core/sage-core.d.ts +80 -0
  28. package/dist/core/sage-core.d.ts.map +1 -0
  29. package/dist/core/sage-core.js +190 -0
  30. package/dist/core/sage-core.js.map +1 -0
  31. package/dist/index.d.ts +9 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +901 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/integrations/apple-reminders.d.ts +96 -0
  36. package/dist/integrations/apple-reminders.d.ts.map +1 -0
  37. package/dist/integrations/apple-reminders.js +250 -0
  38. package/dist/integrations/apple-reminders.js.map +1 -0
  39. package/dist/integrations/calendar-service.d.ts +126 -0
  40. package/dist/integrations/calendar-service.d.ts.map +1 -0
  41. package/dist/integrations/calendar-service.js +295 -0
  42. package/dist/integrations/calendar-service.js.map +1 -0
  43. package/dist/integrations/notion-mcp.d.ts +121 -0
  44. package/dist/integrations/notion-mcp.d.ts.map +1 -0
  45. package/dist/integrations/notion-mcp.js +281 -0
  46. package/dist/integrations/notion-mcp.js.map +1 -0
  47. package/dist/integrations/reminder-manager.d.ts +90 -0
  48. package/dist/integrations/reminder-manager.d.ts.map +1 -0
  49. package/dist/integrations/reminder-manager.js +182 -0
  50. package/dist/integrations/reminder-manager.js.map +1 -0
  51. package/dist/platform/adapter-factory.d.ts +22 -0
  52. package/dist/platform/adapter-factory.d.ts.map +1 -0
  53. package/dist/platform/adapter-factory.js +41 -0
  54. package/dist/platform/adapter-factory.js.map +1 -0
  55. package/dist/platform/adapters/mcp-adapter.d.ts +32 -0
  56. package/dist/platform/adapters/mcp-adapter.d.ts.map +1 -0
  57. package/dist/platform/adapters/mcp-adapter.js +52 -0
  58. package/dist/platform/adapters/mcp-adapter.js.map +1 -0
  59. package/dist/platform/adapters/skills-adapter-ios.d.ts +38 -0
  60. package/dist/platform/adapters/skills-adapter-ios.d.ts.map +1 -0
  61. package/dist/platform/adapters/skills-adapter-ios.js +59 -0
  62. package/dist/platform/adapters/skills-adapter-ios.js.map +1 -0
  63. package/dist/platform/adapters/skills-adapter-web.d.ts +36 -0
  64. package/dist/platform/adapters/skills-adapter-web.d.ts.map +1 -0
  65. package/dist/platform/adapters/skills-adapter-web.js +56 -0
  66. package/dist/platform/adapters/skills-adapter-web.js.map +1 -0
  67. package/dist/platform/detector.d.ts +60 -0
  68. package/dist/platform/detector.d.ts.map +1 -0
  69. package/dist/platform/detector.js +217 -0
  70. package/dist/platform/detector.js.map +1 -0
  71. package/dist/platform/index.d.ts +11 -0
  72. package/dist/platform/index.d.ts.map +1 -0
  73. package/dist/platform/index.js +11 -0
  74. package/dist/platform/index.js.map +1 -0
  75. package/dist/platform/types.d.ts +205 -0
  76. package/dist/platform/types.d.ts.map +1 -0
  77. package/dist/platform/types.js +33 -0
  78. package/dist/platform/types.js.map +1 -0
  79. package/dist/setup/questions.d.ts +15 -0
  80. package/dist/setup/questions.d.ts.map +1 -0
  81. package/dist/setup/questions.js +131 -0
  82. package/dist/setup/questions.js.map +1 -0
  83. package/dist/setup/wizard.d.ts +51 -0
  84. package/dist/setup/wizard.d.ts.map +1 -0
  85. package/dist/setup/wizard.js +210 -0
  86. package/dist/setup/wizard.js.map +1 -0
  87. package/dist/tools/analyze-tasks.d.ts +61 -0
  88. package/dist/tools/analyze-tasks.d.ts.map +1 -0
  89. package/dist/tools/analyze-tasks.js +258 -0
  90. package/dist/tools/analyze-tasks.js.map +1 -0
  91. package/dist/types/config.d.ts +126 -0
  92. package/dist/types/config.d.ts.map +1 -0
  93. package/dist/types/config.js +118 -0
  94. package/dist/types/config.js.map +1 -0
  95. package/dist/types/errors.d.ts +39 -0
  96. package/dist/types/errors.d.ts.map +1 -0
  97. package/dist/types/errors.js +83 -0
  98. package/dist/types/errors.js.map +1 -0
  99. package/dist/types/index.d.ts +7 -0
  100. package/dist/types/index.d.ts.map +1 -0
  101. package/dist/types/index.js +7 -0
  102. package/dist/types/index.js.map +1 -0
  103. package/dist/types/task.d.ts +69 -0
  104. package/dist/types/task.d.ts.map +1 -0
  105. package/dist/types/task.js +5 -0
  106. package/dist/types/task.js.map +1 -0
  107. package/dist/utils/estimation.d.ts +49 -0
  108. package/dist/utils/estimation.d.ts.map +1 -0
  109. package/dist/utils/estimation.js +244 -0
  110. package/dist/utils/estimation.js.map +1 -0
  111. package/dist/utils/priority.d.ts +68 -0
  112. package/dist/utils/priority.d.ts.map +1 -0
  113. package/dist/utils/priority.js +243 -0
  114. package/dist/utils/priority.js.map +1 -0
  115. package/dist/utils/retry.d.ts +62 -0
  116. package/dist/utils/retry.d.ts.map +1 -0
  117. package/dist/utils/retry.js +161 -0
  118. package/dist/utils/retry.js.map +1 -0
  119. package/dist/utils/stakeholders.d.ts +61 -0
  120. package/dist/utils/stakeholders.d.ts.map +1 -0
  121. package/dist/utils/stakeholders.js +301 -0
  122. package/dist/utils/stakeholders.js.map +1 -0
  123. package/dist/utils/task-splitter.d.ts +45 -0
  124. package/dist/utils/task-splitter.d.ts.map +1 -0
  125. package/dist/utils/task-splitter.js +321 -0
  126. package/dist/utils/task-splitter.js.map +1 -0
  127. package/package.json +66 -0
@@ -0,0 +1,301 @@
1
+ /**
2
+ * Stakeholder Extraction System
3
+ * Identifies and extracts stakeholders from task content
4
+ * Requirements: 4.1-4.5
5
+ */
6
+ // Manager keywords
7
+ const MANAGER_KEYWORDS = [
8
+ 'manager',
9
+ 'マネージャー',
10
+ '上司',
11
+ 'boss',
12
+ 'supervisor',
13
+ '管理者',
14
+ 'director',
15
+ 'ディレクター',
16
+ 'lead',
17
+ 'リーダー',
18
+ 'team lead',
19
+ 'チームリード',
20
+ ];
21
+ // Mention patterns
22
+ const MENTION_PATTERNS = [
23
+ /@(\w+)/g, // @username
24
+ /@([^\s]+さん)/g, // @名前さん (Japanese)
25
+ /(?:from|by|with|to|cc|CC)\s+(\w+)/gi, // from/by/with person
26
+ /(?:から|と|へ|宛)\s*([^\s、]+(?:さん|様)?)/g, // Japanese particles
27
+ ];
28
+ export class StakeholderExtractor {
29
+ /**
30
+ * Extract stakeholders from a task
31
+ * Requirement: 4.1, 4.5
32
+ */
33
+ static extractStakeholders(task, teamConfig) {
34
+ const text = `${task.title} ${task.description ?? ''}`;
35
+ const stakeholders = [];
36
+ const matchedTeamMembers = [];
37
+ // Extract @mentions
38
+ const mentions = this.findMentions(text);
39
+ stakeholders.push(...mentions);
40
+ // Match against team members
41
+ if (teamConfig) {
42
+ const matched = this.matchTeamMembers(text, teamConfig);
43
+ for (const member of matched) {
44
+ if (!stakeholders.includes(member.name)) {
45
+ stakeholders.push(member.name);
46
+ matchedTeamMembers.push(member);
47
+ }
48
+ }
49
+ }
50
+ // Check for manager involvement
51
+ const managerInvolved = this.checkManagerInvolvement(text, teamConfig);
52
+ // Add manager to stakeholders if involved
53
+ if (managerInvolved && teamConfig?.manager) {
54
+ if (!stakeholders.includes(teamConfig.manager.name)) {
55
+ stakeholders.push(teamConfig.manager.name);
56
+ matchedTeamMembers.push(teamConfig.manager);
57
+ }
58
+ }
59
+ return {
60
+ stakeholders,
61
+ managerInvolved,
62
+ reason: this.buildReason(stakeholders, managerInvolved, mentions),
63
+ mentions,
64
+ matchedTeamMembers,
65
+ };
66
+ }
67
+ /**
68
+ * Find @mentions in text
69
+ * Requirement: 4.3
70
+ */
71
+ static findMentions(text) {
72
+ const mentions = new Set();
73
+ for (const pattern of MENTION_PATTERNS) {
74
+ // Reset lastIndex for global patterns
75
+ pattern.lastIndex = 0;
76
+ let match;
77
+ while ((match = pattern.exec(text)) !== null) {
78
+ const mention = match[1].trim();
79
+ // Filter out common false positives
80
+ if (mention.length > 1 && !this.isCommonWord(mention)) {
81
+ mentions.add(mention);
82
+ }
83
+ }
84
+ }
85
+ return Array.from(mentions);
86
+ }
87
+ /**
88
+ * Match text against configured team members
89
+ * Requirement: 4.2
90
+ */
91
+ static matchTeamMembers(text, teamConfig) {
92
+ const lowerText = text.toLowerCase();
93
+ const matched = [];
94
+ // Check manager
95
+ if (teamConfig.manager) {
96
+ if (this.memberMatchesText(teamConfig.manager, lowerText)) {
97
+ matched.push(teamConfig.manager);
98
+ }
99
+ }
100
+ // Check frequent collaborators
101
+ for (const collaborator of teamConfig.frequentCollaborators) {
102
+ if (this.memberMatchesText(collaborator, lowerText)) {
103
+ matched.push(collaborator);
104
+ }
105
+ }
106
+ return matched;
107
+ }
108
+ /**
109
+ * Check if a team member matches the text
110
+ */
111
+ static memberMatchesText(member, lowerText) {
112
+ // Check name
113
+ if (lowerText.includes(member.name.toLowerCase())) {
114
+ return true;
115
+ }
116
+ // Check keywords
117
+ for (const keyword of member.keywords) {
118
+ if (lowerText.includes(keyword.toLowerCase())) {
119
+ return true;
120
+ }
121
+ }
122
+ return false;
123
+ }
124
+ /**
125
+ * Check if manager is involved in the task
126
+ * Requirement: 4.4
127
+ */
128
+ static checkManagerInvolvement(text, teamConfig) {
129
+ const lowerText = text.toLowerCase();
130
+ // Check generic manager keywords
131
+ if (MANAGER_KEYWORDS.some((keyword) => lowerText.includes(keyword.toLowerCase()))) {
132
+ return true;
133
+ }
134
+ // Check configured manager
135
+ if (teamConfig?.manager) {
136
+ if (lowerText.includes(teamConfig.manager.name.toLowerCase())) {
137
+ return true;
138
+ }
139
+ for (const keyword of teamConfig.manager.keywords) {
140
+ if (lowerText.includes(keyword.toLowerCase())) {
141
+ return true;
142
+ }
143
+ }
144
+ }
145
+ return false;
146
+ }
147
+ /**
148
+ * Check if a word is a common word (false positive)
149
+ */
150
+ static isCommonWord(word) {
151
+ const commonWords = [
152
+ 'the',
153
+ 'a',
154
+ 'an',
155
+ 'to',
156
+ 'from',
157
+ 'with',
158
+ 'by',
159
+ 'for',
160
+ 'in',
161
+ 'on',
162
+ 'at',
163
+ 'it',
164
+ 'is',
165
+ 'are',
166
+ 'was',
167
+ 'were',
168
+ 'be',
169
+ 'been',
170
+ 'being',
171
+ 'have',
172
+ 'has',
173
+ 'had',
174
+ 'do',
175
+ 'does',
176
+ 'did',
177
+ 'will',
178
+ 'would',
179
+ 'could',
180
+ 'should',
181
+ 'may',
182
+ 'might',
183
+ 'must',
184
+ 'shall',
185
+ 'can',
186
+ 'need',
187
+ 'dare',
188
+ 'ought',
189
+ 'used',
190
+ 'this',
191
+ 'that',
192
+ 'these',
193
+ 'those',
194
+ 'の',
195
+ 'に',
196
+ 'を',
197
+ 'で',
198
+ 'が',
199
+ 'は',
200
+ ];
201
+ return commonWords.includes(word.toLowerCase());
202
+ }
203
+ /**
204
+ * Build a human-readable reason
205
+ */
206
+ static buildReason(stakeholders, managerInvolved, mentions) {
207
+ if (stakeholders.length === 0) {
208
+ return '関係者は検出されませんでした';
209
+ }
210
+ const parts = [];
211
+ if (mentions.length > 0) {
212
+ parts.push(`@メンションから${mentions.length}名を検出`);
213
+ }
214
+ if (managerInvolved) {
215
+ parts.push('マネージャーが関与');
216
+ }
217
+ const nonMentionCount = stakeholders.length - mentions.length;
218
+ if (nonMentionCount > 0 && !managerInvolved) {
219
+ parts.push(`チームメンバーから${nonMentionCount}名を検出`);
220
+ }
221
+ return parts.join('、') || `${stakeholders.length}名の関係者を検出`;
222
+ }
223
+ /**
224
+ * Get priority boost for manager involvement
225
+ */
226
+ static getManagerPriorityBoost() {
227
+ return 1; // Boost priority by 1 level (e.g., P2 -> P1)
228
+ }
229
+ /**
230
+ * Extract all names from text (broader matching)
231
+ */
232
+ static extractPotentialNames(text) {
233
+ const names = new Set();
234
+ // Japanese name patterns (漢字 + さん/様/氏)
235
+ const japaneseNamePattern = /([一-龯]{2,4})(さん|様|氏)/g;
236
+ let match;
237
+ while ((match = japaneseNamePattern.exec(text)) !== null) {
238
+ names.add(match[1]);
239
+ }
240
+ // English capitalized names
241
+ const englishNamePattern = /\b([A-Z][a-z]+(?:\s+[A-Z][a-z]+)?)\b/g;
242
+ while ((match = englishNamePattern.exec(text)) !== null) {
243
+ const name = match[1];
244
+ // Filter out common non-names
245
+ if (!this.isCommonCapitalizedWord(name)) {
246
+ names.add(name);
247
+ }
248
+ }
249
+ return Array.from(names);
250
+ }
251
+ /**
252
+ * Check if a capitalized word is commonly not a name
253
+ */
254
+ static isCommonCapitalizedWord(word) {
255
+ const commonWords = [
256
+ 'Monday',
257
+ 'Tuesday',
258
+ 'Wednesday',
259
+ 'Thursday',
260
+ 'Friday',
261
+ 'Saturday',
262
+ 'Sunday',
263
+ 'January',
264
+ 'February',
265
+ 'March',
266
+ 'April',
267
+ 'May',
268
+ 'June',
269
+ 'July',
270
+ 'August',
271
+ 'September',
272
+ 'October',
273
+ 'November',
274
+ 'December',
275
+ 'The',
276
+ 'This',
277
+ 'That',
278
+ 'Please',
279
+ 'Thanks',
280
+ 'Hello',
281
+ 'Hi',
282
+ 'Dear',
283
+ 'Task',
284
+ 'Project',
285
+ 'Meeting',
286
+ 'Review',
287
+ 'Update',
288
+ 'Urgent',
289
+ 'Important',
290
+ 'TODO',
291
+ 'FIXME',
292
+ 'NOTE',
293
+ 'API',
294
+ 'UI',
295
+ 'PR',
296
+ 'MR',
297
+ ];
298
+ return commonWords.includes(word);
299
+ }
300
+ }
301
+ //# sourceMappingURL=stakeholders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stakeholders.js","sourceRoot":"","sources":["../../src/utils/stakeholders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Task Splitter
3
+ * Splits complex tasks or multiple tasks into manageable pieces
4
+ * Requirements: 11.1-11.6
5
+ */
6
+ import type { Task, SplitResult, ComplexityAnalysis } from '../types/index.js';
7
+ export declare class TaskSplitter {
8
+ /**
9
+ * Split input text into individual tasks
10
+ * Requirement: 11.1, 11.4
11
+ */
12
+ static splitTasks(input: string): SplitResult;
13
+ /**
14
+ * Analyze task complexity
15
+ * Requirement: 11.2, 11.3
16
+ */
17
+ static analyzeComplexity(task: Task): ComplexityAnalysis;
18
+ /**
19
+ * Split input into individual lines/items
20
+ */
21
+ private static splitIntoLines;
22
+ /**
23
+ * Check if input contains multiple tasks
24
+ */
25
+ private static containsMultipleTasks;
26
+ /**
27
+ * Suggest splits for project-level tasks
28
+ */
29
+ private static suggestProjectSplits;
30
+ /**
31
+ * Suggest splits for complex tasks
32
+ */
33
+ private static suggestComplexSplits;
34
+ /**
35
+ * Infer dependencies between tasks
36
+ * Requirement: 11.5
37
+ */
38
+ private static inferDependencies;
39
+ /**
40
+ * Calculate recommended execution order
41
+ * Requirement: 11.6
42
+ */
43
+ private static calculateRecommendedOrder;
44
+ }
45
+ //# sourceMappingURL=task-splitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-splitter.d.ts","sourceRoot":"","sources":["../../src/utils/task-splitter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,IAAI,EAEJ,WAAW,EACX,kBAAkB,EAEnB,MAAM,mBAAmB,CAAC;AA6E3B,qBAAa,YAAY;IACvB;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW;IAgD7C;;;OAGG;IACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB;IAwCxD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IA2B7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAOpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IA8BnC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAoBnC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAkDhC;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,yBAAyB;CAuBzC"}
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Task Splitter
3
+ * Splits complex tasks or multiple tasks into manageable pieces
4
+ * Requirements: 11.1-11.6
5
+ */
6
+ // Patterns that indicate multiple tasks
7
+ const MULTI_TASK_PATTERNS = [
8
+ /(?:^|\n)\s*[-•*]\s+/g, // Bullet points
9
+ /(?:^|\n)\s*\d+[.)]\s+/g, // Numbered lists
10
+ /(?:そして|また|さらに|加えて|それから)/g, // Japanese conjunctions
11
+ /(?:and then|also|additionally|furthermore|moreover)/gi, // English conjunctions
12
+ /[。.]\s*(?=[^。.]+[。.])/g, // Sentence boundaries with more content
13
+ ];
14
+ // Keywords indicating complex tasks
15
+ const COMPLEXITY_KEYWORDS = {
16
+ project: [
17
+ 'システム',
18
+ 'アーキテクチャ',
19
+ '設計',
20
+ '構築',
21
+ 'プロジェクト',
22
+ 'system',
23
+ 'architecture',
24
+ 'design',
25
+ 'build',
26
+ 'project',
27
+ 'develop',
28
+ '開発',
29
+ ],
30
+ complex: [
31
+ 'リファクタ',
32
+ '統合',
33
+ '移行',
34
+ 'マイグレーション',
35
+ '最適化',
36
+ 'refactor',
37
+ 'integrate',
38
+ 'migrate',
39
+ 'migration',
40
+ 'optimize',
41
+ 'implement',
42
+ '実装',
43
+ ],
44
+ medium: [
45
+ '修正',
46
+ '更新',
47
+ '変更',
48
+ '追加',
49
+ '作成',
50
+ 'fix',
51
+ 'update',
52
+ 'change',
53
+ 'add',
54
+ 'create',
55
+ 'modify',
56
+ ],
57
+ simple: [
58
+ '確認',
59
+ 'レビュー',
60
+ 'チェック',
61
+ '読む',
62
+ '返信',
63
+ 'confirm',
64
+ 'review',
65
+ 'check',
66
+ 'read',
67
+ 'reply',
68
+ 'send',
69
+ '送信',
70
+ ],
71
+ };
72
+ // Dependency indicator keywords
73
+ const DEPENDENCY_KEYWORDS = {
74
+ before: ['前に', '先に', 'まず', 'before', 'first', 'prior to'],
75
+ after: ['後に', '次に', 'その後', 'after', 'then', 'following'],
76
+ requires: ['必要', '依存', 'requires', 'depends on', 'needs'],
77
+ };
78
+ export class TaskSplitter {
79
+ /**
80
+ * Split input text into individual tasks
81
+ * Requirement: 11.1, 11.4
82
+ */
83
+ static splitTasks(input) {
84
+ const tasks = [];
85
+ const lines = this.splitIntoLines(input);
86
+ if (lines.length === 1 && !this.containsMultipleTasks(input)) {
87
+ // Single task - check if it needs complexity-based splitting
88
+ const task = { title: input.trim() };
89
+ const complexity = this.analyzeComplexity(task);
90
+ if (complexity.isComplex && complexity.suggestedSplits) {
91
+ return {
92
+ originalInput: input,
93
+ splitTasks: complexity.suggestedSplits,
94
+ splitReason: complexity.reasoning,
95
+ recommendedOrder: complexity.suggestedSplits.map((_, i) => i),
96
+ dependencies: this.inferDependencies(complexity.suggestedSplits),
97
+ };
98
+ }
99
+ return {
100
+ originalInput: input,
101
+ splitTasks: [task],
102
+ splitReason: 'シンプルなタスクのため分割不要',
103
+ recommendedOrder: [0],
104
+ dependencies: [],
105
+ };
106
+ }
107
+ // Multiple lines/tasks detected
108
+ for (const line of lines) {
109
+ const trimmed = line.trim();
110
+ if (trimmed) {
111
+ tasks.push({ title: trimmed });
112
+ }
113
+ }
114
+ const dependencies = this.inferDependencies(tasks);
115
+ const recommendedOrder = this.calculateRecommendedOrder(tasks, dependencies);
116
+ return {
117
+ originalInput: input,
118
+ splitTasks: tasks,
119
+ splitReason: `${tasks.length}個のタスクを検出しました`,
120
+ recommendedOrder,
121
+ dependencies,
122
+ };
123
+ }
124
+ /**
125
+ * Analyze task complexity
126
+ * Requirement: 11.2, 11.3
127
+ */
128
+ static analyzeComplexity(task) {
129
+ const text = `${task.title} ${task.description ?? ''}`.toLowerCase();
130
+ // Check for project-level complexity
131
+ if (COMPLEXITY_KEYWORDS.project.some((k) => text.includes(k.toLowerCase()))) {
132
+ return {
133
+ isComplex: true,
134
+ complexity: 'project',
135
+ suggestedSplits: this.suggestProjectSplits(task),
136
+ reasoning: 'プロジェクトレベルのタスクです。複数のフェーズに分割することを推奨します。',
137
+ };
138
+ }
139
+ // Check for complex tasks
140
+ if (COMPLEXITY_KEYWORDS.complex.some((k) => text.includes(k.toLowerCase()))) {
141
+ return {
142
+ isComplex: true,
143
+ complexity: 'complex',
144
+ suggestedSplits: this.suggestComplexSplits(task),
145
+ reasoning: '複雑なタスクです。より小さなステップに分割することを推奨します。',
146
+ };
147
+ }
148
+ // Check for medium tasks
149
+ if (COMPLEXITY_KEYWORDS.medium.some((k) => text.includes(k.toLowerCase()))) {
150
+ return {
151
+ isComplex: false,
152
+ complexity: 'medium',
153
+ reasoning: '中程度の複雑さのタスクです。そのまま実行可能です。',
154
+ };
155
+ }
156
+ // Simple task
157
+ return {
158
+ isComplex: false,
159
+ complexity: 'simple',
160
+ reasoning: 'シンプルなタスクです。分割は不要です。',
161
+ };
162
+ }
163
+ /**
164
+ * Split input into individual lines/items
165
+ */
166
+ static splitIntoLines(input) {
167
+ // First, try to split by bullet points or numbered lists
168
+ const bulletSplit = input.split(/(?:^|\n)\s*[-•*]\s+/).filter(Boolean);
169
+ if (bulletSplit.length > 1) {
170
+ return bulletSplit.map((s) => s.trim());
171
+ }
172
+ const numberedSplit = input.split(/(?:^|\n)\s*\d+[.)]\s+/).filter(Boolean);
173
+ if (numberedSplit.length > 1) {
174
+ return numberedSplit.map((s) => s.trim());
175
+ }
176
+ // Try splitting by Japanese conjunctions
177
+ const conjunctionSplit = input.split(/(?:そして|また|さらに|加えて|それから)/);
178
+ if (conjunctionSplit.length > 1) {
179
+ return conjunctionSplit.map((s) => s.trim()).filter(Boolean);
180
+ }
181
+ // Split by newlines
182
+ const newlineSplit = input.split('\n').filter((s) => s.trim());
183
+ if (newlineSplit.length > 1) {
184
+ return newlineSplit;
185
+ }
186
+ return [input];
187
+ }
188
+ /**
189
+ * Check if input contains multiple tasks
190
+ */
191
+ static containsMultipleTasks(input) {
192
+ return MULTI_TASK_PATTERNS.some((pattern) => {
193
+ const matches = input.match(pattern);
194
+ return matches && matches.length > 1;
195
+ });
196
+ }
197
+ /**
198
+ * Suggest splits for project-level tasks
199
+ */
200
+ static suggestProjectSplits(task) {
201
+ return [
202
+ {
203
+ title: `${task.title} - 要件定義と計画`,
204
+ order: 0,
205
+ status: 'not_started',
206
+ },
207
+ {
208
+ title: `${task.title} - 設計とアーキテクチャ`,
209
+ order: 1,
210
+ status: 'not_started',
211
+ },
212
+ {
213
+ title: `${task.title} - 実装`,
214
+ order: 2,
215
+ status: 'not_started',
216
+ },
217
+ {
218
+ title: `${task.title} - テストと検証`,
219
+ order: 3,
220
+ status: 'not_started',
221
+ },
222
+ {
223
+ title: `${task.title} - デプロイとドキュメント`,
224
+ order: 4,
225
+ status: 'not_started',
226
+ },
227
+ ];
228
+ }
229
+ /**
230
+ * Suggest splits for complex tasks
231
+ */
232
+ static suggestComplexSplits(task) {
233
+ return [
234
+ {
235
+ title: `${task.title} - 調査と準備`,
236
+ order: 0,
237
+ status: 'not_started',
238
+ },
239
+ {
240
+ title: `${task.title} - 実装`,
241
+ order: 1,
242
+ status: 'not_started',
243
+ },
244
+ {
245
+ title: `${task.title} - 確認とテスト`,
246
+ order: 2,
247
+ status: 'not_started',
248
+ },
249
+ ];
250
+ }
251
+ /**
252
+ * Infer dependencies between tasks
253
+ * Requirement: 11.5
254
+ */
255
+ static inferDependencies(tasks) {
256
+ const dependencies = [];
257
+ for (let i = 0; i < tasks.length; i++) {
258
+ const task = tasks[i];
259
+ const text = `${task.title} ${task.description ?? ''}`.toLowerCase();
260
+ const dependsOn = [];
261
+ // Check for explicit dependency keywords
262
+ for (const [type, keywords] of Object.entries(DEPENDENCY_KEYWORDS)) {
263
+ if (keywords.some((k) => text.includes(k.toLowerCase()))) {
264
+ if (type === 'after' && i > 0) {
265
+ dependsOn.push(i - 1);
266
+ }
267
+ if (type === 'requires' && i > 0) {
268
+ // Look for references to previous tasks
269
+ for (let j = 0; j < i; j++) {
270
+ const prevTitle = tasks[j].title.toLowerCase();
271
+ if (text.includes(prevTitle.substring(0, 10))) {
272
+ dependsOn.push(j);
273
+ }
274
+ }
275
+ }
276
+ }
277
+ }
278
+ if (dependsOn.length > 0) {
279
+ dependencies.push({
280
+ taskIndex: i,
281
+ dependsOn,
282
+ type: 'sequential',
283
+ });
284
+ }
285
+ }
286
+ // If no explicit dependencies found, assume sequential order
287
+ if (dependencies.length === 0 && tasks.length > 1) {
288
+ for (let i = 1; i < tasks.length; i++) {
289
+ dependencies.push({
290
+ taskIndex: i,
291
+ dependsOn: [i - 1],
292
+ type: 'sequential',
293
+ });
294
+ }
295
+ }
296
+ return dependencies;
297
+ }
298
+ /**
299
+ * Calculate recommended execution order
300
+ * Requirement: 11.6
301
+ */
302
+ static calculateRecommendedOrder(tasks, dependencies) {
303
+ const order = [];
304
+ const completed = new Set();
305
+ // Note: Circular dependencies cannot occur with current inferDependencies
306
+ // implementation as it only references previous tasks
307
+ while (order.length < tasks.length) {
308
+ for (let i = 0; i < tasks.length; i++) {
309
+ if (completed.has(i))
310
+ continue;
311
+ const dep = dependencies.find((d) => d.taskIndex === i);
312
+ if (!dep || dep.dependsOn.every((d) => completed.has(d))) {
313
+ order.push(i);
314
+ completed.add(i);
315
+ }
316
+ }
317
+ }
318
+ return order;
319
+ }
320
+ }
321
+ //# sourceMappingURL=task-splitter.js.map