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,11 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Weave Tool for OpenCode Plugin
|
|
3
|
-
*
|
|
4
|
-
* Integrates Weave workflow into OpenCode as a tool.
|
|
5
|
-
* Commands: design, craft, status
|
|
6
|
-
*/
|
|
7
1
|
import { z } from 'zod';
|
|
8
|
-
// Inline shim: tool() is just an identity function in @opencode-ai/plugin
|
|
9
2
|
const tool = (input) => input;
|
|
10
3
|
import { createHash } from 'node:crypto';
|
|
11
4
|
import * as os from 'node:os';
|
|
@@ -39,9 +32,6 @@ import { acquireLoopOperatorLock, appendLoopEvent, createLoopRun, ensureLoopCont
|
|
|
39
32
|
import { getEffectiveGdcConfig, runGdcMachineCommand, countGdcCheckIssues, getStatsNodeSummary, } from '../../weave/gdc.js';
|
|
40
33
|
import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, } from '../../shared/generate-agents.js';
|
|
41
34
|
import { resolveCommand, loadCommandsJson } from './command-registry.js';
|
|
42
|
-
// ============================================================================
|
|
43
|
-
// Tool Factory
|
|
44
|
-
// ============================================================================
|
|
45
35
|
export function createWeaveTool() {
|
|
46
36
|
return {
|
|
47
37
|
description: (() => {
|
|
@@ -145,7 +135,6 @@ export function createWeaveTool() {
|
|
|
145
135
|
execute: async (args, context) => {
|
|
146
136
|
const { command } = args;
|
|
147
137
|
const basePath = context.worktree;
|
|
148
|
-
// Resolve command aliases and deprecation
|
|
149
138
|
const resolved = resolveCommand(command);
|
|
150
139
|
if ('error' in resolved) {
|
|
151
140
|
return `Error: ${resolved.error}`;
|
|
@@ -215,9 +204,6 @@ export function createWeaveTool() {
|
|
|
215
204
|
},
|
|
216
205
|
};
|
|
217
206
|
}
|
|
218
|
-
// ============================================================================
|
|
219
|
-
// Command Handlers
|
|
220
|
-
// ============================================================================
|
|
221
207
|
function toWorkspaceRelative(basePath, filePath) {
|
|
222
208
|
const rel = path.relative(basePath, filePath);
|
|
223
209
|
if (!rel || rel.startsWith('..'))
|
|
@@ -1094,7 +1080,6 @@ async function migrateLegacyPlanIfNeeded(basePath, activePlan) {
|
|
|
1094
1080
|
await unlink(legacyPlanPath);
|
|
1095
1081
|
}
|
|
1096
1082
|
catch {
|
|
1097
|
-
// Non-fatal. Keep migrated plan and continue.
|
|
1098
1083
|
}
|
|
1099
1084
|
return {
|
|
1100
1085
|
migrated: true,
|
|
@@ -1241,7 +1226,6 @@ async function handleInit(basePath) {
|
|
|
1241
1226
|
lines.push('');
|
|
1242
1227
|
lines.push(...gdcReport);
|
|
1243
1228
|
lines.push('');
|
|
1244
|
-
// Check global config
|
|
1245
1229
|
const globalConfigPath = path.join(os.homedir(), '.config', 'opencode', 'maskweaver.config.json');
|
|
1246
1230
|
if (!fs.existsSync(globalConfigPath)) {
|
|
1247
1231
|
lines.push('');
|
|
@@ -1389,7 +1373,6 @@ async function handleApprovePlan(args, basePath) {
|
|
|
1389
1373
|
}
|
|
1390
1374
|
}
|
|
1391
1375
|
catch {
|
|
1392
|
-
// Optional note file.
|
|
1393
1376
|
}
|
|
1394
1377
|
}
|
|
1395
1378
|
activePlan.planApproved = true;
|
|
@@ -1416,7 +1399,6 @@ async function handleDesign(args, basePath) {
|
|
|
1416
1399
|
if (!docsPath) {
|
|
1417
1400
|
return 'Error: docsPath is required for design command. Example: weave design docs/';
|
|
1418
1401
|
}
|
|
1419
|
-
// Step 1: Intake
|
|
1420
1402
|
const resolvedDocsPath = resolveUnderBase(basePath, docsPath);
|
|
1421
1403
|
const intakeResult = await intake({ docsPath: resolvedDocsPath });
|
|
1422
1404
|
const researchResult = await writeResearchReport({
|
|
@@ -1425,7 +1407,6 @@ async function handleDesign(args, basePath) {
|
|
|
1425
1407
|
basePath,
|
|
1426
1408
|
projectName: projectName || 'My Project',
|
|
1427
1409
|
});
|
|
1428
|
-
// Check if there are questions
|
|
1429
1410
|
if (intakeResult.questions.length > 0) {
|
|
1430
1411
|
const lines = [];
|
|
1431
1412
|
lines.push(researchResult.summary);
|
|
@@ -1449,7 +1430,6 @@ async function handleDesign(args, basePath) {
|
|
|
1449
1430
|
lines.push('(또는 기본값으로 진행하려면 "기본값으로 진행해"라고 해주세요)');
|
|
1450
1431
|
return lines.join('\n');
|
|
1451
1432
|
}
|
|
1452
|
-
// Step 2: Plan (if no questions or defaults accepted)
|
|
1453
1433
|
const planResult = await plan({
|
|
1454
1434
|
intake: intakeResult,
|
|
1455
1435
|
projectName: projectName || 'My Project',
|
|
@@ -1508,7 +1488,6 @@ async function handlePrepare(args, basePath) {
|
|
|
1508
1488
|
const intakeResult = await intake({ docsPath: resolvedDocsPath });
|
|
1509
1489
|
const gdcPrepareSync = await runGdcPrepareSync(basePath);
|
|
1510
1490
|
const normalizedPlanName = normalizePlanName(args.planName, projectName, resolvedDocsPath);
|
|
1511
|
-
// Cache-aware skip: skip steps if artifacts already exist
|
|
1512
1491
|
const researchPath = path.join(basePath, 'tasks', 'research.md');
|
|
1513
1492
|
const specsDir = path.join(basePath, '.opencode', 'weave', 'specs');
|
|
1514
1493
|
const plansDir = path.join(basePath, '.opencode', 'weave', 'plans');
|
|
@@ -1529,7 +1508,6 @@ async function handlePrepare(args, basePath) {
|
|
|
1529
1508
|
return false;
|
|
1530
1509
|
}
|
|
1531
1510
|
})();
|
|
1532
|
-
// Step 1: Research
|
|
1533
1511
|
const researchResult = hasResearch
|
|
1534
1512
|
? {
|
|
1535
1513
|
summary: `> ⏭️ Research skipped: \`${toWorkspaceRelative(basePath, researchPath)}\` already exists.`,
|
|
@@ -1541,7 +1519,6 @@ async function handlePrepare(args, basePath) {
|
|
|
1541
1519
|
basePath,
|
|
1542
1520
|
projectName: projectName || 'My Project',
|
|
1543
1521
|
});
|
|
1544
|
-
// Step 2: Spec (baseline)
|
|
1545
1522
|
const specResult = hasSpec
|
|
1546
1523
|
? { summary: `> ⏭️ Spec skipped: existing artifact found in \`${toWorkspaceRelative(basePath, specsDir)}\`.` }
|
|
1547
1524
|
: await createSpec({
|
|
@@ -1550,7 +1527,6 @@ async function handlePrepare(args, basePath) {
|
|
|
1550
1527
|
specName: normalizedPlanName,
|
|
1551
1528
|
basePath,
|
|
1552
1529
|
});
|
|
1553
|
-
// Step 3: Plan
|
|
1554
1530
|
const planResult = hasPlan
|
|
1555
1531
|
? { summary: `> ⏭️ Plan skipped: existing artifact found in \`${toWorkspaceRelative(basePath, plansDir)}\`.` }
|
|
1556
1532
|
: await plan({
|
|
@@ -1647,7 +1623,6 @@ async function handleFlow(args, basePath) {
|
|
|
1647
1623
|
if (!phaseBeforeCraft) {
|
|
1648
1624
|
return `Error: Phase not found: ${resolvedPhaseId}`;
|
|
1649
1625
|
}
|
|
1650
|
-
// Legacy plans may not have explicit tasks yet.
|
|
1651
1626
|
if (!phaseBeforeCraft.tasks || phaseBeforeCraft.tasks.length === 0) {
|
|
1652
1627
|
await manager.addTasks(resolvedPhaseId, generateDefaultPhaseTasks(phaseBeforeCraft));
|
|
1653
1628
|
}
|
|
@@ -1770,9 +1745,6 @@ async function handleFlow(args, basePath) {
|
|
|
1770
1745
|
});
|
|
1771
1746
|
return lines.join('\n');
|
|
1772
1747
|
}
|
|
1773
|
-
// ============================================================================
|
|
1774
|
-
// Handle Map — Codebase Analysis
|
|
1775
|
-
// ============================================================================
|
|
1776
1748
|
async function handleMap(args, basePath) {
|
|
1777
1749
|
const lines = [];
|
|
1778
1750
|
lines.push('## 🔍 Codebase Map');
|
|
@@ -1803,9 +1775,6 @@ async function handleMap(args, basePath) {
|
|
|
1803
1775
|
lines.push('Next: `weave command=interview docsPath="doc"` to discuss the plan.');
|
|
1804
1776
|
return lines.join('\n');
|
|
1805
1777
|
}
|
|
1806
|
-
// ============================================================================
|
|
1807
|
-
// Handle Interview — Multi-step Question Asking
|
|
1808
|
-
// ============================================================================
|
|
1809
1778
|
async function handleInterview(args, basePath) {
|
|
1810
1779
|
const docsPath = args.docsPath || 'docs';
|
|
1811
1780
|
const lines = [];
|
|
@@ -1858,9 +1827,6 @@ async function handleInterview(args, basePath) {
|
|
|
1858
1827
|
}
|
|
1859
1828
|
return lines.join('\n');
|
|
1860
1829
|
}
|
|
1861
|
-
// ============================================================================
|
|
1862
|
-
// Handle Build — Ralph-loop Autonomous Execution
|
|
1863
|
-
// ============================================================================
|
|
1864
1830
|
async function handleBuild(args, basePath) {
|
|
1865
1831
|
const lines = [];
|
|
1866
1832
|
lines.push('## 🏗️ Build');
|
|
@@ -1908,9 +1874,6 @@ async function handleBuild(args, basePath) {
|
|
|
1908
1874
|
}
|
|
1909
1875
|
return lines.join('\n');
|
|
1910
1876
|
}
|
|
1911
|
-
// ============================================================================
|
|
1912
|
-
// Handle Build Resume
|
|
1913
|
-
// ============================================================================
|
|
1914
1877
|
async function handleBuildResume(args, basePath) {
|
|
1915
1878
|
const lines = [];
|
|
1916
1879
|
lines.push('## 🔄 Build Resume');
|
|
@@ -1957,10 +1920,8 @@ async function handleCraft(args, basePath) {
|
|
|
1957
1920
|
return formatPlanApprovalRequired(basePath, activePlan);
|
|
1958
1921
|
}
|
|
1959
1922
|
if (!resolvedPhaseId) {
|
|
1960
|
-
// Get next phase
|
|
1961
1923
|
const manager = getPhaseManager(basePath);
|
|
1962
1924
|
await manager.loadPlan();
|
|
1963
|
-
// Show any recovery messages from auto-repair during load
|
|
1964
1925
|
const recoveryMsgs = manager.getRecoveryMessages();
|
|
1965
1926
|
recoveryPrefix = recoveryMsgs.length > 0
|
|
1966
1927
|
? `> **Auto-repair**: ${recoveryMsgs.join('; ')}\n\n`
|
|
@@ -1976,7 +1937,6 @@ async function handleCraft(args, basePath) {
|
|
|
1976
1937
|
resolvedPhaseId = nextPhase.id;
|
|
1977
1938
|
autoSelectedPhase = true;
|
|
1978
1939
|
}
|
|
1979
|
-
// Ensure tasks exist for legacy plans. (Old plans may have empty task arrays.)
|
|
1980
1940
|
{
|
|
1981
1941
|
const manager = getPhaseManager(basePath);
|
|
1982
1942
|
await manager.loadPlan();
|
|
@@ -1988,7 +1948,6 @@ async function handleCraft(args, basePath) {
|
|
|
1988
1948
|
await manager.addTasks(resolvedPhaseId, generateDefaultPhaseTasks(current));
|
|
1989
1949
|
}
|
|
1990
1950
|
}
|
|
1991
|
-
// Prepare execution plan (validates, marks in_progress, generates plan)
|
|
1992
1951
|
const events = [];
|
|
1993
1952
|
const { plan: executionPlan } = await preparePhaseExecution({
|
|
1994
1953
|
phaseId: resolvedPhaseId,
|
|
@@ -1996,7 +1955,6 @@ async function handleCraft(args, basePath) {
|
|
|
1996
1955
|
onEvent: (event) => events.push(event),
|
|
1997
1956
|
basePath,
|
|
1998
1957
|
});
|
|
1999
|
-
// Format the execution plan as markdown for the Mask Weaver
|
|
2000
1958
|
const planMarkdown = formatExecutionPlan(executionPlan);
|
|
2001
1959
|
const manager = getPhaseManager(basePath);
|
|
2002
1960
|
await manager.loadPlan();
|
|
@@ -2086,14 +2044,11 @@ async function handleStatus(basePath) {
|
|
|
2086
2044
|
const manager = getPhaseManager(basePath);
|
|
2087
2045
|
const activePlan = await manager.loadPlan();
|
|
2088
2046
|
const report = await generateStatusReport(basePath);
|
|
2089
|
-
// Show any recovery messages from auto-repair
|
|
2090
2047
|
const recoveryMsgs = manager.getRecoveryMessages();
|
|
2091
|
-
// Add global knowledge stats
|
|
2092
2048
|
const knowledge = new GlobalKnowledge();
|
|
2093
2049
|
await knowledge.init();
|
|
2094
2050
|
const stats = await knowledge.getStats();
|
|
2095
2051
|
const lines = [];
|
|
2096
|
-
// Show recovery warnings at the top
|
|
2097
2052
|
if (recoveryMsgs.length > 0) {
|
|
2098
2053
|
lines.push('### YAML Auto-Repair Report\n');
|
|
2099
2054
|
for (const msg of recoveryMsgs) {
|
|
@@ -2247,7 +2202,6 @@ async function handleVerify(args, basePath) {
|
|
|
2247
2202
|
return verification.report;
|
|
2248
2203
|
}
|
|
2249
2204
|
async function handleTroubleshoot(args) {
|
|
2250
|
-
// Unified: record mode (absorbs old 'record' command)
|
|
2251
2205
|
if (args.record) {
|
|
2252
2206
|
if (!args.error || !args.solution) {
|
|
2253
2207
|
return 'Error: error and solution are required when record=true. Example: weave command=troubleshoot record=true error="..." solution="..."';
|
|
@@ -2294,17 +2248,6 @@ async function handleRepair(basePath) {
|
|
|
2294
2248
|
const { results, summary } = await manager.repairPlans();
|
|
2295
2249
|
return summary;
|
|
2296
2250
|
}
|
|
2297
|
-
/**
|
|
2298
|
-
* Handle `sync-agents` command.
|
|
2299
|
-
*
|
|
2300
|
-
* Reads maskweaver.config.json (project or global ~/.config/opencode/)
|
|
2301
|
-
* and force-overwrites all dummy-human agent .md files in .opencode/agents/.
|
|
2302
|
-
*
|
|
2303
|
-
* Search order:
|
|
2304
|
-
* 1. {projectDir}/maskweaver.config.json
|
|
2305
|
-
* 2. {projectDir}/.opencode/maskweaver.config.json
|
|
2306
|
-
* 3. ~/.config/opencode/maskweaver.config.json (user global)
|
|
2307
|
-
*/
|
|
2308
2251
|
async function handleSyncAgents(basePath) {
|
|
2309
2252
|
const agentsDir = path.join(basePath, '.opencode', 'agents');
|
|
2310
2253
|
const result = generatePoolAgentFilesFromConfig(basePath, agentsDir, { force: true });
|
|
@@ -2344,18 +2287,10 @@ async function handleSyncAgents(basePath) {
|
|
|
2344
2287
|
}
|
|
2345
2288
|
return lines.join('\n');
|
|
2346
2289
|
}
|
|
2347
|
-
/**
|
|
2348
|
-
* Handle `init-config` command.
|
|
2349
|
-
*
|
|
2350
|
-
* Creates default maskweaver.config.json (runtime config with pool template)
|
|
2351
|
-
* and .opencode/maskweaver.json (plugin config) if they don't exist.
|
|
2352
|
-
* Does NOT overwrite existing files.
|
|
2353
|
-
*/
|
|
2354
2290
|
async function handleInitConfig(basePath) {
|
|
2355
2291
|
const lines = [];
|
|
2356
2292
|
lines.push('## 📝 Config Initialization');
|
|
2357
2293
|
lines.push('');
|
|
2358
|
-
// Create runtime config (maskweaver.config.json)
|
|
2359
2294
|
const runtimePath = writeDefaultRuntimeConfig(basePath);
|
|
2360
2295
|
if (runtimePath) {
|
|
2361
2296
|
lines.push(`✅ Created runtime config: ${toWorkspaceRelative(basePath, runtimePath)}`);
|
|
@@ -2366,7 +2301,6 @@ async function handleInitConfig(basePath) {
|
|
|
2366
2301
|
lines.push('⏭️ maskweaver.config.json already exists (skipped)');
|
|
2367
2302
|
}
|
|
2368
2303
|
lines.push('');
|
|
2369
|
-
// Create plugin config (.opencode/maskweaver.json)
|
|
2370
2304
|
const pluginPath = writeDefaultPluginConfig(basePath);
|
|
2371
2305
|
if (pluginPath) {
|
|
2372
2306
|
lines.push(`✅ Created plugin config: ${toWorkspaceRelative(basePath, pluginPath)}`);
|
|
@@ -2379,9 +2313,6 @@ async function handleInitConfig(basePath) {
|
|
|
2379
2313
|
lines.push('> with your model pool, then run `weave sync-agents` in any project to apply it.');
|
|
2380
2314
|
return lines.join('\n');
|
|
2381
2315
|
}
|
|
2382
|
-
// ============================================================================
|
|
2383
|
-
// Unified Build Handler (absorbs build, build-resume, loop-*)
|
|
2384
|
-
// ============================================================================
|
|
2385
2316
|
async function handleBuildUnified(args, basePath) {
|
|
2386
2317
|
const action = args.action || 'run';
|
|
2387
2318
|
switch (action) {
|
|
@@ -2413,9 +2344,6 @@ async function handleBuildUnified(args, basePath) {
|
|
|
2413
2344
|
return `Error: Unknown build action: ${action}. Available: run, status, stop, list, resume, sync.`;
|
|
2414
2345
|
}
|
|
2415
2346
|
}
|
|
2416
|
-
// ============================================================================
|
|
2417
|
-
// Agents Handler (absorbs sync-agents, init-config)
|
|
2418
|
-
// ============================================================================
|
|
2419
2347
|
async function handleAgents(args, basePath) {
|
|
2420
2348
|
if (!args.sync && !args.init) {
|
|
2421
2349
|
return 'Error: agents requires an action. Use `sync=true` to regenerate agent files, or `init=true` to create default config.';
|
|
@@ -3065,7 +2993,6 @@ async function handleApprove(args, basePath) {
|
|
|
3065
2993
|
`Finalization blocked: verification failed for ${resolvedPhaseId}.`,
|
|
3066
2994
|
]);
|
|
3067
2995
|
}
|
|
3068
|
-
// If no commands detected, allow finalization but make it explicit.
|
|
3069
2996
|
if (verification.results.length === 0) {
|
|
3070
2997
|
await phaseManager.markAllTasksPassed(resolvedPhaseId);
|
|
3071
2998
|
const result = await handleUserResponse(resolvedPhaseId, 'approve', undefined, basePath);
|
|
@@ -3082,7 +3009,6 @@ async function handleApprove(args, basePath) {
|
|
|
3082
3009
|
shardSwitch ? 'Advanced to next shard.' : '',
|
|
3083
3010
|
].filter(Boolean));
|
|
3084
3011
|
}
|
|
3085
|
-
// Optional: commit during finalization
|
|
3086
3012
|
if (commit) {
|
|
3087
3013
|
try {
|
|
3088
3014
|
await ensureGitRepo(basePath);
|
|
@@ -3121,7 +3047,6 @@ async function handleApprove(args, basePath) {
|
|
|
3121
3047
|
const secretWarning = findings.length > 0
|
|
3122
3048
|
? formatSecretScanReport(findings)
|
|
3123
3049
|
: null;
|
|
3124
|
-
// Commit message fallback: Pn: Phase Name
|
|
3125
3050
|
const phase = phaseManager.getPhase(resolvedPhaseId);
|
|
3126
3051
|
const defaultMsg = phase ? `${phase.id}: ${phase.name}` : `${resolvedPhaseId}: complete`;
|
|
3127
3052
|
const msg = (commitMessage && commitMessage.trim().length > 0)
|
|
@@ -3157,7 +3082,6 @@ async function handleApprove(args, basePath) {
|
|
|
3157
3082
|
]);
|
|
3158
3083
|
}
|
|
3159
3084
|
}
|
|
3160
|
-
// Passed with results: include report in approval output.
|
|
3161
3085
|
{
|
|
3162
3086
|
await phaseManager.markAllTasksPassed(resolvedPhaseId);
|
|
3163
3087
|
}
|
|
@@ -3320,7 +3244,6 @@ async function syncWorkflowArtifacts(basePath, manager, options) {
|
|
|
3320
3244
|
await writeFile(todoPath, `${lines.join('\n')}\n`, 'utf-8');
|
|
3321
3245
|
}
|
|
3322
3246
|
catch {
|
|
3323
|
-
// Non-fatal: artifact sync should never break workflow execution.
|
|
3324
3247
|
}
|
|
3325
3248
|
}
|
|
3326
3249
|
function sanitizeLessonText(input, maxLength = 240) {
|
|
@@ -3363,7 +3286,6 @@ async function appendWorkflowLesson(basePath, lesson) {
|
|
|
3363
3286
|
await writeFile(lessonsPath, `${current.trimEnd()}\n\n${entry}`, 'utf-8');
|
|
3364
3287
|
}
|
|
3365
3288
|
catch {
|
|
3366
|
-
// Non-fatal: lesson capture should not block workflow execution.
|
|
3367
3289
|
}
|
|
3368
3290
|
}
|
|
3369
3291
|
function resolveUnderBase(basePath, inputPath) {
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -1,32 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin Types
|
|
3
|
-
*
|
|
4
|
-
* Shared types for Maskweaver plugin tools
|
|
5
|
-
*
|
|
6
|
-
* Based on @opencode-ai/plugin tool definitions.
|
|
7
|
-
*/
|
|
8
1
|
import type { z } from 'zod';
|
|
9
|
-
/**
|
|
10
|
-
* Minimal context required by Maskweaver tool factories.
|
|
11
|
-
* SDK provides richer context, but factories only need worktree.
|
|
12
|
-
*/
|
|
13
2
|
export interface ToolContext {
|
|
14
3
|
worktree: string;
|
|
15
4
|
}
|
|
16
|
-
/**
|
|
17
|
-
* Tool factory interface for creating OpenCode tools
|
|
18
|
-
*/
|
|
19
5
|
export interface ToolFactory {
|
|
20
|
-
/** Tool description shown to LLM */
|
|
21
6
|
description: string;
|
|
22
|
-
/** Zod schema for argument validation */
|
|
23
7
|
args: z.ZodType<any>;
|
|
24
|
-
/** Execute function that returns string result */
|
|
25
8
|
execute: (args: any, context: ToolContext) => Promise<string>;
|
|
26
9
|
}
|
|
27
|
-
/**
|
|
28
|
-
* Standard tool response format
|
|
29
|
-
*/
|
|
30
10
|
export interface ToolResponse<T = unknown> {
|
|
31
11
|
success: boolean;
|
|
32
12
|
data?: T;
|
package/dist/plugin/types.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Retrospect Package
|
|
3
|
-
*
|
|
4
|
-
* 회고 및 가면 관리 시스템
|
|
5
|
-
*
|
|
6
|
-
* "Export only what matters" - Kent Beck
|
|
7
|
-
*/
|
|
8
1
|
export type { RetrospectTrigger, RetrospectDepth, MaskUsageRecord, RetrospectInput, RetrospectResult, } from './types.js';
|
|
9
2
|
export type { RetrospectStrategy } from './strategies/base.js';
|
|
10
3
|
export { selectStrategy, QuickRetrospectStrategy, StandardRetrospectStrategy, DeepRetrospectStrategy, } from './strategies/index.js';
|
package/dist/retrospect/index.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Retrospect Package
|
|
3
|
-
*
|
|
4
|
-
* 회고 및 가면 관리 시스템
|
|
5
|
-
*
|
|
6
|
-
* "Export only what matters" - Kent Beck
|
|
7
|
-
*/
|
|
8
1
|
export { selectStrategy, QuickRetrospectStrategy, StandardRetrospectStrategy, DeepRetrospectStrategy, } from './strategies/index.js';
|
|
9
|
-
// Core functions
|
|
10
2
|
export { performRetrospect, getMemoryPath, getDbPath } from './retrospect.js';
|
|
11
|
-
// Mask save
|
|
12
3
|
export { saveMask } from './mask-save.js';
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mask Save Logic
|
|
3
|
-
*
|
|
4
|
-
* 효과적인 가면을 MASKS.md에 저장
|
|
5
|
-
*
|
|
6
|
-
* "Clean code reads like well-written prose" - Kent Beck
|
|
7
|
-
*/
|
|
8
1
|
interface MaskSaveInput {
|
|
9
2
|
name: string;
|
|
10
3
|
expertise: string;
|
|
@@ -21,10 +14,5 @@ interface MaskSaveResult {
|
|
|
21
14
|
effectivenessScore?: number;
|
|
22
15
|
message: string;
|
|
23
16
|
}
|
|
24
|
-
/**
|
|
25
|
-
* 가면 저장
|
|
26
|
-
*
|
|
27
|
-
* "Make each function tell a story" - Kent Beck
|
|
28
|
-
*/
|
|
29
17
|
export declare function saveMask(basePath: string, input: MaskSaveInput): MaskSaveResult;
|
|
30
18
|
export type { MaskSaveInput, MaskSaveResult };
|
|
@@ -1,21 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mask Save Logic
|
|
3
|
-
*
|
|
4
|
-
* 효과적인 가면을 MASKS.md에 저장
|
|
5
|
-
*
|
|
6
|
-
* "Clean code reads like well-written prose" - Kent Beck
|
|
7
|
-
*/
|
|
8
1
|
import { join } from 'path';
|
|
9
2
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
10
3
|
import { getMemoryPath } from './retrospect.js';
|
|
11
|
-
// ============================================================================
|
|
12
|
-
// Constants
|
|
13
|
-
// ============================================================================
|
|
14
4
|
const EFFECTIVENESS_NEW_SCORE_WEIGHT = 0.3;
|
|
15
5
|
const CUSTOM_SECTION_HEADER = '## 커스텀 가면';
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// Date Formatting
|
|
18
|
-
// ============================================================================
|
|
19
6
|
function formatTimestamp() {
|
|
20
7
|
const now = new Date();
|
|
21
8
|
const year = now.getFullYear();
|
|
@@ -25,36 +12,19 @@ function formatTimestamp() {
|
|
|
25
12
|
const minute = String(now.getMinutes()).padStart(2, '0');
|
|
26
13
|
return `${year}-${month}-${day} ${hour}:${minute}`;
|
|
27
14
|
}
|
|
28
|
-
// ============================================================================
|
|
29
|
-
// Effectiveness Score Calculation
|
|
30
|
-
// ============================================================================
|
|
31
|
-
/**
|
|
32
|
-
* 이동 평균으로 효과성 점수 계산
|
|
33
|
-
*
|
|
34
|
-
* "The simplest thing that could possibly work" - Kent Beck
|
|
35
|
-
*/
|
|
36
15
|
function calculateMovingAverageScore(currentScore, newScore, weight = EFFECTIVENESS_NEW_SCORE_WEIGHT) {
|
|
37
16
|
if (currentScore === 0) {
|
|
38
17
|
return newScore;
|
|
39
18
|
}
|
|
40
19
|
const updatedScore = currentScore * (1 - weight) + newScore * weight;
|
|
41
|
-
return Math.round(updatedScore * 10) / 10;
|
|
20
|
+
return Math.round(updatedScore * 10) / 10;
|
|
42
21
|
}
|
|
43
|
-
// ============================================================================
|
|
44
|
-
// Markdown Parsing
|
|
45
|
-
// ============================================================================
|
|
46
|
-
/**
|
|
47
|
-
* 이름을 비교 가능한 형태로 정규화
|
|
48
|
-
*/
|
|
49
22
|
function normalizeNameForComparison(name) {
|
|
50
23
|
return name
|
|
51
24
|
.toLowerCase()
|
|
52
25
|
.replace(/\s+/g, '')
|
|
53
26
|
.replace(/[()]/g, '');
|
|
54
27
|
}
|
|
55
|
-
/**
|
|
56
|
-
* MASKS.md에서 특정 가면 섹션을 찾습니다.
|
|
57
|
-
*/
|
|
58
28
|
function findMaskSection(content, maskName) {
|
|
59
29
|
const lines = content.split('\n');
|
|
60
30
|
const normalizedTarget = normalizeNameForComparison(maskName);
|
|
@@ -63,23 +33,19 @@ function findMaskSection(content, maskName) {
|
|
|
63
33
|
let currentScore = 0;
|
|
64
34
|
for (let i = 0; i < lines.length; i++) {
|
|
65
35
|
const line = lines[i];
|
|
66
|
-
// ### 가면명 형식 감지
|
|
67
36
|
if (line.startsWith('### ')) {
|
|
68
|
-
// 이전 가면 섹션 종료 체크
|
|
69
37
|
if (currentMaskStart !== -1) {
|
|
70
38
|
const normalizedCurrent = normalizeNameForComparison(currentMaskName);
|
|
71
39
|
if (normalizedCurrent === normalizedTarget) {
|
|
72
40
|
return { start: currentMaskStart, end: i - 1, score: currentScore };
|
|
73
41
|
}
|
|
74
42
|
}
|
|
75
|
-
// 새 가면 섹션 시작
|
|
76
43
|
currentMaskStart = i;
|
|
77
44
|
const withoutPrefix = line.replace(/^###\s*/, '');
|
|
78
45
|
const nameMatch = withoutPrefix.match(/^([^(]+)/);
|
|
79
46
|
currentMaskName = nameMatch ? nameMatch[1].trim() : withoutPrefix.trim();
|
|
80
47
|
currentScore = 0;
|
|
81
48
|
}
|
|
82
|
-
// 효과성 점수 추출
|
|
83
49
|
if (currentMaskStart !== -1 && line.includes('**효과성 점수**')) {
|
|
84
50
|
const colonIndex = line.indexOf(':');
|
|
85
51
|
if (colonIndex !== -1) {
|
|
@@ -88,7 +54,6 @@ function findMaskSection(content, maskName) {
|
|
|
88
54
|
}
|
|
89
55
|
}
|
|
90
56
|
}
|
|
91
|
-
// 마지막 가면 체크
|
|
92
57
|
if (currentMaskStart !== -1) {
|
|
93
58
|
const normalizedCurrent = normalizeNameForComparison(currentMaskName);
|
|
94
59
|
if (normalizedCurrent === normalizedTarget) {
|
|
@@ -97,12 +62,6 @@ function findMaskSection(content, maskName) {
|
|
|
97
62
|
}
|
|
98
63
|
return null;
|
|
99
64
|
}
|
|
100
|
-
// ============================================================================
|
|
101
|
-
// Markdown Generation
|
|
102
|
-
// ============================================================================
|
|
103
|
-
/**
|
|
104
|
-
* 새 가면 섹션 마크다운 생성
|
|
105
|
-
*/
|
|
106
65
|
function generateNewMaskSection(input) {
|
|
107
66
|
const timestamp = formatTimestamp();
|
|
108
67
|
const usageRecord = input.usageNote
|
|
@@ -118,29 +77,22 @@ function generateNewMaskSection(input) {
|
|
|
118
77
|
${usageRecord}
|
|
119
78
|
`;
|
|
120
79
|
}
|
|
121
|
-
/**
|
|
122
|
-
* 기존 가면 섹션 업데이트
|
|
123
|
-
*/
|
|
124
80
|
function updateExistingMask(content, section, newScore, usageNote) {
|
|
125
81
|
const lines = content.split('\n');
|
|
126
82
|
const timestamp = formatTimestamp();
|
|
127
83
|
const newUsageRecord = usageNote
|
|
128
84
|
? ` - ${timestamp} (점수: ${newScore}) - ${usageNote}`
|
|
129
85
|
: ` - ${timestamp} (점수: ${newScore})`;
|
|
130
|
-
// 효과성 점수 업데이트
|
|
131
86
|
const updatedScore = calculateMovingAverageScore(section.score, newScore);
|
|
132
87
|
const sectionLines = lines.slice(section.start, section.end + 1);
|
|
133
88
|
const result = [];
|
|
134
89
|
let usageRecordInserted = false;
|
|
135
90
|
for (const line of sectionLines) {
|
|
136
|
-
// 효과성 점수 라인 업데이트
|
|
137
91
|
if (line.includes('**효과성 점수**')) {
|
|
138
92
|
result.push(`- **효과성 점수**: ${updatedScore}`);
|
|
139
93
|
}
|
|
140
|
-
// 사용 기록 라인 찾기
|
|
141
94
|
else if (line.includes('**사용 기록**')) {
|
|
142
95
|
result.push(line);
|
|
143
|
-
// 바로 다음에 새 기록 추가
|
|
144
96
|
result.push(newUsageRecord);
|
|
145
97
|
usageRecordInserted = true;
|
|
146
98
|
}
|
|
@@ -148,43 +100,28 @@ function updateExistingMask(content, section, newScore, usageNote) {
|
|
|
148
100
|
result.push(line);
|
|
149
101
|
}
|
|
150
102
|
}
|
|
151
|
-
// 사용 기록 섹션이 없으면 마지막에 추가
|
|
152
103
|
if (!usageRecordInserted) {
|
|
153
104
|
result.push(`- **사용 기록**: `);
|
|
154
105
|
result.push(newUsageRecord);
|
|
155
106
|
}
|
|
156
|
-
// 전체 파일 재구성
|
|
157
107
|
const before = lines.slice(0, section.start);
|
|
158
108
|
const after = lines.slice(section.end + 1);
|
|
159
109
|
return [...before, ...result, ...after].join('\n');
|
|
160
110
|
}
|
|
161
|
-
/**
|
|
162
|
-
* 새 가면 추가
|
|
163
|
-
*/
|
|
164
111
|
function addNewMask(content, input) {
|
|
165
112
|
const newSection = generateNewMaskSection(input);
|
|
166
|
-
// 커스텀 가면 섹션 찾기
|
|
167
113
|
const customSectionIndex = content.indexOf(CUSTOM_SECTION_HEADER);
|
|
168
114
|
if (customSectionIndex !== -1) {
|
|
169
|
-
// 커스텀 섹션 바로 다음에 추가
|
|
170
115
|
const insertPosition = customSectionIndex + CUSTOM_SECTION_HEADER.length;
|
|
171
116
|
const afterHeader = content.slice(insertPosition);
|
|
172
117
|
const beforeHeader = content.slice(0, insertPosition);
|
|
173
118
|
return `${beforeHeader}\n\n${newSection}${afterHeader}`;
|
|
174
119
|
}
|
|
175
|
-
// 커스텀 섹션이 없으면 파일 끝에 추가
|
|
176
120
|
return `${content}\n${CUSTOM_SECTION_HEADER}\n\n${newSection}`;
|
|
177
121
|
}
|
|
178
|
-
// ============================================================================
|
|
179
|
-
// File Operations
|
|
180
|
-
// ============================================================================
|
|
181
|
-
/**
|
|
182
|
-
* MASKS.md 파일 읽기
|
|
183
|
-
*/
|
|
184
122
|
function readMasksFile(basePath) {
|
|
185
123
|
const masksPath = getMemoryPath('masks', basePath);
|
|
186
124
|
if (!existsSync(masksPath)) {
|
|
187
|
-
// 기본 템플릿 반환
|
|
188
125
|
return `# 가면 라이브러리 (Mask Library)
|
|
189
126
|
|
|
190
127
|
이 파일은 가면술사가 사용하는 가면들의 정의와 효과성을 기록합니다.
|
|
@@ -202,9 +139,6 @@ ${CUSTOM_SECTION_HEADER}
|
|
|
202
139
|
}
|
|
203
140
|
return readFileSync(masksPath, 'utf-8');
|
|
204
141
|
}
|
|
205
|
-
/**
|
|
206
|
-
* MASKS.md 파일 쓰기
|
|
207
|
-
*/
|
|
208
142
|
function writeMasksFile(basePath, content) {
|
|
209
143
|
const masksPath = getMemoryPath('masks', basePath);
|
|
210
144
|
const dir = join(basePath, '.opencode', 'memory');
|
|
@@ -213,32 +147,19 @@ function writeMasksFile(basePath, content) {
|
|
|
213
147
|
}
|
|
214
148
|
writeFileSync(masksPath, content, 'utf-8');
|
|
215
149
|
}
|
|
216
|
-
// ============================================================================
|
|
217
|
-
// Main Function
|
|
218
|
-
// ============================================================================
|
|
219
|
-
/**
|
|
220
|
-
* 가면 저장
|
|
221
|
-
*
|
|
222
|
-
* "Make each function tell a story" - Kent Beck
|
|
223
|
-
*/
|
|
224
150
|
export function saveMask(basePath, input) {
|
|
225
151
|
try {
|
|
226
|
-
// 1. MASKS.md 읽기
|
|
227
152
|
let content = readMasksFile(basePath);
|
|
228
|
-
// 2. 해당 가면이 있는지 확인
|
|
229
153
|
const existingSection = findMaskSection(content, input.name);
|
|
230
154
|
let action;
|
|
231
155
|
if (existingSection) {
|
|
232
|
-
// 3a. 기존 가면 업데이트
|
|
233
156
|
content = updateExistingMask(content, existingSection, input.effectivenessScore, input.usageNote);
|
|
234
157
|
action = 'updated';
|
|
235
158
|
}
|
|
236
159
|
else {
|
|
237
|
-
// 3b. 새 가면 추가
|
|
238
160
|
content = addNewMask(content, input);
|
|
239
161
|
action = 'created';
|
|
240
162
|
}
|
|
241
|
-
// 4. 파일 저장
|
|
242
163
|
writeMasksFile(basePath, content);
|
|
243
164
|
return {
|
|
244
165
|
success: true,
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Retrospect Core
|
|
3
|
-
*
|
|
4
|
-
* 회고 시스템의 메인 로직
|
|
5
|
-
*
|
|
6
|
-
* "Each function has one clear purpose" - Kent Beck
|
|
7
|
-
*/
|
|
8
1
|
import type { RetrospectInput, RetrospectResult } from './types.js';
|
|
9
|
-
/**
|
|
10
|
-
* 메모리 경로 반환
|
|
11
|
-
*/
|
|
12
2
|
declare function getMemoryPath(type: string, basePath: string): string;
|
|
13
|
-
/**
|
|
14
|
-
* DB 경로 반환
|
|
15
|
-
*/
|
|
16
3
|
declare function getDbPath(basePath: string): string;
|
|
17
|
-
/**
|
|
18
|
-
* 회고 수행
|
|
19
|
-
*
|
|
20
|
-
* "Make it work, make it right, make it fast" - Kent Beck
|
|
21
|
-
*/
|
|
22
4
|
export declare function performRetrospect(basePath: string, input: RetrospectInput): RetrospectResult;
|
|
23
5
|
export { getMemoryPath, getDbPath };
|