maskweaver 0.9.3 → 0.9.5

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 (246) hide show
  1. package/README.ko.md +279 -325
  2. package/README.md +109 -113
  3. package/assets/commands/meta/commands.json +34 -34
  4. package/assets/commands/weave-agents.md +12 -52
  5. package/assets/commands/weave-approve.md +12 -51
  6. package/assets/commands/weave-archive.md +21 -0
  7. package/assets/commands/weave-build.md +20 -89
  8. package/assets/commands/weave-craft.md +22 -43
  9. package/assets/commands/weave-help.md +37 -106
  10. package/assets/commands/weave-init.md +26 -108
  11. package/assets/commands/weave-interview.md +13 -111
  12. package/assets/commands/weave-map.md +13 -99
  13. package/assets/commands/weave-prepare.md +23 -69
  14. package/assets/commands/weave-refine-plan.md +26 -59
  15. package/assets/commands/weave-repair.md +22 -70
  16. package/assets/commands/weave-status.md +22 -155
  17. package/assets/commands/weave-troubleshoot.md +11 -47
  18. package/assets/commands/weave-verify.md +23 -44
  19. package/assets/commands/weave-worktree.md +27 -69
  20. package/dist/cli/doctor.js +5 -21
  21. package/dist/cli/install.d.ts +0 -8
  22. package/dist/cli/install.js +0 -39
  23. package/dist/context/config.d.ts +0 -22
  24. package/dist/context/config.js +0 -28
  25. package/dist/context/feature.d.ts +0 -39
  26. package/dist/context/feature.js +0 -77
  27. package/dist/context/files.d.ts +0 -13
  28. package/dist/context/files.js +1 -24
  29. package/dist/context/index.d.ts +0 -7
  30. package/dist/context/index.js +0 -12
  31. package/dist/context/project.d.ts +0 -21
  32. package/dist/context/project.js +0 -30
  33. package/dist/context/types.d.ts +0 -48
  34. package/dist/context/types.js +0 -12
  35. package/dist/context/utils.d.ts +0 -18
  36. package/dist/context/utils.js +0 -27
  37. package/dist/core/engine/promptBuilder.d.ts +0 -17
  38. package/dist/core/engine/promptBuilder.js +0 -28
  39. package/dist/core/index.d.ts +0 -6
  40. package/dist/core/index.js +0 -9
  41. package/dist/core/loader/MaskLoader.d.ts +0 -23
  42. package/dist/core/loader/MaskLoader.js +0 -29
  43. package/dist/core/schema/types.d.ts +0 -47
  44. package/dist/core/schema/types.js +0 -6
  45. package/dist/core/schema/validator.d.ts +0 -14
  46. package/dist/core/schema/validator.js +0 -18
  47. package/dist/i18n/index.d.ts +0 -18
  48. package/dist/i18n/index.js +4 -23
  49. package/dist/index.d.ts +0 -8
  50. package/dist/index.js +0 -8
  51. package/dist/lib.d.ts +0 -5
  52. package/dist/lib.js +0 -12
  53. package/dist/memory/chunking.d.ts +0 -22
  54. package/dist/memory/chunking.js +2 -37
  55. package/dist/memory/core.d.ts +0 -29
  56. package/dist/memory/core.js +1 -52
  57. package/dist/memory/index.d.ts +0 -5
  58. package/dist/memory/index.js +0 -10
  59. package/dist/memory/indexer.d.ts +0 -21
  60. package/dist/memory/indexer.js +0 -44
  61. package/dist/memory/providers/examples.d.ts +0 -5
  62. package/dist/memory/providers/examples.js +4 -64
  63. package/dist/memory/providers/factory.d.ts +0 -44
  64. package/dist/memory/providers/factory.js +0 -46
  65. package/dist/memory/providers/index.d.ts +0 -26
  66. package/dist/memory/providers/index.js +0 -28
  67. package/dist/memory/providers/ollama.d.ts +0 -6
  68. package/dist/memory/providers/ollama.js +1 -8
  69. package/dist/memory/providers/openai.d.ts +0 -6
  70. package/dist/memory/providers/openai.js +1 -8
  71. package/dist/memory/providers/openrouter.d.ts +0 -6
  72. package/dist/memory/providers/openrouter.js +0 -8
  73. package/dist/memory/providers/text-only.d.ts +0 -13
  74. package/dist/memory/providers/text-only.js +0 -17
  75. package/dist/memory/providers/types.d.ts +0 -39
  76. package/dist/memory/providers/types.js +0 -7
  77. package/dist/memory/providers/voyage.d.ts +0 -22
  78. package/dist/memory/providers/voyage.js +1 -24
  79. package/dist/memory/search/hybrid.d.ts +0 -12
  80. package/dist/memory/search/hybrid.js +1 -22
  81. package/dist/memory/store/sqlite.d.ts +0 -72
  82. package/dist/memory/store/sqlite.js +4 -127
  83. package/dist/plugin/config/index.d.ts +0 -112
  84. package/dist/plugin/config/index.js +0 -115
  85. package/dist/plugin/index.d.ts +0 -13
  86. package/dist/plugin/index.js +1 -124
  87. package/dist/plugin/tools/command-registry.d.ts +0 -6
  88. package/dist/plugin/tools/command-registry.js +0 -14
  89. package/dist/plugin/tools/context.d.ts +0 -12
  90. package/dist/plugin/tools/context.js +0 -58
  91. package/dist/plugin/tools/maskSave.d.ts +0 -3
  92. package/dist/plugin/tools/maskSave.js +0 -3
  93. package/dist/plugin/tools/memoryGet.d.ts +0 -3
  94. package/dist/plugin/tools/memoryGet.js +0 -3
  95. package/dist/plugin/tools/memoryIndexer.d.ts +0 -3
  96. package/dist/plugin/tools/memoryIndexer.js +0 -10
  97. package/dist/plugin/tools/memorySearch.d.ts +0 -31
  98. package/dist/plugin/tools/memorySearch.js +0 -79
  99. package/dist/plugin/tools/memoryWrite.d.ts +0 -8
  100. package/dist/plugin/tools/memoryWrite.js +0 -32
  101. package/dist/plugin/tools/retrospect.d.ts +0 -3
  102. package/dist/plugin/tools/retrospect.js +0 -3
  103. package/dist/plugin/tools/slashcommand.d.ts +0 -11
  104. package/dist/plugin/tools/slashcommand.js +0 -38
  105. package/dist/plugin/tools/squad.d.ts +0 -12
  106. package/dist/plugin/tools/squad.js +11 -83
  107. package/dist/plugin/tools/weave.d.ts +0 -6
  108. package/dist/plugin/tools/weave.js +0 -78
  109. package/dist/plugin/types.d.ts +0 -20
  110. package/dist/plugin/types.js +0 -7
  111. package/dist/retrospect/index.d.ts +0 -7
  112. package/dist/retrospect/index.js +0 -9
  113. package/dist/retrospect/mask-save.d.ts +0 -12
  114. package/dist/retrospect/mask-save.js +1 -80
  115. package/dist/retrospect/retrospect.d.ts +0 -18
  116. package/dist/retrospect/retrospect.js +0 -63
  117. package/dist/retrospect/strategies/base.d.ts +0 -15
  118. package/dist/retrospect/strategies/base.js +0 -7
  119. package/dist/retrospect/strategies/deep.d.ts +0 -12
  120. package/dist/retrospect/strategies/deep.js +0 -24
  121. package/dist/retrospect/strategies/index.d.ts +0 -12
  122. package/dist/retrospect/strategies/index.js +0 -12
  123. package/dist/retrospect/strategies/quick.d.ts +0 -12
  124. package/dist/retrospect/strategies/quick.js +0 -19
  125. package/dist/retrospect/strategies/standard.d.ts +0 -12
  126. package/dist/retrospect/strategies/standard.js +0 -15
  127. package/dist/retrospect/types.d.ts +0 -7
  128. package/dist/retrospect/types.js +0 -7
  129. package/dist/shared/config.d.ts +0 -105
  130. package/dist/shared/config.js +0 -33
  131. package/dist/shared/errors.d.ts +0 -18
  132. package/dist/shared/errors.js +0 -19
  133. package/dist/shared/generate-agents.d.ts +0 -69
  134. package/dist/shared/generate-agents.js +2 -86
  135. package/dist/shared/image.d.ts +0 -67
  136. package/dist/shared/image.js +6 -104
  137. package/dist/shared/index.d.ts +0 -5
  138. package/dist/shared/index.js +0 -7
  139. package/dist/shared/model-registry.d.ts +0 -72
  140. package/dist/shared/model-registry.js +5 -95
  141. package/dist/shared/types.d.ts +0 -15
  142. package/dist/shared/types.js +0 -3
  143. package/dist/shared-context/dag.d.ts +0 -105
  144. package/dist/shared-context/dag.js +3 -114
  145. package/dist/shared-context/index.d.ts +0 -5
  146. package/dist/shared-context/index.js +0 -15
  147. package/dist/shared-context/logger.d.ts +0 -37
  148. package/dist/shared-context/logger.js +0 -41
  149. package/dist/shared-context/parallel-executor.d.ts +0 -54
  150. package/dist/shared-context/parallel-executor.js +4 -56
  151. package/dist/shared-context/session.d.ts +0 -56
  152. package/dist/shared-context/session.js +0 -47
  153. package/dist/shared-context/squad.d.ts +0 -68
  154. package/dist/shared-context/squad.js +0 -63
  155. package/dist/shared-context/storage.d.ts +0 -132
  156. package/dist/shared-context/storage.js +0 -116
  157. package/dist/shared-context/task.d.ts +0 -120
  158. package/dist/shared-context/task.js +0 -152
  159. package/dist/shared-context/test/dag.test.js +9 -14
  160. package/dist/shared-context/test/logger.test.d.ts +0 -8
  161. package/dist/shared-context/test/logger.test.js +0 -52
  162. package/dist/shared-context/test/session.test.d.ts +0 -7
  163. package/dist/shared-context/test/session.test.js +0 -63
  164. package/dist/shared-context/test/squad.test.d.ts +0 -10
  165. package/dist/shared-context/test/squad.test.js +2 -68
  166. package/dist/shared-context/test/storage.test.d.ts +0 -8
  167. package/dist/shared-context/test/storage.test.js +0 -68
  168. package/dist/shared-context/test/task.test.d.ts +0 -7
  169. package/dist/shared-context/test/task.test.js +0 -54
  170. package/dist/shared-context/test/watchdog.test.d.ts +0 -7
  171. package/dist/shared-context/test/watchdog.test.js +3 -58
  172. package/dist/shared-context/types.d.ts +0 -215
  173. package/dist/shared-context/types.js +0 -125
  174. package/dist/shared-context/watchdog.d.ts +0 -127
  175. package/dist/shared-context/watchdog.js +0 -148
  176. package/dist/shared-context/worktree.d.ts +0 -68
  177. package/dist/shared-context/worktree.js +2 -34
  178. package/dist/verify/budget.d.ts +0 -29
  179. package/dist/verify/budget.js +0 -34
  180. package/dist/verify/critical-files.d.ts +0 -17
  181. package/dist/verify/critical-files.js +0 -37
  182. package/dist/verify/escalation.d.ts +0 -20
  183. package/dist/verify/escalation.js +0 -22
  184. package/dist/verify/index.d.ts +0 -5
  185. package/dist/verify/index.js +0 -11
  186. package/dist/verify/prompts.d.ts +0 -20
  187. package/dist/verify/prompts.js +0 -20
  188. package/dist/verify/types.d.ts +0 -26
  189. package/dist/verify/types.js +1 -12
  190. package/dist/verify/verifier.d.ts +0 -29
  191. package/dist/verify/verifier.js +0 -54
  192. package/dist/version.d.ts +1 -16
  193. package/dist/version.js +1 -16
  194. package/dist/weave/bridge.d.ts +0 -35
  195. package/dist/weave/bridge.js +0 -51
  196. package/dist/weave/environment/detector.d.ts +0 -6
  197. package/dist/weave/environment/detector.js +4 -45
  198. package/dist/weave/environment/index.d.ts +0 -19
  199. package/dist/weave/environment/index.js +1 -39
  200. package/dist/weave/environment/issues.d.ts +0 -35
  201. package/dist/weave/environment/issues.js +0 -59
  202. package/dist/weave/git.d.ts +0 -8
  203. package/dist/weave/git.js +0 -8
  204. package/dist/weave/index.d.ts +0 -13
  205. package/dist/weave/index.js +2 -28
  206. package/dist/weave/knowledge/global.d.ts +0 -39
  207. package/dist/weave/knowledge/global.js +2 -78
  208. package/dist/weave/loop.js +0 -3
  209. package/dist/weave/orchestrator.d.ts +0 -69
  210. package/dist/weave/orchestrator.js +1 -101
  211. package/dist/weave/phase-manager.d.ts +0 -64
  212. package/dist/weave/phase-manager.js +0 -89
  213. package/dist/weave/security/secret-scan.d.ts +0 -14
  214. package/dist/weave/security/secret-scan.js +0 -19
  215. package/dist/weave/stages/build.js +0 -15
  216. package/dist/weave/stages/execute.d.ts +0 -42
  217. package/dist/weave/stages/execute.js +4 -86
  218. package/dist/weave/stages/handoff.d.ts +0 -7
  219. package/dist/weave/stages/handoff.js +0 -43
  220. package/dist/weave/stages/index.d.ts +0 -3
  221. package/dist/weave/stages/index.js +0 -3
  222. package/dist/weave/stages/intake.d.ts +0 -8
  223. package/dist/weave/stages/intake.js +5 -65
  224. package/dist/weave/stages/map.d.ts +0 -1
  225. package/dist/weave/stages/openspec.d.ts +0 -1
  226. package/dist/weave/stages/plan.d.ts +0 -11
  227. package/dist/weave/stages/plan.js +1 -53
  228. package/dist/weave/stages/refine.d.ts +0 -7
  229. package/dist/weave/stages/refine.js +0 -7
  230. package/dist/weave/stages/research.d.ts +0 -6
  231. package/dist/weave/stages/research.js +0 -6
  232. package/dist/weave/stages/spec.d.ts +0 -12
  233. package/dist/weave/stages/spec.js +0 -17
  234. package/dist/weave/types.d.ts +0 -20
  235. package/dist/weave/types.js +0 -5
  236. package/dist/weave/verification/commands.d.ts +0 -12
  237. package/dist/weave/verification/commands.js +0 -19
  238. package/dist/weave/verification/index.d.ts +0 -6
  239. package/dist/weave/verification/index.js +1 -19
  240. package/dist/weave/verification/playwright.d.ts +0 -47
  241. package/dist/weave/verification/playwright.js +1 -90
  242. package/dist/weave/worktree.d.ts +0 -16
  243. package/dist/weave/worktree.js +0 -23
  244. package/dist/weave/yaml-repair.d.ts +0 -39
  245. package/dist/weave/yaml-repair.js +13 -116
  246. package/package.json +1 -1
@@ -1,16 +1,7 @@
1
- /**
2
- * Weave Intake Stage
3
- *
4
- * Document analysis and question generation.
5
- * Uses Maskweaver memory for semantic search of past similar projects.
6
- */
7
1
  import * as fs from 'node:fs';
8
2
  import * as path from 'node:path';
9
3
  import { analyzeEnvironment } from '../environment/index.js';
10
4
  import { readMapResult } from './map.js';
11
- // ============================================================================
12
- // Document Discovery
13
- // ============================================================================
14
5
  const DOC_EXTENSIONS = ['.md', '.txt', '.yaml', '.yml', '.json'];
15
6
  const INDEX_FILES = ['index.md', 'README.md', 'readme.md'];
16
7
  function discoverDocuments(basePath) {
@@ -19,7 +10,6 @@ function discoverDocuments(basePath) {
19
10
  if (!fs.existsSync(dir))
20
11
  return;
21
12
  const entries = fs.readdirSync(dir, { withFileTypes: true });
22
- // Prioritize index files
23
13
  for (const indexFile of INDEX_FILES) {
24
14
  const indexPath = path.join(dir, indexFile);
25
15
  if (fs.existsSync(indexPath)) {
@@ -42,19 +32,13 @@ function discoverDocuments(basePath) {
42
32
  walk(basePath);
43
33
  return docs;
44
34
  }
45
- // ============================================================================
46
- // Document Analysis
47
- // ============================================================================
48
35
  function analyzeDocument(filePath) {
49
36
  const content = fs.readFileSync(filePath, 'utf-8');
50
37
  const fileName = path.basename(filePath);
51
- // Extract title (first H1 or filename)
52
38
  const titleMatch = content.match(/^#\s+(.+)$/m);
53
39
  const title = titleMatch ? titleMatch[1] : fileName.replace(/\.[^.]+$/, '');
54
- // Extract sections (H2 headers)
55
40
  const sectionMatches = content.match(/^##\s+(.+)$/gm) || [];
56
41
  const sections = sectionMatches.map(s => s.replace(/^##\s+/, ''));
57
- // Extract key points (bullet points under important headers)
58
42
  const keyPoints = [];
59
43
  const bulletMatches = content.match(/^[-*]\s+(.+)$/gm) || [];
60
44
  for (const bullet of bulletMatches.slice(0, 10)) {
@@ -67,9 +51,6 @@ function analyzeDocument(filePath) {
67
51
  keyPoints,
68
52
  };
69
53
  }
70
- // ============================================================================
71
- // Feature Extraction
72
- // ============================================================================
73
54
  const FEATURE_PATTERNS = [
74
55
  /(?:기능|feature|functionality)[::]\s*(.+)/gi,
75
56
  /(?:할 수 있다|can|should|must)\s+(.+)/gi,
@@ -78,13 +59,11 @@ const FEATURE_PATTERNS = [
78
59
  function extractFeatures(documents) {
79
60
  const features = new Set();
80
61
  for (const doc of documents) {
81
- // From key points
82
62
  for (const point of doc.keyPoints) {
83
63
  if (point.length > 10 && point.length < 100) {
84
64
  features.add(point);
85
65
  }
86
66
  }
87
- // From sections
88
67
  for (const section of doc.sections) {
89
68
  if (section.length > 5 && section.length < 50) {
90
69
  features.add(section);
@@ -93,9 +72,6 @@ function extractFeatures(documents) {
93
72
  }
94
73
  return Array.from(features).slice(0, 20);
95
74
  }
96
- // ============================================================================
97
- // Technical Requirements Detection
98
- // ============================================================================
99
75
  const TECH_PATTERNS = {
100
76
  frontend: [
101
77
  /react/i, /vue/i, /angular/i, /svelte/i, /next\.?js/i,
@@ -129,13 +105,9 @@ function detectTechnicalRequirements(documents) {
129
105
  }
130
106
  return result;
131
107
  }
132
- // ============================================================================
133
- // Question Generation
134
- // ============================================================================
135
108
  function generateQuestions(features, techReqs) {
136
109
  const questions = [];
137
110
  let qId = 1;
138
- // If no frontend detected, ask
139
111
  if (!techReqs.frontend || techReqs.frontend.length === 0) {
140
112
  questions.push({
141
113
  id: `Q${qId++}`,
@@ -145,7 +117,6 @@ function generateQuestions(features, techReqs) {
145
117
  required: true,
146
118
  });
147
119
  }
148
- // If no database detected, ask
149
120
  if (!techReqs.database || techReqs.database.length === 0) {
150
121
  questions.push({
151
122
  id: `Q${qId++}`,
@@ -155,7 +126,6 @@ function generateQuestions(features, techReqs) {
155
126
  required: true,
156
127
  });
157
128
  }
158
- // Priority question
159
129
  if (features.length > 3) {
160
130
  questions.push({
161
131
  id: `Q${qId++}`,
@@ -167,36 +137,23 @@ function generateQuestions(features, techReqs) {
167
137
  }
168
138
  return questions;
169
139
  }
170
- /**
171
- * Search memory for similar past projects based on features.
172
- * Uses hybrid search (vector + text) from memory module.
173
- */
174
140
  async function searchSimilarProjects(features, techStack) {
175
141
  const results = [];
176
142
  try {
177
- // Dynamic import to avoid circular dependencies
178
143
  const memoryModule = await import('../../memory/index.js');
179
- // Build query from features and tech stack
180
144
  const query = [...features.slice(0, 5), ...techStack].join(' ');
181
- // Get database instance (returns null if not initialized)
182
145
  const db = memoryModule.tryGetDatabase();
183
146
  if (!db) {
184
147
  console.log('[Intake] Memory database not initialized, skipping similar project search');
185
148
  return results;
186
149
  }
187
- // Create a text-only provider for simple search
188
- // ProviderConfig uses 'type' not 'provider'
189
150
  const provider = memoryModule.createProvider({
190
151
  type: 'text-only',
191
152
  });
192
- // Use hybridSearch or fall back to text search
193
153
  let searchResults = [];
194
154
  if (provider) {
195
- // Try semantic search if provider available
196
- // embed() takes string[] and returns Embedding[] (number[][])
197
155
  const embeddingResult = await provider.embed([query]);
198
- const embedding = embeddingResult[0]; // Get first (only) embedding
199
- // hybridSearch takes (query, queryEmbedding, options)
156
+ const embedding = embeddingResult[0];
200
157
  searchResults = memoryModule.hybridSearch(query, embedding, {
201
158
  limit: 5,
202
159
  minScore: 0.3,
@@ -204,23 +161,19 @@ async function searchSimilarProjects(features, techStack) {
204
161
  }
205
162
  else {
206
163
  console.log('[Intake] Provider not available, using text search only');
207
- // Fall back to text-only search
208
164
  const textResults = db.searchByText(query, 5);
209
165
  searchResults = textResults.map((r) => ({
210
166
  chunk: r.chunk,
211
- score: r.score || 0.5, // Default score for text matches
167
+ score: r.score || 0.5,
212
168
  }));
213
169
  }
214
- // Process results to extract project insights
215
170
  for (const result of searchResults) {
216
171
  const { chunk, score } = result;
217
- // Try to extract project name from path
218
172
  const pathParts = chunk.path.split(/[/\\]/);
219
173
  const projectName = pathParts.find((p) => !p.startsWith('.') &&
220
174
  p !== 'memory' &&
221
175
  p !== 'daily' &&
222
176
  !p.endsWith('.md')) || 'Previous Project';
223
- // Extract relevant features mentioned
224
177
  const relevantFeatures = features.filter(f => chunk.text.toLowerCase().includes(f.toLowerCase().slice(0, 10)));
225
178
  if (relevantFeatures.length > 0 || score > 0.5) {
226
179
  results.push({
@@ -233,14 +186,10 @@ async function searchSimilarProjects(features, techStack) {
233
186
  }
234
187
  }
235
188
  catch (e) {
236
- // Memory search is optional, don't fail intake
237
189
  console.log('[Intake] Similar project search failed:', e);
238
190
  }
239
191
  return results;
240
192
  }
241
- // ============================================================================
242
- // Map Integration — Structural Change Detection & Consent
243
- // ============================================================================
244
193
  export async function injectMapContext(map, features) {
245
194
  const structuralChanges = [];
246
195
  const consentPrompts = [];
@@ -347,49 +296,40 @@ export async function intake(options) {
347
296
  const extendedOptions = options;
348
297
  const skipEnvironmentAnalysis = extendedOptions.skipEnvironmentAnalysis ?? false;
349
298
  const warningsOnly = extendedOptions.warningsOnly ?? false;
350
- // Resolve path
351
299
  const absolutePath = path.isAbsolute(docsPath)
352
300
  ? docsPath
353
301
  : path.join(process.cwd(), docsPath);
354
302
  if (!fs.existsSync(absolutePath)) {
355
303
  throw new Error(`Documents path not found: ${absolutePath}`);
356
304
  }
357
- // Discover documents
358
305
  const docPaths = fs.statSync(absolutePath).isDirectory()
359
306
  ? discoverDocuments(absolutePath)
360
307
  : [absolutePath];
361
308
  if (docPaths.length === 0) {
362
309
  throw new Error(`No documents found in: ${absolutePath}`);
363
310
  }
364
- // Analyze each document
365
311
  const documents = docPaths.map(analyzeDocument);
366
- // Extract information
367
312
  const features = extractFeatures(documents);
368
313
  const technicalRequirements = detectTechnicalRequirements(documents);
369
314
  const questions = generateQuestions(features, technicalRequirements);
370
- // Build tech stack array for memory search
371
315
  const techStack = [
372
316
  ...(technicalRequirements.frontend || []),
373
317
  ...(technicalRequirements.backend || []),
374
318
  ...(technicalRequirements.database || []),
375
319
  ];
376
- // Search memory for similar past projects
377
320
  const similarProjectResults = await searchSimilarProjects(features, techStack);
378
321
  const similarProjects = similarProjectResults.map(r => `${r.projectName} (${(r.similarity * 100).toFixed(0)}% 유사): ${r.relevantFeatures.join(', ')}`);
379
- // Proactive environment analysis
380
322
  let environment;
381
323
  if (!skipEnvironmentAnalysis) {
382
324
  try {
383
- // Get the project directory (parent of docs path or current working directory)
384
325
  const projectPath = fs.statSync(absolutePath).isDirectory()
385
- ? path.dirname(absolutePath) // Parent of docs folder
386
- : path.dirname(absolutePath); // Same for single file
326
+ ? path.dirname(absolutePath)
327
+ : path.dirname(absolutePath);
387
328
  environment = await analyzeEnvironment({
388
329
  projectPath: projectPath !== '.' ? projectPath : process.cwd(),
389
330
  warningsOnly,
390
331
  includeProjectHistory: true,
391
332
  });
392
- // Log critical issues
393
333
  const criticalIssues = environment.issues.filter(i => i.severity === 'critical');
394
334
  if (criticalIssues.length > 0) {
395
335
  console.log(`\n⚠️ [Intake] ${criticalIssues.length}개의 Critical 이슈가 감지되었습니다!`);
@@ -410,7 +350,7 @@ export async function intake(options) {
410
350
  return {
411
351
  documents,
412
352
  features,
413
- domainTerms: [], // TODO: Extract domain-specific terminology
353
+ domainTerms: [],
414
354
  technicalRequirements,
415
355
  questions,
416
356
  similarProjects: similarProjects.length > 0 ? similarProjects : undefined,
@@ -3,7 +3,6 @@ export interface MapOptions {
3
3
  basePath?: string;
4
4
  onMessage?: (msg: string) => void;
5
5
  useGraphify?: boolean;
6
- /** If true, runs graphify-windows skill for deep knowledge graph analysis */
7
6
  deep?: boolean;
8
7
  }
9
8
  export declare function analyzeCodebase(options: MapOptions): Promise<MapResult>;
@@ -3,7 +3,6 @@ export interface OpenSpecOutputOptions {
3
3
  basePath: string;
4
4
  changeId: string;
5
5
  plan: WeavePlan;
6
- /** Overwrite existing files (default: false). */
7
6
  overwrite?: boolean;
8
7
  }
9
8
  export interface OpenSpecOutputResult {
@@ -1,24 +1,13 @@
1
- /**
2
- * Weave Plan Stage
3
- *
4
- * Create phase-based execution plan from analyzed requirements.
5
- * Generates testable MVPs per phase with clear completion criteria.
6
- */
7
1
  import type { WeavePhase, WeavePlan } from '../types.js';
8
2
  import type { IntakeResult } from './intake.js';
9
3
  export interface PlanOptions {
10
4
  intake: IntakeResult;
11
5
  projectName: string;
12
- /** Optional stable identifier used for plan filename/state.yaml */
13
6
  planName?: string;
14
- /** Base path for .opencode/weave (defaults to process.cwd()) */
15
7
  basePath?: string;
16
8
  userAnswers?: Record<string, string>;
17
- /** Auto-split oversized plans into multiple shard plan files (default: true). */
18
9
  splitPlans?: boolean;
19
- /** Max phases per shard plan when splitting (default: 3). */
20
10
  splitMaxPhases?: number;
21
- /** Max estimated hours per shard plan when splitting (default: 10). */
22
11
  splitMaxHours?: number;
23
12
  }
24
13
  export interface PlanResult {
@@ -1,15 +1,6 @@
1
- /**
2
- * Weave Plan Stage
3
- *
4
- * Create phase-based execution plan from analyzed requirements.
5
- * Generates testable MVPs per phase with clear completion criteria.
6
- */
7
1
  import { getPhaseManager } from '../phase-manager.js';
8
2
  import { getEffectiveGdcConfig, runGdcMachineCommand, getGraphNodeIds, getGraphEdges, countGdcCheckIssues, } from '../gdc.js';
9
3
  import { generateOpenSpecArtifacts, ensureOpenSpecWorkspace } from './openspec.js';
10
- // ============================================================================
11
- // Phase Size Estimation
12
- // ============================================================================
13
4
  const PHASE_SIZE_GUIDE = {
14
5
  tooSmall: ['변수명 변경', '오타 수정'],
15
6
  justRight: ['UI 컴포넌트 하나', '저장 기능', 'API 엔드포인트 하나'],
@@ -126,14 +117,10 @@ function buildSplitSummary(rootPlanName, shards, totalHours) {
126
117
  lines.push('Next: approve current shard, then run craft. Next shard is auto-activated when current shard is completed.');
127
118
  return lines.join('\n');
128
119
  }
129
- // ============================================================================
130
- // Architecture Inference
131
- // ============================================================================
132
120
  function inferArchitecture(intake, userAnswers) {
133
121
  const arch = {
134
122
  notes: '아키텍처는 진행하면서 조정될 수 있습니다',
135
123
  };
136
- // From detected requirements
137
124
  if (intake.technicalRequirements.frontend?.length) {
138
125
  arch.frontend = intake.technicalRequirements.frontend.join(' + ');
139
126
  }
@@ -143,7 +130,6 @@ function inferArchitecture(intake, userAnswers) {
143
130
  if (intake.technicalRequirements.database?.length) {
144
131
  arch.database = intake.technicalRequirements.database.join(' + ');
145
132
  }
146
- // From user answers
147
133
  if (userAnswers) {
148
134
  for (const [key, value] of Object.entries(userAnswers)) {
149
135
  if (key.includes('프론트엔드') || key.includes('frontend')) {
@@ -154,39 +140,30 @@ function inferArchitecture(intake, userAnswers) {
154
140
  }
155
141
  }
156
142
  }
157
- // Defaults
158
143
  if (!arch.frontend)
159
144
  arch.frontend = 'React + Vite';
160
145
  if (!arch.database)
161
146
  arch.database = 'LocalStorage (Phase 1-3)';
162
147
  return arch;
163
148
  }
164
- // ============================================================================
165
- // Phase Generation
166
- // ============================================================================
167
149
  function generatePhases(intake, userAnswers) {
168
150
  const phases = [];
169
151
  const features = intake.features;
170
- // Determine priority order
171
152
  let prioritizedFeatures = [...features];
172
153
  if (userAnswers) {
173
154
  const priorityAnswer = Object.entries(userAnswers).find(([k]) => k.includes('우선순위') || k.includes('priority'));
174
155
  if (priorityAnswer) {
175
156
  const priority = priorityAnswer[1];
176
- // Move priority feature to front
177
157
  prioritizedFeatures = [
178
158
  priority,
179
159
  ...features.filter(f => f !== priority)
180
160
  ];
181
161
  }
182
162
  }
183
- // Generate phases from features
184
163
  let phaseNum = 1;
185
164
  for (const feature of prioritizedFeatures.slice(0, 8)) {
186
165
  const phaseId = `P${phaseNum}`;
187
- // Create completion criteria
188
166
  const doneWhen = `유저가 ${feature.toLowerCase().replace(/[을를이가은는]/g, '')}할 수 있다`;
189
- // Create checklist items
190
167
  const checklist = [
191
168
  `${feature} 관련 UI가 표시되는가?`,
192
169
  `기능이 정상 동작하는가?`,
@@ -198,7 +175,7 @@ function generatePhases(intake, userAnswers) {
198
175
  status: 'pending',
199
176
  doneWhen,
200
177
  checklist,
201
- estimatedHours: 3, // Default estimate
178
+ estimatedHours: 3,
202
179
  dependsOn: phaseNum > 1 ? [`P${phaseNum - 1}`] : undefined,
203
180
  });
204
181
  phaseNum++;
@@ -388,14 +365,9 @@ function inferPhaseDependenciesFromGraph(phases, phaseNodeMap, edges) {
388
365
  };
389
366
  });
390
367
  }
391
- // ============================================================================
392
- // Main Plan Function
393
- // ============================================================================
394
368
  export async function plan(options) {
395
369
  const { intake, projectName, userAnswers, planName, basePath } = options;
396
- // Infer architecture
397
370
  const architecture = inferArchitecture(intake, userAnswers);
398
- // Generate phases
399
371
  let phases = generatePhases(intake, userAnswers);
400
372
  const gdcSignals = await collectGdcPlanningSignals(basePath, intake);
401
373
  const intakeNeedles = buildNeedlesFromIntake(intake);
@@ -412,20 +384,16 @@ export async function plan(options) {
412
384
  : gdcNote;
413
385
  }
414
386
  }
415
- // Create vision summary
416
387
  const vision = intake.features.length > 0
417
388
  ? `${projectName}: ${intake.features.slice(0, 3).join(', ')} 등의 기능을 제공하는 애플리케이션`
418
389
  : `${projectName} 애플리케이션`;
419
- // Attach structural changes from intake
420
390
  const structuralChanges = intake.structuralChanges?.filter(sc => sc.agreed) || [];
421
- // Calculate total estimated hours
422
391
  const estimatedTotalHours = phases.reduce((sum, p) => sum + (p.estimatedHours || 3), 0);
423
392
  const normalizedPlanName = normalizePlanName(planName || toKebabCase(projectName) || 'weave-plan');
424
393
  const splitConfig = resolveSplitConfig(options);
425
394
  const manager = getPhaseManager(basePath);
426
395
  if (shouldSplitPlan(phases, estimatedTotalHours, splitConfig)) {
427
396
  const groups = partitionPhases(phases, splitConfig);
428
- // If partitioning still yields one group, keep the standard single-plan flow.
429
397
  if (groups.length > 1) {
430
398
  const createdShards = [];
431
399
  for (let i = 0; i < groups.length; i += 1) {
@@ -473,7 +441,6 @@ export async function plan(options) {
473
441
  if (!firstShard) {
474
442
  throw new Error('Failed to create shard plans from oversized plan');
475
443
  }
476
- // Set active shard to the first one for immediate execution.
477
444
  await manager.savePlan(firstShard.plan);
478
445
  return {
479
446
  plan: firstShard.plan,
@@ -484,7 +451,6 @@ export async function plan(options) {
484
451
  };
485
452
  }
486
453
  }
487
- // Standard single-plan flow
488
454
  const weavePlan = await manager.createPlan({
489
455
  planName: normalizedPlanName,
490
456
  projectName,
@@ -493,17 +459,14 @@ export async function plan(options) {
493
459
  phases,
494
460
  planRole: 'standalone',
495
461
  });
496
- // Attach structural changes to plan
497
462
  if (structuralChanges.length > 0) {
498
463
  weavePlan.structuralChanges = structuralChanges;
499
464
  await manager.savePlan(weavePlan);
500
465
  }
501
- // Attach map info if available
502
466
  if (intake.codebaseMapPath) {
503
467
  weavePlan.mapReportPath = intake.codebaseMapPath;
504
468
  weavePlan.mapGeneratedAt = new Date().toISOString();
505
469
  }
506
- // vNext: Generate a baseline executable task list per phase
507
470
  for (const phase of weavePlan.phases) {
508
471
  const tasks = generateDefaultPhaseTasks(phase, {
509
472
  changeId: weavePlan.planName || normalizedPlanName,
@@ -514,7 +477,6 @@ export async function plan(options) {
514
477
  await manager.addTasks(phase.id, tasks);
515
478
  }
516
479
  }
517
- // Generate OpenSpec artifacts
518
480
  try {
519
481
  const changeId = weavePlan.planName || normalizedPlanName;
520
482
  await ensureOpenSpecWorkspace(basePath || process.cwd());
@@ -527,9 +489,7 @@ export async function plan(options) {
527
489
  weavePlan.openspecDir = openspecResult.changeDir;
528
490
  }
529
491
  catch {
530
- // OpenSpec generation is best-effort
531
492
  }
532
- // Generate summary
533
493
  const summary = generatePlanSummary(weavePlan, estimatedTotalHours);
534
494
  return {
535
495
  plan: weavePlan,
@@ -540,7 +500,6 @@ export async function plan(options) {
540
500
  };
541
501
  }
542
502
  function generateDefaultPhaseTasks(phase, gdc) {
543
- // Keep tasks small, specific, and runnable. Downstream craft can refine.
544
503
  const baseId = phase.id;
545
504
  const title = phase.name;
546
505
  const nodeIds = (gdc?.nodeIds || []).slice(0, 4);
@@ -602,9 +561,6 @@ function toKebabCase(input) {
602
561
  .replace(/[^a-z0-9]+/g, '-')
603
562
  .replace(/^-+|-+$/g, '');
604
563
  }
605
- // ============================================================================
606
- // Summary Generation
607
- // ============================================================================
608
564
  function generatePlanSummary(plan, totalHours) {
609
565
  const lines = [];
610
566
  lines.push(`## 📋 실행 계획서`);
@@ -661,24 +617,18 @@ function generatePlanSummary(plan, totalHours) {
661
617
  lines.push(`승인 후 \`/weave build\`로 자율 실행을 시작합니다.`);
662
618
  return lines.join('\n');
663
619
  }
664
- // ============================================================================
665
- // Plan Modification
666
- // ============================================================================
667
620
  export async function modifyPlan(modifications) {
668
621
  const manager = getPhaseManager();
669
622
  const plan = await manager.loadPlan();
670
623
  if (!plan) {
671
624
  throw new Error('No plan exists to modify');
672
625
  }
673
- // Remove phases
674
626
  if (modifications.removePhases) {
675
627
  plan.phases = plan.phases.filter(p => !modifications.removePhases.includes(p.id));
676
628
  }
677
- // Add phases
678
629
  if (modifications.addPhases) {
679
630
  plan.phases.push(...modifications.addPhases.map(p => ({ ...p, tasks: [] })));
680
631
  }
681
- // Update phases
682
632
  if (modifications.updatePhases) {
683
633
  for (const { id, updates } of modifications.updatePhases) {
684
634
  const phase = plan.phases.find(p => p.id === id);
@@ -687,11 +637,9 @@ export async function modifyPlan(modifications) {
687
637
  }
688
638
  }
689
639
  }
690
- // Update architecture
691
640
  if (modifications.updateArchitecture) {
692
641
  plan.architecture = { ...plan.architecture, ...modifications.updateArchitecture };
693
642
  }
694
- // Save
695
643
  await manager.savePlan(plan);
696
644
  return plan;
697
645
  }
@@ -1,10 +1,3 @@
1
- /**
2
- * Weave Refine Stage
3
- *
4
- * Applies structured plan-note directives to an existing plan.
5
- * This enables an annotation cycle where humans edit notes and
6
- * the plan is updated mechanically before implementation.
7
- */
8
1
  import type { WeavePlan } from '../types.js';
9
2
  export interface RefinePlanResult {
10
3
  updatedPlan: WeavePlan;
@@ -1,10 +1,3 @@
1
- /**
2
- * Weave Refine Stage
3
- *
4
- * Applies structured plan-note directives to an existing plan.
5
- * This enables an annotation cycle where humans edit notes and
6
- * the plan is updated mechanically before implementation.
7
- */
8
1
  const STATUS_VALUES = new Set([
9
2
  'pending',
10
3
  'in_progress',
@@ -1,9 +1,3 @@
1
- /**
2
- * Weave Research Stage
3
- *
4
- * Produces a persistent research artifact before planning/implementation.
5
- * The report is intentionally markdown-first so humans can annotate and review.
6
- */
7
1
  import type { IntakeResult } from './intake.js';
8
2
  export interface ResearchOptions {
9
3
  docsPath: string;
@@ -1,9 +1,3 @@
1
- /**
2
- * Weave Research Stage
3
- *
4
- * Produces a persistent research artifact before planning/implementation.
5
- * The report is intentionally markdown-first so humans can annotate and review.
6
- */
7
1
  import * as fs from 'node:fs';
8
2
  import * as path from 'node:path';
9
3
  import { getEffectiveGdcConfig, runGdcMachineCommand, countGdcCheckIssues, getGraphNodeIds, getGraphEdges, getStatsNodeSummary, } from '../gdc.js';
@@ -1,13 +1,3 @@
1
- /**
2
- * Weave Spec Stage
3
- *
4
- * Converts intake analysis into a structured spec file.
5
- *
6
- * NOTE:
7
- * - This is intentionally conservative and heuristic-based.
8
- * - The goal is to produce a usable baseline spec (requirements + ACs)
9
- * that can be refined later.
10
- */
11
1
  import type { IntakeResult } from './intake.js';
12
2
  export type RequirementCategory = 'functional' | 'constraint' | 'performance' | 'ux';
13
3
  export type RequirementPriority = 'must' | 'should' | 'could' | 'wont';
@@ -32,9 +22,7 @@ export interface WeaveSpec {
32
22
  export interface SpecOptions {
33
23
  intake: IntakeResult;
34
24
  projectName: string;
35
- /** Spec name (kebab-case). Defaults to "weave-spec". */
36
25
  specName?: string;
37
- /** Base path for .opencode/weave (defaults to process.cwd()). */
38
26
  basePath?: string;
39
27
  }
40
28
  export interface SpecResult {
@@ -1,20 +1,7 @@
1
- /**
2
- * Weave Spec Stage
3
- *
4
- * Converts intake analysis into a structured spec file.
5
- *
6
- * NOTE:
7
- * - This is intentionally conservative and heuristic-based.
8
- * - The goal is to produce a usable baseline spec (requirements + ACs)
9
- * that can be refined later.
10
- */
11
1
  import * as fs from 'node:fs';
12
2
  import * as path from 'node:path';
13
3
  import { stringify } from 'yaml';
14
4
  import { safeWriteFile } from '../yaml-repair.js';
15
- // ============================================================================
16
- // Helpers
17
- // ============================================================================
18
5
  const WEAVE_DIR = path.join('.opencode', 'weave');
19
6
  function toKebabCase(input) {
20
7
  return input
@@ -55,7 +42,6 @@ function defaultAcceptanceType(category) {
55
42
  }
56
43
  }
57
44
  function defaultScenario(desc, category) {
58
- // Keep the scenario concise; downstream plan/craft can refine.
59
45
  switch (category) {
60
46
  case 'performance':
61
47
  return `${desc} (성능 기준을 만족한다)`;
@@ -95,9 +81,6 @@ function formatSpecSummary(spec, specPath) {
95
81
  `- 검증 기준: ${totalAC}개${typeLine ? ` (${typeLine})` : ''}`,
96
82
  ].join('\n');
97
83
  }
98
- // ============================================================================
99
- // Main
100
- // ============================================================================
101
84
  export async function spec(options) {
102
85
  const basePath = options.basePath || process.cwd();
103
86
  const specsDir = path.join(basePath, WEAVE_DIR, 'specs');