maskweaver 0.9.4 → 0.9.6
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.
- package/README.ko.md +638 -592
- package/README.md +671 -667
- package/dist/cli/doctor.js +5 -21
- package/dist/cli/install.d.ts +0 -8
- package/dist/cli/install.js +0 -39
- package/dist/context/config.d.ts +0 -22
- package/dist/context/config.js +0 -28
- package/dist/context/feature.d.ts +0 -39
- package/dist/context/feature.js +0 -77
- package/dist/context/files.d.ts +0 -13
- package/dist/context/files.js +1 -24
- package/dist/context/index.d.ts +0 -7
- package/dist/context/index.js +0 -12
- package/dist/context/project.d.ts +0 -21
- package/dist/context/project.js +0 -30
- package/dist/context/types.d.ts +0 -48
- package/dist/context/types.js +0 -12
- package/dist/context/utils.d.ts +0 -18
- package/dist/context/utils.js +0 -27
- package/dist/core/engine/promptBuilder.d.ts +0 -17
- package/dist/core/engine/promptBuilder.js +0 -28
- package/dist/core/index.d.ts +0 -6
- package/dist/core/index.js +0 -9
- package/dist/core/loader/MaskLoader.d.ts +0 -23
- package/dist/core/loader/MaskLoader.js +0 -29
- package/dist/core/schema/types.d.ts +0 -47
- package/dist/core/schema/types.js +0 -6
- package/dist/core/schema/validator.d.ts +0 -14
- package/dist/core/schema/validator.js +0 -18
- package/dist/i18n/index.d.ts +0 -18
- package/dist/i18n/index.js +4 -23
- package/dist/index.d.ts +0 -8
- package/dist/index.js +0 -8
- package/dist/lib.d.ts +0 -5
- package/dist/lib.js +0 -12
- package/dist/memory/chunking.d.ts +0 -22
- package/dist/memory/chunking.js +2 -37
- package/dist/memory/core.d.ts +0 -29
- package/dist/memory/core.js +1 -52
- package/dist/memory/index.d.ts +0 -5
- package/dist/memory/index.js +0 -10
- package/dist/memory/indexer.d.ts +0 -21
- package/dist/memory/indexer.js +0 -44
- package/dist/memory/providers/examples.d.ts +0 -5
- package/dist/memory/providers/examples.js +4 -64
- package/dist/memory/providers/factory.d.ts +0 -44
- package/dist/memory/providers/factory.js +0 -46
- package/dist/memory/providers/index.d.ts +0 -26
- package/dist/memory/providers/index.js +0 -28
- package/dist/memory/providers/ollama.d.ts +0 -6
- package/dist/memory/providers/ollama.js +1 -8
- package/dist/memory/providers/openai.d.ts +0 -6
- package/dist/memory/providers/openai.js +1 -8
- package/dist/memory/providers/openrouter.d.ts +0 -6
- package/dist/memory/providers/openrouter.js +0 -8
- package/dist/memory/providers/text-only.d.ts +0 -13
- package/dist/memory/providers/text-only.js +0 -17
- package/dist/memory/providers/types.d.ts +0 -39
- package/dist/memory/providers/types.js +0 -7
- package/dist/memory/providers/voyage.d.ts +0 -22
- package/dist/memory/providers/voyage.js +1 -24
- package/dist/memory/search/hybrid.d.ts +0 -12
- package/dist/memory/search/hybrid.js +1 -22
- package/dist/memory/store/sqlite.d.ts +0 -72
- package/dist/memory/store/sqlite.js +4 -127
- package/dist/plugin/config/index.d.ts +0 -112
- package/dist/plugin/config/index.js +0 -115
- package/dist/plugin/index.d.ts +0 -13
- package/dist/plugin/index.js +1 -123
- package/dist/plugin/tools/command-registry.d.ts +0 -6
- package/dist/plugin/tools/command-registry.js +0 -14
- package/dist/plugin/tools/context.d.ts +0 -12
- package/dist/plugin/tools/context.js +0 -58
- package/dist/plugin/tools/maskSave.d.ts +0 -3
- package/dist/plugin/tools/maskSave.js +0 -3
- package/dist/plugin/tools/memoryGet.d.ts +0 -3
- package/dist/plugin/tools/memoryGet.js +0 -3
- package/dist/plugin/tools/memoryIndexer.d.ts +0 -3
- package/dist/plugin/tools/memoryIndexer.js +0 -10
- package/dist/plugin/tools/memorySearch.d.ts +0 -31
- package/dist/plugin/tools/memorySearch.js +0 -79
- package/dist/plugin/tools/memoryWrite.d.ts +0 -8
- package/dist/plugin/tools/memoryWrite.js +0 -32
- package/dist/plugin/tools/retrospect.d.ts +0 -3
- package/dist/plugin/tools/retrospect.js +0 -3
- package/dist/plugin/tools/slashcommand.d.ts +0 -11
- package/dist/plugin/tools/slashcommand.js +0 -38
- package/dist/plugin/tools/squad.d.ts +0 -12
- package/dist/plugin/tools/squad.js +11 -83
- package/dist/plugin/tools/weave.d.ts +0 -6
- package/dist/plugin/tools/weave.js +0 -78
- package/dist/plugin/types.d.ts +0 -20
- package/dist/plugin/types.js +0 -7
- package/dist/retrospect/index.d.ts +0 -7
- package/dist/retrospect/index.js +0 -9
- package/dist/retrospect/mask-save.d.ts +0 -12
- package/dist/retrospect/mask-save.js +1 -80
- package/dist/retrospect/retrospect.d.ts +0 -18
- package/dist/retrospect/retrospect.js +0 -63
- package/dist/retrospect/strategies/base.d.ts +0 -15
- package/dist/retrospect/strategies/base.js +0 -7
- package/dist/retrospect/strategies/deep.d.ts +0 -12
- package/dist/retrospect/strategies/deep.js +0 -24
- package/dist/retrospect/strategies/index.d.ts +0 -12
- package/dist/retrospect/strategies/index.js +0 -12
- package/dist/retrospect/strategies/quick.d.ts +0 -12
- package/dist/retrospect/strategies/quick.js +0 -19
- package/dist/retrospect/strategies/standard.d.ts +0 -12
- package/dist/retrospect/strategies/standard.js +0 -15
- package/dist/retrospect/types.d.ts +0 -7
- package/dist/retrospect/types.js +0 -7
- package/dist/shared/config.d.ts +0 -105
- package/dist/shared/config.js +0 -33
- package/dist/shared/errors.d.ts +0 -18
- package/dist/shared/errors.js +0 -19
- package/dist/shared/generate-agents.d.ts +0 -69
- package/dist/shared/generate-agents.js +2 -86
- package/dist/shared/image.d.ts +0 -67
- package/dist/shared/image.js +6 -104
- package/dist/shared/index.d.ts +0 -5
- package/dist/shared/index.js +0 -7
- package/dist/shared/model-registry.d.ts +0 -72
- package/dist/shared/model-registry.js +5 -95
- package/dist/shared/types.d.ts +0 -15
- package/dist/shared/types.js +0 -3
- package/dist/shared-context/dag.d.ts +0 -105
- package/dist/shared-context/dag.js +3 -114
- package/dist/shared-context/index.d.ts +0 -5
- package/dist/shared-context/index.js +0 -15
- package/dist/shared-context/logger.d.ts +0 -37
- package/dist/shared-context/logger.js +0 -41
- package/dist/shared-context/parallel-executor.d.ts +0 -54
- package/dist/shared-context/parallel-executor.js +4 -56
- package/dist/shared-context/session.d.ts +0 -56
- package/dist/shared-context/session.js +0 -47
- package/dist/shared-context/squad.d.ts +0 -68
- package/dist/shared-context/squad.js +0 -63
- package/dist/shared-context/storage.d.ts +0 -132
- package/dist/shared-context/storage.js +0 -116
- package/dist/shared-context/task.d.ts +0 -120
- package/dist/shared-context/task.js +0 -152
- package/dist/shared-context/test/dag.test.js +9 -14
- package/dist/shared-context/test/logger.test.d.ts +0 -8
- package/dist/shared-context/test/logger.test.js +0 -52
- package/dist/shared-context/test/session.test.d.ts +0 -7
- package/dist/shared-context/test/session.test.js +0 -63
- package/dist/shared-context/test/squad.test.d.ts +0 -10
- package/dist/shared-context/test/squad.test.js +2 -68
- package/dist/shared-context/test/storage.test.d.ts +0 -8
- package/dist/shared-context/test/storage.test.js +0 -68
- package/dist/shared-context/test/task.test.d.ts +0 -7
- package/dist/shared-context/test/task.test.js +0 -54
- package/dist/shared-context/test/watchdog.test.d.ts +0 -7
- package/dist/shared-context/test/watchdog.test.js +3 -58
- package/dist/shared-context/types.d.ts +0 -215
- package/dist/shared-context/types.js +0 -125
- package/dist/shared-context/watchdog.d.ts +0 -127
- package/dist/shared-context/watchdog.js +0 -148
- package/dist/shared-context/worktree.d.ts +0 -68
- package/dist/shared-context/worktree.js +2 -34
- package/dist/verify/budget.d.ts +0 -29
- package/dist/verify/budget.js +0 -34
- package/dist/verify/critical-files.d.ts +0 -17
- package/dist/verify/critical-files.js +0 -37
- package/dist/verify/escalation.d.ts +0 -20
- package/dist/verify/escalation.js +0 -22
- package/dist/verify/index.d.ts +0 -5
- package/dist/verify/index.js +0 -11
- package/dist/verify/prompts.d.ts +0 -20
- package/dist/verify/prompts.js +0 -20
- package/dist/verify/types.d.ts +0 -26
- package/dist/verify/types.js +1 -12
- package/dist/verify/verifier.d.ts +0 -29
- package/dist/verify/verifier.js +0 -54
- package/dist/version.d.ts +1 -16
- package/dist/version.js +1 -16
- package/dist/weave/bridge.d.ts +0 -35
- package/dist/weave/bridge.js +0 -51
- package/dist/weave/environment/detector.d.ts +0 -6
- package/dist/weave/environment/detector.js +4 -45
- package/dist/weave/environment/index.d.ts +0 -19
- package/dist/weave/environment/index.js +1 -39
- package/dist/weave/environment/issues.d.ts +0 -35
- package/dist/weave/environment/issues.js +0 -59
- package/dist/weave/git.d.ts +0 -8
- package/dist/weave/git.js +0 -8
- package/dist/weave/index.d.ts +0 -13
- package/dist/weave/index.js +2 -28
- package/dist/weave/knowledge/global.d.ts +0 -39
- package/dist/weave/knowledge/global.js +2 -78
- package/dist/weave/loop.js +0 -3
- package/dist/weave/orchestrator.d.ts +0 -69
- package/dist/weave/orchestrator.js +1 -101
- package/dist/weave/phase-manager.d.ts +0 -64
- package/dist/weave/phase-manager.js +0 -89
- package/dist/weave/security/secret-scan.d.ts +0 -14
- package/dist/weave/security/secret-scan.js +0 -19
- package/dist/weave/stages/build.js +0 -15
- package/dist/weave/stages/execute.d.ts +0 -42
- package/dist/weave/stages/execute.js +4 -86
- package/dist/weave/stages/handoff.d.ts +0 -7
- package/dist/weave/stages/handoff.js +0 -43
- package/dist/weave/stages/index.d.ts +0 -3
- package/dist/weave/stages/index.js +0 -3
- package/dist/weave/stages/intake.d.ts +0 -8
- package/dist/weave/stages/intake.js +5 -65
- package/dist/weave/stages/map.d.ts +0 -1
- package/dist/weave/stages/openspec.d.ts +0 -1
- package/dist/weave/stages/plan.d.ts +0 -11
- package/dist/weave/stages/plan.js +1 -53
- package/dist/weave/stages/refine.d.ts +0 -7
- package/dist/weave/stages/refine.js +0 -7
- package/dist/weave/stages/research.d.ts +0 -6
- package/dist/weave/stages/research.js +0 -6
- package/dist/weave/stages/spec.d.ts +0 -12
- package/dist/weave/stages/spec.js +0 -17
- package/dist/weave/types.d.ts +0 -20
- package/dist/weave/types.js +0 -5
- package/dist/weave/verification/commands.d.ts +0 -12
- package/dist/weave/verification/commands.js +0 -19
- package/dist/weave/verification/index.d.ts +0 -6
- package/dist/weave/verification/index.js +1 -19
- package/dist/weave/verification/playwright.d.ts +0 -47
- package/dist/weave/verification/playwright.js +1 -90
- package/dist/weave/worktree.d.ts +0 -16
- package/dist/weave/worktree.js +0 -23
- package/dist/weave/yaml-repair.d.ts +0 -39
- package/dist/weave/yaml-repair.js +13 -116
- 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];
|
|
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,
|
|
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)
|
|
386
|
-
: path.dirname(absolutePath);
|
|
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: [],
|
|
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>;
|
|
@@ -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,
|
|
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');
|