maskweaver 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,8 +18,7 @@ import { archiveChange } from '../../weave/stages/archive.js';
18
18
  import { generateStatusReport, handleUserResponse } from '../../weave/stages/handoff.js';
19
19
  import { analyzeCodebase, runGraphifyAnalysis, readMapResult } from '../../weave/stages/map.js';
20
20
  import { interview as interviewStage, listInterviewStates } from '../../weave/stages/intake.js';
21
- import { executeBuildLoop, generateBuildState, generateBuildId, loadBuildState } from '../../weave/stages/build.js';
22
- import { WeaveOrchestrator } from '../../weave/orchestrator.js';
21
+ import { generateBuildId } from '../../weave/stages/build.js';
23
22
  import { getPhaseManager } from '../../weave/phase-manager.js';
24
23
  import { recommendVerificationCommands, formatRecommendedCommandsAsBash } from '../../weave/verification/index.js';
25
24
  import { createWeaveWorktree, listWeaveWorktrees, resolveWeaveWorktree, removeWeaveWorktree, ensureIgnoreOverride, ensureWeaveState, } from '../../weave/worktree.js';
@@ -27,10 +26,11 @@ import { ensureGitRepo, stageAllChanges, listStagedFiles, hasStagedChanges, comm
27
26
  import { scanFilesForSecrets, loadSecretScanConfig, shouldBlockOnFindings, formatSecretScanReport } from '../../weave/security/secret-scan.js';
28
27
  import { searchTroubleshooting, recordTroubleshooting, GlobalKnowledge } from '../../weave/knowledge/global.js';
29
28
  import { ensureChangeArtifact, readChangeMetadata, writeChangeVerificationReport } from '../../weave/change-artifacts.js';
29
+ import { advanceBuildStep } from '../../weave/wave-executor.js';
30
30
  import { analyzeParallelOpportunities, executionPlanToSquadTasks } from '../../weave/bridge.js';
31
31
  import { acquireLoopOperatorLock, appendLoopEvent, createLoopRun, ensureLoopContract, listLoopRuns, readLoopRun, releaseLoopOperatorLock, refreshLoopOperatorLock, requestLoopStop, toLoopOperatorStatePath, resolveLoopId, toLoopRunPath, updateLoopRun, writeLoopOperatorState, writeLoopAttemptControllerNotes, writeLoopAttemptTaskBundle, writeLoopAttemptWorkerBrief, writeLoopAttemptVerificationReport, } from '../../weave/loop.js';
32
32
  import { getEffectiveGdcConfig, runGdcMachineCommand, countGdcCheckIssues, getStatsNodeSummary, } from '../../weave/gdc.js';
33
- import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, } from '../../shared/generate-agents.js';
33
+ import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, writeAutoDetectedConfig, formatProviderChecklist, } from '../../shared/generate-agents.js';
34
34
  import { resolveCommand, loadCommandsJson } from './command-registry.js';
35
35
  export function createWeaveTool() {
36
36
  return {
@@ -61,6 +61,8 @@ export function createWeaveTool() {
61
61
  .describe('Force regenerate agent .md files from config pool (for agents command)'),
62
62
  init: z.boolean().optional()
63
63
  .describe('Create default maskweaver.config.json with pool template (for agents command)'),
64
+ force: z.boolean().optional()
65
+ .describe('Force re-detect subscription and overwrite maskweaver.config.json (for agents command)'),
64
66
  docsPath: z.string().optional()
65
67
  .describe('Path to requirements documents (for design command)'),
66
68
  phaseId: z.string().optional()
@@ -129,6 +131,8 @@ export function createWeaveTool() {
129
131
  .describe('Maximum retries per task (for build command)'),
130
132
  buildId: z.string().optional()
131
133
  .describe('Build ID to resume (for build-resume command)'),
134
+ taskResults: z.string().optional()
135
+ .describe('JSON array of TaskResult from previous wave (for resume)'),
132
136
  phaseIds: z.string().optional()
133
137
  .describe('Comma-separated phase IDs (for build command)'),
134
138
  },
@@ -163,7 +167,7 @@ export function createWeaveTool() {
163
167
  result = await handleApprovePlan(args, basePath);
164
168
  break;
165
169
  case 'craft':
166
- result = await handleCraft(args, basePath);
170
+ result = '> ⚠️ `craft` is deprecated. Use `weave command=build` instead — it now auto-approves and runs the full build loop (craft + build + verify).\n\n' + await handleBuildUnified(args, basePath);
167
171
  break;
168
172
  case 'build':
169
173
  result = await handleBuildUnified(args, basePath);
@@ -1945,48 +1949,90 @@ async function handleInterview(args, basePath) {
1945
1949
  }
1946
1950
  async function handleBuild(args, basePath) {
1947
1951
  const lines = [];
1948
- lines.push('## 🏗️ Build');
1952
+ lines.push('## 🏗️ Build (Wave)');
1949
1953
  lines.push('');
1950
1954
  const manager = getPhaseManager(basePath);
1951
1955
  const plan = await manager.loadPlan();
1952
1956
  if (!plan) {
1953
- return 'Error: No active plan found. Run `weave command=design docsPath="docs/"` first.';
1957
+ return 'Error: No active plan found. Run `weave command=prepare docsPath="docs/"` first.';
1954
1958
  }
1955
1959
  if (!plan.planApproved) {
1956
- return 'Error: Plan not approved. Run `weave command=approve` first.';
1960
+ plan.planApproved = true;
1961
+ plan.planApprovedAt = new Date().toISOString();
1962
+ plan.planApprovalNotes = 'Auto-approved by build command.';
1963
+ await manager.savePlan(plan);
1964
+ lines.push(`> ⚡ Plan auto-approved: **${plan.projectName}**`);
1965
+ lines.push('');
1957
1966
  }
1958
- lines.push(`Plan: **${plan.projectName}** (approved at ${plan.planApprovedAt || 'N/A'})`);
1959
- lines.push('');
1960
- const orchestrator = new WeaveOrchestrator();
1967
+ const changeId = plan.activeChangeId || plan.planName || 'main';
1961
1968
  const buildId = generateBuildId();
1962
- const state = generateBuildState(buildId, plan.planName || plan.projectName, args.maxRetries || 3);
1963
- const onMessages = [];
1964
- lines.push('Starting autonomous build loop...');
1965
- lines.push('');
1966
- const result = await executeBuildLoop({
1967
- plan,
1968
- state,
1969
- orchestrator,
1970
- basePath,
1971
- maxRetries: args.maxRetries,
1972
- phaseIds: args.phaseIds ? args.phaseIds.split(',').map((id) => id.trim()).filter(Boolean) : undefined,
1973
- onMessage: (msg) => { onMessages.push(msg); },
1974
- });
1975
- for (const msg of onMessages) {
1976
- lines.push(msg);
1977
- }
1969
+ lines.push(`Plan: **${plan.projectName}** (approved at ${plan.planApprovedAt || 'N/A'})`);
1970
+ lines.push(`Build: \`${buildId}\``);
1978
1971
  lines.push('');
1979
- if (result.success) {
1980
- lines.push('## Build Complete');
1981
- }
1982
- else {
1983
- lines.push('## ⚠️ Build Blocked');
1972
+ try {
1973
+ const decision = await advanceBuildStep({
1974
+ plan,
1975
+ basePath,
1976
+ buildId,
1977
+ changeId,
1978
+ maxRetries: args.maxRetries || 3,
1979
+ phaseIds: args.phaseIds ? args.phaseIds.split(',').map(s => s.trim()).filter(Boolean) : undefined,
1980
+ });
1981
+ switch (decision.kind) {
1982
+ case 'dispatch_wave': {
1983
+ lines.push(`### Wave ${decision.wave.waveIndex} — ${decision.contracts.length} task(s)`);
1984
+ lines.push(`Parallel-safe: ${decision.wave.parallelSafe ? '✅ Yes' : '⚠️ No (sequential)'}`);
1985
+ lines.push('');
1986
+ for (const contract of decision.contracts) {
1987
+ lines.push(`#### ${contract.taskId} — \`${contract.subagentType}\`${contract.mask ? ` (${contract.mask})` : ''}`);
1988
+ lines.push(`- Allowed: ${contract.allowedPaths.length > 0 ? contract.allowedPaths.join(', ') : '*'}`);
1989
+ lines.push(`- Verify: ${contract.verifyCommands.join('; ') || 'none'}`);
1990
+ lines.push(`- Brief: \`${contract.briefPath}\``);
1991
+ lines.push(`- Context: \`${contract.contextPath}\``);
1992
+ lines.push('');
1993
+ lines.push('```');
1994
+ lines.push(`Task(${contract.subagentType}, prompt=Read ${contract.briefPath} and execute the task.)`);
1995
+ lines.push('```');
1996
+ lines.push('');
1997
+ }
1998
+ lines.push('---');
1999
+ lines.push(`After Task() calls complete, pass results:`);
2000
+ lines.push('```');
2001
+ lines.push(`weave command=build action=resume buildId="${buildId}" taskResults='[{"taskId":"<id>","phaseId":"<pid>","status":"succeeded","changedFiles":["file.ts"],"createdSymbols":[],"downstreamExports":[]}]'`);
2002
+ lines.push('```');
2003
+ break;
2004
+ }
2005
+ case 'verify': {
2006
+ lines.push(`### Verifying Wave ${decision.waveIndex}`);
2007
+ lines.push('Running verification commands...');
2008
+ break;
2009
+ }
2010
+ case 'repair': {
2011
+ lines.push(`### 🔧 Repair: ${decision.contract.taskId}`);
2012
+ lines.push(`Failure: ${decision.failureKind}`);
2013
+ lines.push('');
2014
+ lines.push('```');
2015
+ lines.push(`Task(${decision.contract.subagentType}, prompt=Read ${decision.contract.briefPath} and fix the issues.)`);
2016
+ lines.push('```');
2017
+ break;
2018
+ }
2019
+ case 'blocked': {
2020
+ lines.push(`### ⛔ Blocked`);
2021
+ lines.push(decision.reason);
2022
+ if (decision.failedTasks.length > 0) {
2023
+ lines.push(`Failed tasks: ${decision.failedTasks.join(', ')}`);
2024
+ }
2025
+ break;
2026
+ }
2027
+ case 'complete': {
2028
+ lines.push('### ✅ Build Complete');
2029
+ lines.push(decision.summary);
2030
+ break;
2031
+ }
2032
+ }
1984
2033
  }
1985
- lines.push('');
1986
- lines.push(result.summary);
1987
- if (result.tasksEscalated > 0 || result.tasksFailed > 0) {
1988
- lines.push('');
1989
- lines.push('To resume after fixing issues: `weave command=build-resume buildId="<buildId>"`');
2034
+ catch (e) {
2035
+ lines.push(`❌ Error: ${e instanceof Error ? e.message : String(e)}`);
1990
2036
  }
1991
2037
  return lines.join('\n');
1992
2038
  }
@@ -1995,31 +2041,87 @@ async function handleBuildResume(args, basePath) {
1995
2041
  lines.push('## 🔄 Build Resume');
1996
2042
  lines.push('');
1997
2043
  if (!args.buildId) {
1998
- return 'Error: buildId is required. Use `weave command=build-resume buildId="<id>"`.';
1999
- }
2000
- const state = await loadBuildState(basePath, args.buildId);
2001
- if (!state) {
2002
- return `Error: Build state not found: ${args.buildId}`;
2003
- }
2004
- if (state.status !== 'blocked') {
2005
- return `Build ${args.buildId} is not blocked (status: ${state.status}). No need to resume.`;
2044
+ return 'Error: buildId is required. Use `weave command=build action=resume buildId="<id>"`.';
2006
2045
  }
2007
2046
  const manager = getPhaseManager(basePath);
2008
2047
  const plan = await manager.loadPlan();
2009
2048
  if (!plan) {
2010
2049
  return 'Error: No active plan found.';
2011
2050
  }
2012
- state.status = 'running';
2013
- state.escalationReason = undefined;
2014
- const orchestrator = new WeaveOrchestrator();
2015
- const result = await executeBuildLoop({
2016
- plan,
2017
- state,
2018
- orchestrator,
2019
- basePath,
2020
- maxRetries: args.maxRetries || 3,
2021
- });
2022
- lines.push(result.summary);
2051
+ const changeId = plan.activeChangeId || plan.planName || 'main';
2052
+ let lastResults = [];
2053
+ if (args.taskResults) {
2054
+ try {
2055
+ lastResults = JSON.parse(args.taskResults);
2056
+ }
2057
+ catch {
2058
+ lines.push('> ⚠️ Could not parse taskResults, proceeding without previous results.');
2059
+ }
2060
+ }
2061
+ else {
2062
+ lines.push('> ⚠️ No taskResults provided. Pass results from Task() calls as JSON:');
2063
+ lines.push('> `weave command=build action=resume buildId="..." taskResults=\'[{"taskId":"...","phaseId":"...","status":"succeeded","changedFiles":[],"createdSymbols":[],"downstreamExports":[]}]\'`');
2064
+ lines.push('');
2065
+ }
2066
+ try {
2067
+ const decision = await advanceBuildStep({
2068
+ plan,
2069
+ basePath,
2070
+ buildId: args.buildId,
2071
+ changeId,
2072
+ lastResults: lastResults.length > 0 ? lastResults : undefined,
2073
+ maxRetries: args.maxRetries || 3,
2074
+ });
2075
+ switch (decision.kind) {
2076
+ case 'dispatch_wave': {
2077
+ lines.push(`### Next Wave ${decision.wave.waveIndex} — ${decision.contracts.length} task(s)`);
2078
+ lines.push(`Parallel-safe: ${decision.wave.parallelSafe ? '✅ Yes' : '⚠️ No'}`);
2079
+ lines.push('');
2080
+ for (const contract of decision.contracts) {
2081
+ lines.push(`#### ${contract.taskId} — \`${contract.subagentType}\``);
2082
+ lines.push('```');
2083
+ lines.push(`Task(${contract.subagentType}, prompt=Read ${contract.briefPath} and execute the task.)`);
2084
+ lines.push('```');
2085
+ lines.push('');
2086
+ }
2087
+ lines.push(`After Task() calls complete, pass results:`);
2088
+ lines.push('```');
2089
+ lines.push(`weave command=build action=resume buildId="${args.buildId}" taskResults='[{"taskId":"<id>","phaseId":"<pid>","status":"succeeded","changedFiles":["file.ts"],"createdSymbols":[],"downstreamExports":[]}]'`);
2090
+ lines.push('```');
2091
+ break;
2092
+ }
2093
+ case 'repair': {
2094
+ lines.push(`### 🔧 Repair: ${decision.contract.taskId}`);
2095
+ lines.push(`Failure: ${decision.failureKind}`);
2096
+ lines.push('```');
2097
+ lines.push(`Task(${decision.contract.subagentType}, prompt=Read ${decision.contract.briefPath} and fix.)`);
2098
+ lines.push('```');
2099
+ lines.push('');
2100
+ lines.push(`After fix, pass results:`);
2101
+ lines.push('```');
2102
+ lines.push(`weave command=build action=resume buildId="${args.buildId}" taskResults='[{"taskId":"${decision.contract.taskId}","phaseId":"${decision.contract.phaseId}","status":"succeeded","changedFiles":[],"createdSymbols":[],"downstreamExports":[]}]'`);
2103
+ lines.push('```');
2104
+ break;
2105
+ }
2106
+ case 'blocked': {
2107
+ lines.push('### ⛔ Build Blocked');
2108
+ lines.push(decision.reason);
2109
+ break;
2110
+ }
2111
+ case 'complete': {
2112
+ lines.push('### ✅ Build Complete');
2113
+ lines.push(decision.summary);
2114
+ break;
2115
+ }
2116
+ case 'verify': {
2117
+ lines.push(`### Verifying Wave ${decision.waveIndex}...`);
2118
+ break;
2119
+ }
2120
+ }
2121
+ }
2122
+ catch (e) {
2123
+ lines.push(`❌ Error: ${e instanceof Error ? e.message : String(e)}`);
2124
+ }
2023
2125
  return lines.join('\n');
2024
2126
  }
2025
2127
  async function handleCraft(args, basePath) {
@@ -2429,6 +2531,59 @@ async function handleInitConfig(basePath) {
2429
2531
  lines.push('> with your model pool, then run `weave sync-agents` in any project to apply it.');
2430
2532
  return lines.join('\n');
2431
2533
  }
2534
+ async function handleWaveBuildStatus(buildId, basePath) {
2535
+ const manager = getPhaseManager(basePath);
2536
+ const plan = await manager.loadPlan();
2537
+ if (!plan)
2538
+ return null;
2539
+ const changeId = plan.activeChangeId || plan.planName || 'main';
2540
+ const buildDir = path.join(basePath, 'changes', changeId, 'builds', buildId);
2541
+ if (!fs.existsSync(buildDir))
2542
+ return null;
2543
+ const lines = [];
2544
+ lines.push(`## Wave Build Status: \`${buildId}\``);
2545
+ lines.push('');
2546
+ const wavesDir = path.join(buildDir, 'waves');
2547
+ if (fs.existsSync(wavesDir)) {
2548
+ const waveFiles = fs.readdirSync(wavesDir).filter(f => f.startsWith('wave-')).sort();
2549
+ for (const wf of waveFiles) {
2550
+ const content = fs.readFileSync(path.join(wavesDir, wf), 'utf-8');
2551
+ lines.push(`### ${wf.replace('.md', '')}`);
2552
+ lines.push('```');
2553
+ lines.push(content.slice(0, 2000));
2554
+ lines.push('```');
2555
+ lines.push('');
2556
+ }
2557
+ }
2558
+ const tasksDir = path.join(buildDir, 'tasks');
2559
+ if (fs.existsSync(tasksDir)) {
2560
+ const taskDirs = fs.readdirSync(tasksDir, { withFileTypes: true }).filter(d => d.isDirectory());
2561
+ lines.push(`### Tasks (${taskDirs.length})`);
2562
+ lines.push('');
2563
+ for (const td of taskDirs) {
2564
+ const resultPath = path.join(tasksDir, td.name, 'result.md');
2565
+ const briefPath = path.join(tasksDir, td.name, 'brief.md');
2566
+ if (fs.existsSync(resultPath)) {
2567
+ const resultContent = fs.readFileSync(resultPath, 'utf-8');
2568
+ const statusMatch = resultContent.match(/\*\*Status:\*\*\s*(\w+)/);
2569
+ lines.push(`- ${td.name}: ${statusMatch?.[1] || 'unknown'}`);
2570
+ }
2571
+ else if (fs.existsSync(briefPath)) {
2572
+ lines.push(`- ${td.name}: dispatched (no result yet)`);
2573
+ }
2574
+ }
2575
+ lines.push('');
2576
+ }
2577
+ const contextIndexPath = path.join(buildDir, 'context-index.yaml');
2578
+ if (fs.existsSync(contextIndexPath)) {
2579
+ lines.push('### Context Index');
2580
+ lines.push('```yaml');
2581
+ lines.push(fs.readFileSync(contextIndexPath, 'utf-8').slice(0, 1500));
2582
+ lines.push('```');
2583
+ lines.push('');
2584
+ }
2585
+ return lines.join('\n');
2586
+ }
2432
2587
  async function handleBuildUnified(args, basePath) {
2433
2588
  const action = args.action || 'run';
2434
2589
  switch (action) {
@@ -2439,13 +2594,16 @@ async function handleBuildUnified(args, basePath) {
2439
2594
  case 'status': {
2440
2595
  const loopId = args.buildId || args.loopId;
2441
2596
  if (!loopId)
2442
- return 'Error: buildId or loopId is required for status action. Example: weave command=build action=status buildId="build-20250428-a1b2"';
2597
+ return 'Error: buildId is required. Example: weave command=build action=status buildId="build-20250428-a1b2"';
2598
+ const waveStatus = await handleWaveBuildStatus(loopId, basePath);
2599
+ if (waveStatus)
2600
+ return waveStatus;
2443
2601
  return handleLoopStatus({ loopId }, basePath);
2444
2602
  }
2445
2603
  case 'stop': {
2446
2604
  const loopId = args.buildId || args.loopId;
2447
2605
  if (!loopId)
2448
- return 'Error: buildId or loopId is required for stop action. Example: weave command=build action=stop buildId="build-20250428-a1b2"';
2606
+ return 'Error: buildId is required. Example: weave command=build action=stop buildId="build-20250428-a1b2"';
2449
2607
  return handleLoopStop({ loopId, context: undefined }, basePath);
2450
2608
  }
2451
2609
  case 'list':
@@ -2461,10 +2619,20 @@ async function handleBuildUnified(args, basePath) {
2461
2619
  }
2462
2620
  }
2463
2621
  async function handleAgents(args, basePath) {
2464
- if (!args.sync && !args.init) {
2465
- return 'Error: agents requires an action. Use `sync=true` to regenerate agent files, or `init=true` to create default config.';
2622
+ if (!args.sync && !args.init && !args.force) {
2623
+ return 'Error: agents requires an action. Use `sync=true` to regenerate agent files, `init=true` to create default config, or `force=true` to re-detect subscription and overwrite config.';
2466
2624
  }
2467
2625
  const sections = [];
2626
+ if (args.force) {
2627
+ const result = writeAutoDetectedConfig(basePath, true);
2628
+ if (result) {
2629
+ sections.push(`## ✅ Config Force-Updated\n\nAuto-detected subscription: \`${result.detection.primary}\` (${result.detection.subscriptions.join(', ')})\n\n\`\`\`\n${formatProviderChecklist(result.detection)}\n\`\`\`\n\nWrote to: \`${toWorkspaceRelative(basePath, result.path)}\``);
2630
+ }
2631
+ else {
2632
+ sections.push('## ❌ Force update failed\n\nCould not auto-detect subscription. Make sure opencode CLI is available.');
2633
+ }
2634
+ sections.push(await handleSyncAgents(basePath));
2635
+ }
2468
2636
  if (args.sync) {
2469
2637
  sections.push(await handleSyncAgents(basePath));
2470
2638
  }
@@ -117,6 +117,7 @@ export interface ModelPoolEntry {
117
117
  maxConcurrent: number;
118
118
  capabilities: ModelCapability[];
119
119
  costTier: ModelCostTier;
120
+ priority?: number;
120
121
  description?: string;
121
122
  }
122
123
  export type DummyHumansConfig = Record<string, string> | {
@@ -35,7 +35,7 @@ export declare function detectSubscriptionsFromConfig(opencodeConfig: Record<str
35
35
  export declare function buildPoolFromDetection(detection: SubscriptionDetectionResult): any[];
36
36
  export declare function buildConfigFromDetection(detection: SubscriptionDetectionResult): Record<string, any>;
37
37
  export declare function formatProviderChecklist(detection: SubscriptionDetectionResult): string;
38
- export declare function writeAutoDetectedConfig(projectDir: string): {
38
+ export declare function writeAutoDetectedConfig(projectDir: string, force?: boolean): {
39
39
  path: string;
40
40
  detection: SubscriptionDetectionResult;
41
41
  } | null;
@@ -48,6 +48,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
48
48
  readonly maxConcurrent: 5;
49
49
  readonly capabilities: readonly ["search", "formatting", "simple-coding", "file-ops"];
50
50
  readonly costTier: "low";
51
+ readonly priority: 1;
51
52
  readonly description: "DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업";
52
53
  }, {
53
54
  readonly id: "deepseek-general";
@@ -56,6 +57,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
56
57
  readonly maxConcurrent: 3;
57
58
  readonly capabilities: readonly ["coding", "testing", "refactoring", "backend"];
58
59
  readonly costTier: "medium";
60
+ readonly priority: 2;
59
61
  readonly description: "DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드";
60
62
  }, {
61
63
  readonly id: "qwen-vision";
@@ -64,6 +66,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
64
66
  readonly maxConcurrent: 3;
65
67
  readonly capabilities: readonly ["vision", "frontend", "testing"];
66
68
  readonly costTier: "medium";
69
+ readonly priority: 1;
67
70
  readonly description: "Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트";
68
71
  }, {
69
72
  readonly id: "deepseek-pro";
@@ -72,6 +75,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
72
75
  readonly maxConcurrent: 2;
73
76
  readonly capabilities: readonly ["architecture", "debugging", "reasoning", "complex-coding", "refactoring"];
74
77
  readonly costTier: "high";
78
+ readonly priority: 2;
75
79
  readonly description: "DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅";
76
80
  }, {
77
81
  readonly id: "kimi-vision";
@@ -80,6 +84,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
80
84
  readonly maxConcurrent: 2;
81
85
  readonly capabilities: readonly ["vision", "reasoning", "complex-coding", "architecture", "debugging"];
82
86
  readonly costTier: "high";
87
+ readonly priority: 1;
83
88
  readonly description: "Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론";
84
89
  }];
85
90
  };
@@ -271,6 +271,7 @@ function buildZaiPool() {
271
271
  maxConcurrent: 1,
272
272
  capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
273
273
  costTier: 'low',
274
+ priority: 1,
274
275
  description: 'GLM-5 Turbo - 빠름. 단순 검색/포매팅/파일작업',
275
276
  },
276
277
  {
@@ -280,6 +281,7 @@ function buildZaiPool() {
280
281
  maxConcurrent: 10,
281
282
  capabilities: ['coding', 'testing', 'refactoring', 'backend'],
282
283
  costTier: 'medium',
284
+ priority: 1,
283
285
  description: 'GLM-5.1 - 일반. 코딩/리팩토링/백엔드',
284
286
  },
285
287
  {
@@ -289,6 +291,7 @@ function buildZaiPool() {
289
291
  maxConcurrent: 10,
290
292
  capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
291
293
  costTier: 'high',
294
+ priority: 1,
292
295
  description: 'GLM-5.1 - 고급 추론. 아키텍처/복잡 디버깅',
293
296
  },
294
297
  ];
@@ -302,6 +305,7 @@ function buildOpencodeGoPool() {
302
305
  maxConcurrent: 5,
303
306
  capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
304
307
  costTier: 'low',
308
+ priority: 1,
305
309
  description: 'DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업',
306
310
  },
307
311
  {
@@ -311,6 +315,7 @@ function buildOpencodeGoPool() {
311
315
  maxConcurrent: 3,
312
316
  capabilities: ['coding', 'testing', 'refactoring', 'backend'],
313
317
  costTier: 'medium',
318
+ priority: 2,
314
319
  description: 'DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드',
315
320
  },
316
321
  {
@@ -320,6 +325,7 @@ function buildOpencodeGoPool() {
320
325
  maxConcurrent: 3,
321
326
  capabilities: ['vision', 'frontend', 'testing'],
322
327
  costTier: 'medium',
328
+ priority: 1,
323
329
  description: 'Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트',
324
330
  },
325
331
  {
@@ -329,6 +335,7 @@ function buildOpencodeGoPool() {
329
335
  maxConcurrent: 2,
330
336
  capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
331
337
  costTier: 'high',
338
+ priority: 2,
332
339
  description: 'DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅',
333
340
  },
334
341
  {
@@ -338,6 +345,7 @@ function buildOpencodeGoPool() {
338
345
  maxConcurrent: 2,
339
346
  capabilities: ['vision', 'reasoning', 'complex-coding', 'architecture', 'debugging'],
340
347
  costTier: 'high',
348
+ priority: 1,
341
349
  description: 'Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론',
342
350
  },
343
351
  ];
@@ -405,7 +413,7 @@ export function formatProviderChecklist(detection) {
405
413
  lines.push('구독을 변경하려면 maskweaver.config.json의 dummyHumans.pool을 편집하세요.');
406
414
  return lines.join('\n');
407
415
  }
408
- export function writeAutoDetectedConfig(projectDir) {
416
+ export function writeAutoDetectedConfig(projectDir, force) {
409
417
  let detection;
410
418
  try {
411
419
  detection = detectSubscriptionsFromCli();
@@ -425,7 +433,7 @@ export function writeAutoDetectedConfig(projectDir) {
425
433
  return null;
426
434
  } })()
427
435
  : null;
428
- if (existingConfig?.dummyHumans?.pool?.length > 0) {
436
+ if (!force && existingConfig?.dummyHumans?.pool?.length > 0) {
429
437
  return null;
430
438
  }
431
439
  const newConfig = buildConfigFromDetection(detection);
@@ -447,6 +455,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
447
455
  maxConcurrent: 5,
448
456
  capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
449
457
  costTier: 'low',
458
+ priority: 1,
450
459
  description: 'DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업',
451
460
  },
452
461
  {
@@ -456,6 +465,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
456
465
  maxConcurrent: 3,
457
466
  capabilities: ['coding', 'testing', 'refactoring', 'backend'],
458
467
  costTier: 'medium',
468
+ priority: 2,
459
469
  description: 'DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드',
460
470
  },
461
471
  {
@@ -465,6 +475,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
465
475
  maxConcurrent: 3,
466
476
  capabilities: ['vision', 'frontend', 'testing'],
467
477
  costTier: 'medium',
478
+ priority: 1,
468
479
  description: 'Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트',
469
480
  },
470
481
  {
@@ -474,6 +485,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
474
485
  maxConcurrent: 2,
475
486
  capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
476
487
  costTier: 'high',
488
+ priority: 2,
477
489
  description: 'DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅',
478
490
  },
479
491
  {
@@ -483,6 +495,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
483
495
  maxConcurrent: 2,
484
496
  capabilities: ['vision', 'reasoning', 'complex-coding', 'architecture', 'debugging'],
485
497
  costTier: 'high',
498
+ priority: 1,
486
499
  description: 'Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론',
487
500
  },
488
501
  ],
@@ -187,6 +187,10 @@ export class ModelRegistry {
187
187
  return -1;
188
188
  if (!slotA.available && slotB.available)
189
189
  return 1;
190
+ const priA = a.priority ?? 0;
191
+ const priB = b.priority ?? 0;
192
+ if (priB !== priA)
193
+ return priB - priA;
190
194
  if (preferCheap) {
191
195
  const costDiff = COST_ORDER[a.costTier] - COST_ORDER[b.costTier];
192
196
  if (costDiff !== 0)
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.9.9";
1
+ export declare const VERSION = "0.10.1";
2
2
  export declare function getVersionString(): string;
package/dist/version.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = '0.9.9';
1
+ export const VERSION = '0.10.1';
2
2
  export function getVersionString() {
3
3
  return `Maskweaver v${VERSION}`;
4
4
  }
@@ -0,0 +1,87 @@
1
+ import type { ContextIndex } from './types.js';
2
+ export declare function getWikiDir(basePath: string): string;
3
+ export declare function getBuildDir(basePath: string, changeId: string, buildId: string): string;
4
+ export declare function getTasksDir(basePath: string, changeId: string, buildId: string): string;
5
+ export declare function getTaskDir(basePath: string, changeId: string, buildId: string, taskId: string): string;
6
+ export declare function getWavesDir(basePath: string, changeId: string, buildId: string): string;
7
+ export declare function getSnapshotsDir(basePath: string, changeId: string, buildId: string): string;
8
+ export declare function writeBrief(taskDir: string, data: {
9
+ taskId: string;
10
+ buildId: string;
11
+ wave: number;
12
+ dependsOn: string[];
13
+ allowedPaths: string[];
14
+ forbiddenPaths: string[];
15
+ contextPaths: string[];
16
+ acceptanceRefs: string[];
17
+ verifyCommands: string[];
18
+ goal: string;
19
+ requiredOutcome: string[];
20
+ criticalWarnings: string[];
21
+ }): Promise<string>;
22
+ export declare function writeContext(taskDir: string, data: {
23
+ taskId: string;
24
+ sourceHashes: Record<string, string>;
25
+ investigation: string;
26
+ constraints: string[];
27
+ reuseCandidates: string[];
28
+ knownRisks: string[];
29
+ }): Promise<string>;
30
+ export declare function writeResult(taskDir: string, data: {
31
+ taskId: string;
32
+ status: 'succeeded' | 'failed';
33
+ changedFiles: string[];
34
+ createdSymbols: string[];
35
+ errorSummary?: string;
36
+ downstreamExports: Array<{
37
+ kind: string;
38
+ path: string;
39
+ summary: string;
40
+ }>;
41
+ notes: string;
42
+ }): Promise<string>;
43
+ export declare function writeVerify(taskDir: string, data: {
44
+ taskId: string;
45
+ status: 'passed' | 'failed';
46
+ commands: Array<{
47
+ command: string;
48
+ status: string;
49
+ output?: string;
50
+ }>;
51
+ }): Promise<string>;
52
+ export declare function writeWavePlan(wavesDir: string, data: {
53
+ buildId: string;
54
+ waveIndex: number;
55
+ tasks: Array<{
56
+ taskId: string;
57
+ phaseId: string;
58
+ allowedPaths: string[];
59
+ dependsOn: string[];
60
+ }>;
61
+ parallelSafe: boolean;
62
+ }): Promise<string>;
63
+ export declare function updateWaveResults(wavesDir: string, waveIndex: number, results: {
64
+ tasks: Array<{
65
+ taskId: string;
66
+ status: string;
67
+ changedFiles: string[];
68
+ verification: string;
69
+ }>;
70
+ contextUpdates: string[];
71
+ }): Promise<void>;
72
+ export declare function ensureWikiDir(basePath: string): Promise<string>;
73
+ export declare function writeWikiPage(basePath: string, page: string, content: string): Promise<void>;
74
+ export declare function readWikiPage(basePath: string, page: string): Promise<string | null>;
75
+ export declare function appendChangesLog(basePath: string, entry: {
76
+ ts: string;
77
+ buildId: string;
78
+ wave: number;
79
+ taskId: string;
80
+ status: string;
81
+ changedFiles: string[];
82
+ exports: string[];
83
+ verify: string;
84
+ }): Promise<void>;
85
+ export declare function writeContextIndex(buildDir: string, index: ContextIndex): Promise<void>;
86
+ export declare function readContextIndex(buildDir: string): Promise<ContextIndex | null>;
87
+ export declare function snapshotWiki(basePath: string, snapshotDir: string): Promise<void>;