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,15 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase Manager
|
|
3
|
-
*
|
|
4
|
-
* Manages phase lifecycle and persistence.
|
|
5
|
-
* Integrates with Maskweaver's context module for file tracking.
|
|
6
|
-
*/
|
|
7
1
|
import * as fs from 'node:fs';
|
|
8
2
|
import * as path from 'node:path';
|
|
9
3
|
import { yamlEscapeString, safeWriteFile, safeReadYaml, validatePlanStructure, repairAllPlans } from './yaml-repair.js';
|
|
10
|
-
// ============================================================================
|
|
11
|
-
// Configuration
|
|
12
|
-
// ============================================================================
|
|
13
4
|
const WEAVE_DIR = '.opencode/weave';
|
|
14
5
|
const PLAN_FILE = 'PLAN.yaml';
|
|
15
6
|
const STATE_FILE = 'state.yaml';
|
|
@@ -38,9 +29,6 @@ function ensurePlansDir(basePath = process.cwd()) {
|
|
|
38
29
|
fs.mkdirSync(dir, { recursive: true });
|
|
39
30
|
}
|
|
40
31
|
}
|
|
41
|
-
// ============================================================================
|
|
42
|
-
// YAML Serialization (Safe - with proper escaping)
|
|
43
|
-
// ============================================================================
|
|
44
32
|
function serializePlan(plan) {
|
|
45
33
|
const lines = [];
|
|
46
34
|
lines.push(`# Weave Plan - ${plan.projectName}`);
|
|
@@ -214,9 +202,6 @@ function serializePlan(plan) {
|
|
|
214
202
|
}
|
|
215
203
|
return lines.join('\n');
|
|
216
204
|
}
|
|
217
|
-
// ============================================================================
|
|
218
|
-
// Phase Manager Class
|
|
219
|
-
// ============================================================================
|
|
220
205
|
export class PhaseManager {
|
|
221
206
|
basePath;
|
|
222
207
|
plan = null;
|
|
@@ -224,21 +209,11 @@ export class PhaseManager {
|
|
|
224
209
|
constructor(basePath = process.cwd()) {
|
|
225
210
|
this.basePath = basePath;
|
|
226
211
|
}
|
|
227
|
-
/**
|
|
228
|
-
* Get recovery messages from last load operation.
|
|
229
|
-
* UI can display these to inform the user about auto-repairs.
|
|
230
|
-
*/
|
|
231
212
|
getRecoveryMessages() {
|
|
232
213
|
return this._recoveryMessages;
|
|
233
214
|
}
|
|
234
|
-
/**
|
|
235
|
-
* Load existing plan or return null.
|
|
236
|
-
* Supports multi-plan architecture (state.yaml → plans/) with legacy PLAN.yaml fallback.
|
|
237
|
-
* Auto-repairs corrupted YAML files when possible.
|
|
238
|
-
*/
|
|
239
215
|
async loadPlan() {
|
|
240
216
|
this._recoveryMessages = [];
|
|
241
|
-
// 1. Try new multi-plan architecture: state.yaml → plans/{active_plan}.yaml
|
|
242
217
|
const statePath = getStatePath(this.basePath);
|
|
243
218
|
if (fs.existsSync(statePath)) {
|
|
244
219
|
try {
|
|
@@ -271,7 +246,6 @@ export class PhaseManager {
|
|
|
271
246
|
console.error('[PhaseManager] Failed to load from state.yaml:', e);
|
|
272
247
|
}
|
|
273
248
|
}
|
|
274
|
-
// 2. Legacy fallback: PLAN.yaml
|
|
275
249
|
const planPath = getPlanPath(this.basePath);
|
|
276
250
|
if (!fs.existsSync(planPath)) {
|
|
277
251
|
return null;
|
|
@@ -291,32 +265,21 @@ export class PhaseManager {
|
|
|
291
265
|
}
|
|
292
266
|
return null;
|
|
293
267
|
}
|
|
294
|
-
/**
|
|
295
|
-
* Save plan to disk using safe file I/O (atomic writes with backup).
|
|
296
|
-
* If state.yaml exists (new mode): save to plans/{planName}.yaml and update state.yaml.
|
|
297
|
-
* Otherwise (legacy mode): save to PLAN.yaml.
|
|
298
|
-
*/
|
|
299
268
|
async savePlan(plan) {
|
|
300
269
|
ensureWeaveDir(this.basePath);
|
|
301
270
|
plan.updatedAt = new Date().toISOString();
|
|
302
271
|
const content = serializePlan(plan);
|
|
303
272
|
const statePath = getStatePath(this.basePath);
|
|
304
|
-
// vNext default: always use multi-plan mode. If state.yaml is missing,
|
|
305
|
-
// create it instead of falling back to legacy PLAN.yaml.
|
|
306
273
|
if (!fs.existsSync(statePath)) {
|
|
307
274
|
ensurePlansDir(this.basePath);
|
|
308
275
|
const { stringify } = await import('yaml');
|
|
309
276
|
safeWriteFile(statePath, stringify({ active_plan: null }));
|
|
310
277
|
}
|
|
311
|
-
// Multi-plan mode: save to plans/ directory
|
|
312
278
|
ensurePlansDir(this.basePath);
|
|
313
279
|
const planName = this.toPlanFileName(plan.planName || plan.projectName);
|
|
314
|
-
// Persist normalized planName back onto the plan for stability
|
|
315
280
|
plan.planName = planName;
|
|
316
281
|
const planFilePath = path.join(getPlansDir(this.basePath), `${planName}.yaml`);
|
|
317
282
|
safeWriteFile(planFilePath, content);
|
|
318
|
-
// Update state.yaml with active_plan while preserving additional keys.
|
|
319
|
-
// This avoids clobbering forward-compatible state fields.
|
|
320
283
|
const { stringify } = await import('yaml');
|
|
321
284
|
let stateData = {};
|
|
322
285
|
try {
|
|
@@ -326,22 +289,15 @@ export class PhaseManager {
|
|
|
326
289
|
}
|
|
327
290
|
}
|
|
328
291
|
catch {
|
|
329
|
-
// ignore state parse errors and overwrite with minimal state
|
|
330
292
|
}
|
|
331
293
|
stateData.active_plan = planName;
|
|
332
294
|
const stateContent = stringify(stateData);
|
|
333
295
|
safeWriteFile(statePath, stateContent);
|
|
334
296
|
this.plan = plan;
|
|
335
297
|
}
|
|
336
|
-
/**
|
|
337
|
-
* Repair all plan files. Returns repair report.
|
|
338
|
-
*/
|
|
339
298
|
async repairPlans() {
|
|
340
299
|
return repairAllPlans(this.basePath);
|
|
341
300
|
}
|
|
342
|
-
/**
|
|
343
|
-
* Create a new plan.
|
|
344
|
-
*/
|
|
345
301
|
async createPlan(input) {
|
|
346
302
|
const now = new Date().toISOString();
|
|
347
303
|
const plan = {
|
|
@@ -365,17 +321,11 @@ export class PhaseManager {
|
|
|
365
321
|
await this.savePlan(plan);
|
|
366
322
|
return plan;
|
|
367
323
|
}
|
|
368
|
-
/**
|
|
369
|
-
* Get a specific phase.
|
|
370
|
-
*/
|
|
371
324
|
getPhase(phaseId) {
|
|
372
325
|
if (!this.plan)
|
|
373
326
|
return null;
|
|
374
327
|
return this.plan.phases.find(p => p.id === phaseId) || null;
|
|
375
328
|
}
|
|
376
|
-
/**
|
|
377
|
-
* Update phase status.
|
|
378
|
-
*/
|
|
379
329
|
async updatePhaseStatus(phaseId, status, additionalData) {
|
|
380
330
|
if (!this.plan) {
|
|
381
331
|
await this.loadPlan();
|
|
@@ -391,7 +341,6 @@ export class PhaseManager {
|
|
|
391
341
|
}
|
|
392
342
|
if (status === 'completed' && !phase.completedAt) {
|
|
393
343
|
phase.completedAt = new Date().toISOString();
|
|
394
|
-
// Calculate actual hours if we have start time
|
|
395
344
|
if (phase.startedAt) {
|
|
396
345
|
const start = new Date(phase.startedAt).getTime();
|
|
397
346
|
const end = new Date(phase.completedAt).getTime();
|
|
@@ -405,9 +354,6 @@ export class PhaseManager {
|
|
|
405
354
|
await this.savePlan(this.plan);
|
|
406
355
|
return phase;
|
|
407
356
|
}
|
|
408
|
-
/**
|
|
409
|
-
* Add tasks to a phase.
|
|
410
|
-
*/
|
|
411
357
|
async addTasks(phaseId, tasks) {
|
|
412
358
|
if (!this.plan) {
|
|
413
359
|
await this.loadPlan();
|
|
@@ -425,9 +371,6 @@ export class PhaseManager {
|
|
|
425
371
|
})));
|
|
426
372
|
await this.savePlan(this.plan);
|
|
427
373
|
}
|
|
428
|
-
/**
|
|
429
|
-
* Update task status.
|
|
430
|
-
*/
|
|
431
374
|
async updateTaskStatus(phaseId, taskId, status, additionalData) {
|
|
432
375
|
if (!this.plan) {
|
|
433
376
|
await this.loadPlan();
|
|
@@ -447,16 +390,11 @@ export class PhaseManager {
|
|
|
447
390
|
if (additionalData) {
|
|
448
391
|
Object.assign(task, additionalData);
|
|
449
392
|
}
|
|
450
|
-
// Track masks used in phase
|
|
451
393
|
if (task.maskUsed && !phase.masksUsed?.includes(task.maskUsed)) {
|
|
452
394
|
phase.masksUsed = [...(phase.masksUsed || []), task.maskUsed];
|
|
453
395
|
}
|
|
454
396
|
await this.savePlan(this.plan);
|
|
455
397
|
}
|
|
456
|
-
/**
|
|
457
|
-
* Mark all tasks in a phase as passed.
|
|
458
|
-
* Useful when the phase is approved after full verification.
|
|
459
|
-
*/
|
|
460
398
|
async markAllTasksPassed(phaseId) {
|
|
461
399
|
if (!this.plan) {
|
|
462
400
|
await this.loadPlan();
|
|
@@ -473,15 +411,11 @@ export class PhaseManager {
|
|
|
473
411
|
}
|
|
474
412
|
await this.savePlan(this.plan);
|
|
475
413
|
}
|
|
476
|
-
/**
|
|
477
|
-
* Get next pending phase (respecting dependencies).
|
|
478
|
-
*/
|
|
479
414
|
getNextPhase() {
|
|
480
415
|
if (!this.plan)
|
|
481
416
|
return null;
|
|
482
417
|
for (const phase of this.plan.phases) {
|
|
483
418
|
if (phase.status === 'pending') {
|
|
484
|
-
// Check dependencies
|
|
485
419
|
if (phase.dependsOn && phase.dependsOn.length > 0) {
|
|
486
420
|
const allDepsCompleted = phase.dependsOn.every(depId => {
|
|
487
421
|
const dep = this.plan.phases.find(p => p.id === depId);
|
|
@@ -495,9 +429,6 @@ export class PhaseManager {
|
|
|
495
429
|
}
|
|
496
430
|
return null;
|
|
497
431
|
}
|
|
498
|
-
/**
|
|
499
|
-
* Get plan statistics.
|
|
500
|
-
*/
|
|
501
432
|
getStats() {
|
|
502
433
|
if (!this.plan) {
|
|
503
434
|
return { totalPhases: 0, completedPhases: 0, inProgressPhases: 0, progress: 0 };
|
|
@@ -512,24 +443,15 @@ export class PhaseManager {
|
|
|
512
443
|
progress: total > 0 ? Math.round((completed / total) * 100) : 0,
|
|
513
444
|
};
|
|
514
445
|
}
|
|
515
|
-
/**
|
|
516
|
-
* Convert project name to a filesystem-safe plan file name.
|
|
517
|
-
*/
|
|
518
446
|
toPlanFileName(projectName) {
|
|
519
447
|
return projectName
|
|
520
448
|
.toLowerCase()
|
|
521
449
|
.replace(/[^a-z0-9]+/g, '-')
|
|
522
450
|
.replace(/^-+|-+$/g, '') || 'unnamed';
|
|
523
451
|
}
|
|
524
|
-
/**
|
|
525
|
-
* Load all plans from the plans/ directory.
|
|
526
|
-
* Returns empty array in legacy mode or if no plans exist.
|
|
527
|
-
* Auto-repairs corrupted plans when possible.
|
|
528
|
-
*/
|
|
529
452
|
async loadAllPlans() {
|
|
530
453
|
const plansDir = getPlansDir(this.basePath);
|
|
531
454
|
if (!fs.existsSync(plansDir)) {
|
|
532
|
-
// Legacy mode: try loading single PLAN.yaml
|
|
533
455
|
const legacyPlan = await this.loadPlan();
|
|
534
456
|
return legacyPlan ? [legacyPlan] : [];
|
|
535
457
|
}
|
|
@@ -559,10 +481,6 @@ export class PhaseManager {
|
|
|
559
481
|
}
|
|
560
482
|
return plans;
|
|
561
483
|
}
|
|
562
|
-
/**
|
|
563
|
-
* Get the active plan name from state.yaml.
|
|
564
|
-
* Returns null in legacy mode or if state.yaml doesn't exist.
|
|
565
|
-
*/
|
|
566
484
|
async getActivePlanName() {
|
|
567
485
|
const statePath = getStatePath(this.basePath);
|
|
568
486
|
if (!fs.existsSync(statePath)) {
|
|
@@ -571,10 +489,6 @@ export class PhaseManager {
|
|
|
571
489
|
const result = await safeReadYaml(statePath);
|
|
572
490
|
return result.data?.active_plan || null;
|
|
573
491
|
}
|
|
574
|
-
/**
|
|
575
|
-
* Load and return state.yaml content.
|
|
576
|
-
* Returns null if state.yaml doesn't exist (legacy mode).
|
|
577
|
-
*/
|
|
578
492
|
async loadState() {
|
|
579
493
|
const statePath = getStatePath(this.basePath);
|
|
580
494
|
if (!fs.existsSync(statePath)) {
|
|
@@ -651,9 +565,6 @@ export class PhaseManager {
|
|
|
651
565
|
};
|
|
652
566
|
}
|
|
653
567
|
}
|
|
654
|
-
// ============================================================================
|
|
655
|
-
// Convenience Functions
|
|
656
|
-
// ============================================================================
|
|
657
568
|
const managerCache = new Map();
|
|
658
569
|
function normalizeBasePath(basePath) {
|
|
659
570
|
return path.resolve(basePath || process.cwd());
|
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Secret Scan (Best-effort)
|
|
3
|
-
*
|
|
4
|
-
* This is a lightweight pre-commit guard. It is not a full DLP solution.
|
|
5
|
-
*
|
|
6
|
-
* Design goals:
|
|
7
|
-
* - Scan only the files we are about to commit (staged list)
|
|
8
|
-
* - Avoid dumping secrets in logs; always mask
|
|
9
|
-
* - Keep false-positives low by using strong signatures
|
|
10
|
-
*/
|
|
11
1
|
export type SecretKind = 'private_key' | 'aws_access_key_id' | 'github_token' | 'google_api_key' | 'openai_api_key' | 'slack_token' | 'generic_password';
|
|
12
2
|
export type SecretSeverity = 'high' | 'medium';
|
|
13
3
|
export interface SecretFinding {
|
|
@@ -21,17 +11,13 @@ export interface SecretFinding {
|
|
|
21
11
|
export interface SecretScanConfig {
|
|
22
12
|
version: 1;
|
|
23
13
|
ignore?: {
|
|
24
|
-
/** Glob-like patterns (/, *, ** supported). */
|
|
25
14
|
paths?: string[];
|
|
26
|
-
/** Ignore specific kinds entirely. */
|
|
27
15
|
kinds?: SecretKind[];
|
|
28
16
|
};
|
|
29
17
|
allow?: {
|
|
30
|
-
/** Allowed matches by substring or `re:<regex>` */
|
|
31
18
|
matches?: string[];
|
|
32
19
|
};
|
|
33
20
|
mode?: {
|
|
34
|
-
/** Which severities should block a commit. Default: ['high'] */
|
|
35
21
|
blockSeverities?: SecretSeverity[];
|
|
36
22
|
};
|
|
37
23
|
}
|
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Secret Scan (Best-effort)
|
|
3
|
-
*
|
|
4
|
-
* This is a lightweight pre-commit guard. It is not a full DLP solution.
|
|
5
|
-
*
|
|
6
|
-
* Design goals:
|
|
7
|
-
* - Scan only the files we are about to commit (staged list)
|
|
8
|
-
* - Avoid dumping secrets in logs; always mask
|
|
9
|
-
* - Keep false-positives low by using strong signatures
|
|
10
|
-
*/
|
|
11
1
|
import * as fs from 'node:fs';
|
|
12
2
|
import * as path from 'node:path';
|
|
13
3
|
import { parse as parseYaml } from 'yaml';
|
|
14
|
-
// Prefer strong signatures.
|
|
15
4
|
const PATTERNS = [
|
|
16
5
|
{
|
|
17
6
|
kind: 'private_key',
|
|
@@ -43,8 +32,6 @@ const PATTERNS = [
|
|
|
43
32
|
regex: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/,
|
|
44
33
|
severity: 'high',
|
|
45
34
|
},
|
|
46
|
-
// Lower confidence: password-like assignments.
|
|
47
|
-
// Keep strict: require key name + quotes.
|
|
48
35
|
{
|
|
49
36
|
kind: 'generic_password',
|
|
50
37
|
regex: /\b(?:password|passwd|pwd)\b\s*[:=]\s*['"][^'"]{8,}['"]/i,
|
|
@@ -115,7 +102,6 @@ function matchesAnyGlob(globs, filePath) {
|
|
|
115
102
|
return true;
|
|
116
103
|
}
|
|
117
104
|
catch {
|
|
118
|
-
// ignore invalid glob
|
|
119
105
|
}
|
|
120
106
|
}
|
|
121
107
|
return false;
|
|
@@ -184,13 +170,10 @@ function isProbablyBinary(buf) {
|
|
|
184
170
|
let nonPrintable = 0;
|
|
185
171
|
for (let i = 0; i < max; i++) {
|
|
186
172
|
const b = buf[i];
|
|
187
|
-
// NUL
|
|
188
173
|
if (b === 0)
|
|
189
174
|
return true;
|
|
190
|
-
// allow tabs/newlines/cr
|
|
191
175
|
if (b === 9 || b === 10 || b === 13)
|
|
192
176
|
continue;
|
|
193
|
-
// printable ASCII range
|
|
194
177
|
if (b >= 32 && b <= 126)
|
|
195
178
|
continue;
|
|
196
179
|
nonPrintable++;
|
|
@@ -205,7 +188,6 @@ function maskValue(value) {
|
|
|
205
188
|
}
|
|
206
189
|
function maskLine(line, match) {
|
|
207
190
|
const masked = maskValue(match);
|
|
208
|
-
// Replace only first occurrence to keep context
|
|
209
191
|
return line.replace(match, masked);
|
|
210
192
|
}
|
|
211
193
|
export function scanFilesForSecrets(options) {
|
|
@@ -263,7 +245,6 @@ export function scanFilesForSecrets(options) {
|
|
|
263
245
|
matchMasked: maskValue(rawMatch),
|
|
264
246
|
preview: maskLine(line, rawMatch).slice(0, 300),
|
|
265
247
|
});
|
|
266
|
-
// Only one finding per pattern per line.
|
|
267
248
|
break;
|
|
268
249
|
}
|
|
269
250
|
}
|
|
@@ -144,7 +144,6 @@ function isPlanContractViolated(task, plan) {
|
|
|
144
144
|
return false;
|
|
145
145
|
if (!task.files || task.files.length === 0)
|
|
146
146
|
return false;
|
|
147
|
-
// Violation: task touches files NOT covered by any agreed structural change
|
|
148
147
|
const agreedFiles = new Set();
|
|
149
148
|
for (const sc of agreedChanges) {
|
|
150
149
|
for (const file of sc.affectedFiles)
|
|
@@ -222,11 +221,9 @@ function generateBrief(task, phase, plan, agentTier, mask) {
|
|
|
222
221
|
lines.push(`---`);
|
|
223
222
|
return lines.join('\n');
|
|
224
223
|
}
|
|
225
|
-
// Remove dead code: generateTaskBrief was duplicated inline above
|
|
226
224
|
async function runVerification(basePath, task) {
|
|
227
225
|
const checks = [];
|
|
228
226
|
let allPassed = true;
|
|
229
|
-
// 1. TypeScript / build check
|
|
230
227
|
try {
|
|
231
228
|
const tsConfigPath = path.join(basePath, 'tsconfig.json');
|
|
232
229
|
if (fs.existsSync(tsConfigPath)) {
|
|
@@ -249,7 +246,6 @@ async function runVerification(basePath, task) {
|
|
|
249
246
|
catch {
|
|
250
247
|
checks.push('⏭️ TypeScript check failed to run');
|
|
251
248
|
}
|
|
252
|
-
// 2. GDC sync
|
|
253
249
|
const gdc = getEffectiveGdcConfig(basePath);
|
|
254
250
|
if (gdc.enabled) {
|
|
255
251
|
try {
|
|
@@ -266,7 +262,6 @@ async function runVerification(basePath, task) {
|
|
|
266
262
|
checks.push('⏭️ GDC sync error');
|
|
267
263
|
}
|
|
268
264
|
}
|
|
269
|
-
// 3. Task-specific verification
|
|
270
265
|
if (task.verify) {
|
|
271
266
|
for (const v of task.verify) {
|
|
272
267
|
if (v.kind === 'checklist') {
|
|
@@ -349,7 +344,6 @@ export async function executeBuildLoop(options) {
|
|
|
349
344
|
while (state.status === 'running') {
|
|
350
345
|
const next = pickNextTask(plan, state, phaseFilter);
|
|
351
346
|
if (!next) {
|
|
352
|
-
// Check if all tasks completed
|
|
353
347
|
const allPassed = plan.phases.every(p => p.tasks.every(t => {
|
|
354
348
|
const ts = state.tasks.find(s => s.taskId === t.id && s.phaseId === p.id);
|
|
355
349
|
return ts?.status === 'passed' || t.status === 'passed';
|
|
@@ -368,7 +362,6 @@ export async function executeBuildLoop(options) {
|
|
|
368
362
|
const { phase, task } = next;
|
|
369
363
|
state.currentPhaseId = phase.id;
|
|
370
364
|
state.currentTaskId = task.id;
|
|
371
|
-
// Check plan contract violation
|
|
372
365
|
if (isPlanContractViolated(task, plan)) {
|
|
373
366
|
state.status = 'blocked';
|
|
374
367
|
state.escalationReason = `Task ${task.id} violates agreed plan contract (structural changes)`;
|
|
@@ -394,7 +387,6 @@ export async function executeBuildLoop(options) {
|
|
|
394
387
|
}
|
|
395
388
|
onEvent?.({ type: 'task_started', phaseId: phase.id, taskId: task.id });
|
|
396
389
|
onMsg(`▶️ Running ${task.id} (${taskAgentTier})`);
|
|
397
|
-
// Execute task — generate brief for AI agent
|
|
398
390
|
const taskStatus = state.tasks.find(t => t.taskId === task.id && t.phaseId === phase.id);
|
|
399
391
|
const taskResult = await executeTask(task, phase, plan, orchestrator, basePath, onEvent);
|
|
400
392
|
if (taskStatus && taskResult.instructions) {
|
|
@@ -404,10 +396,8 @@ export async function executeBuildLoop(options) {
|
|
|
404
396
|
instructions.push(taskResult.instructions);
|
|
405
397
|
}
|
|
406
398
|
if (taskResult.success) {
|
|
407
|
-
// Verify
|
|
408
399
|
const verification = await runVerification(basePath, task);
|
|
409
400
|
if (verification.passed) {
|
|
410
|
-
// Mark task as passed
|
|
411
401
|
task.status = 'passed';
|
|
412
402
|
const ts = state.tasks.find(t => t.taskId === task.id && t.phaseId === phase.id);
|
|
413
403
|
if (ts) {
|
|
@@ -415,7 +405,6 @@ export async function executeBuildLoop(options) {
|
|
|
415
405
|
ts.completedAt = new Date().toISOString();
|
|
416
406
|
ts.commitHash = taskResult.commitHash;
|
|
417
407
|
}
|
|
418
|
-
// Update OpenSpec tasks
|
|
419
408
|
try {
|
|
420
409
|
if (plan.openspecDir) {
|
|
421
410
|
const changeId = plan.planName || 'main';
|
|
@@ -423,9 +412,7 @@ export async function executeBuildLoop(options) {
|
|
|
423
412
|
}
|
|
424
413
|
}
|
|
425
414
|
catch { }
|
|
426
|
-
// GDC sync per task
|
|
427
415
|
try {
|
|
428
|
-
// Verification already ran GDC sync (no need to repeat)
|
|
429
416
|
await lightReMap(basePath);
|
|
430
417
|
}
|
|
431
418
|
catch { }
|
|
@@ -446,14 +433,12 @@ export async function executeBuildLoop(options) {
|
|
|
446
433
|
iterationsWithoutProgress++;
|
|
447
434
|
onMsg(`❌ ${task.id} failed: ${(taskResult.error || '').slice(0, 100)}`);
|
|
448
435
|
}
|
|
449
|
-
// Check no-progress limit
|
|
450
436
|
if (iterationsWithoutProgress >= maxIterationsWithoutProgress) {
|
|
451
437
|
state.status = 'blocked';
|
|
452
438
|
state.escalationReason = `No progress after ${iterationsWithoutProgress} consecutive task failures. Last: ${state.tasks.filter(t => t.status === 'failed').pop()?.taskId || 'unknown'}`;
|
|
453
439
|
onMsg(`⛔ Blocked: ${state.escalationReason}`);
|
|
454
440
|
break;
|
|
455
441
|
}
|
|
456
|
-
// Save state after each task
|
|
457
442
|
state.updatedAt = new Date().toISOString();
|
|
458
443
|
await saveBuildState(basePath, state);
|
|
459
444
|
}
|
|
@@ -1,14 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Weave Execute Stage
|
|
3
|
-
*
|
|
4
|
-
* Generates execution plans with automatic mask and agent tier selection.
|
|
5
|
-
* Actual code generation/testing is performed by AI agents (dummy-flash/human/premium)
|
|
6
|
-
* via the Task tool — this module handles:
|
|
7
|
-
* - Phase validation and dependency checking
|
|
8
|
-
* - Execution plan generation (mask + agent tier per task)
|
|
9
|
-
* - Formatting the plan for the Mask Weaver to act upon
|
|
10
|
-
* - AI-driven verification system integration
|
|
11
|
-
*/
|
|
12
1
|
import type { WeavePhase, WeaveTask, WeaveEvent, PhaseExecutionPlan } from '../types.js';
|
|
13
2
|
import { WeaveOrchestrator } from '../orchestrator.js';
|
|
14
3
|
export interface ExecuteOptions {
|
|
@@ -16,7 +5,6 @@ export interface ExecuteOptions {
|
|
|
16
5
|
onEvent?: (event: WeaveEvent) => void;
|
|
17
6
|
projectType?: string;
|
|
18
7
|
techStack?: string[];
|
|
19
|
-
/** Base path for .opencode/weave (defaults to process.cwd()) */
|
|
20
8
|
basePath?: string;
|
|
21
9
|
}
|
|
22
10
|
export interface PrepareResult {
|
|
@@ -42,34 +30,9 @@ export interface TaskExecutionContext {
|
|
|
42
30
|
projectType?: string;
|
|
43
31
|
techStack?: string[];
|
|
44
32
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Prepare a phase for execution.
|
|
47
|
-
*
|
|
48
|
-
* This is the primary entry point for craft. It:
|
|
49
|
-
* 1. Validates dependencies
|
|
50
|
-
* 2. Marks the phase as in_progress
|
|
51
|
-
* 3. Generates an execution plan (mask + agent tier per task)
|
|
52
|
-
* 4. Returns the plan for the Mask Weaver to delegate via Task tool
|
|
53
|
-
*
|
|
54
|
-
* The actual code generation/testing is performed by AI agents
|
|
55
|
-
* (dummy-flash, dummy-human, dummy-premium) — not by this function.
|
|
56
|
-
*/
|
|
57
33
|
export declare function preparePhaseExecution(options: ExecuteOptions): Promise<PrepareResult>;
|
|
58
|
-
/**
|
|
59
|
-
* Format a PhaseExecutionPlan into markdown instructions
|
|
60
|
-
* that the Mask Weaver can read and act upon.
|
|
61
|
-
*/
|
|
62
34
|
export declare function formatExecutionPlan(plan: PhaseExecutionPlan): string;
|
|
63
|
-
/**
|
|
64
|
-
* @deprecated Use preparePhaseExecution() + formatExecutionPlan() instead.
|
|
65
|
-
* Kept for backward compatibility.
|
|
66
|
-
*/
|
|
67
35
|
export declare function execute(options: ExecuteOptions): Promise<ExecuteResult>;
|
|
68
|
-
/**
|
|
69
|
-
* Multi-layer verification that AI can perform automatically.
|
|
70
|
-
* Each layer returns pass/fail with error details.
|
|
71
|
-
* If any layer fails, the execute loop will retry.
|
|
72
|
-
*/
|
|
73
36
|
export interface VerificationLayer {
|
|
74
37
|
name: string;
|
|
75
38
|
order: number;
|
|
@@ -91,13 +54,8 @@ export interface AIVerificationOptions {
|
|
|
91
54
|
enableScreenshots?: boolean;
|
|
92
55
|
enablePlaywright?: boolean;
|
|
93
56
|
enableDevTools?: boolean;
|
|
94
|
-
/** Verification scope. quick: TypeCheck + UnitTests only. full: all available. */
|
|
95
57
|
mode?: 'quick' | 'full';
|
|
96
58
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Run all verification layers in order.
|
|
99
|
-
* Returns as soon as any layer fails.
|
|
100
|
-
*/
|
|
101
59
|
export declare function runAIVerification(options: AIVerificationOptions): Promise<{
|
|
102
60
|
passed: boolean;
|
|
103
61
|
results: VerificationResult[];
|