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.
Files changed (229) hide show
  1. package/README.ko.md +638 -592
  2. package/README.md +671 -667
  3. package/dist/cli/doctor.js +5 -21
  4. package/dist/cli/install.d.ts +0 -8
  5. package/dist/cli/install.js +0 -39
  6. package/dist/context/config.d.ts +0 -22
  7. package/dist/context/config.js +0 -28
  8. package/dist/context/feature.d.ts +0 -39
  9. package/dist/context/feature.js +0 -77
  10. package/dist/context/files.d.ts +0 -13
  11. package/dist/context/files.js +1 -24
  12. package/dist/context/index.d.ts +0 -7
  13. package/dist/context/index.js +0 -12
  14. package/dist/context/project.d.ts +0 -21
  15. package/dist/context/project.js +0 -30
  16. package/dist/context/types.d.ts +0 -48
  17. package/dist/context/types.js +0 -12
  18. package/dist/context/utils.d.ts +0 -18
  19. package/dist/context/utils.js +0 -27
  20. package/dist/core/engine/promptBuilder.d.ts +0 -17
  21. package/dist/core/engine/promptBuilder.js +0 -28
  22. package/dist/core/index.d.ts +0 -6
  23. package/dist/core/index.js +0 -9
  24. package/dist/core/loader/MaskLoader.d.ts +0 -23
  25. package/dist/core/loader/MaskLoader.js +0 -29
  26. package/dist/core/schema/types.d.ts +0 -47
  27. package/dist/core/schema/types.js +0 -6
  28. package/dist/core/schema/validator.d.ts +0 -14
  29. package/dist/core/schema/validator.js +0 -18
  30. package/dist/i18n/index.d.ts +0 -18
  31. package/dist/i18n/index.js +4 -23
  32. package/dist/index.d.ts +0 -8
  33. package/dist/index.js +0 -8
  34. package/dist/lib.d.ts +0 -5
  35. package/dist/lib.js +0 -12
  36. package/dist/memory/chunking.d.ts +0 -22
  37. package/dist/memory/chunking.js +2 -37
  38. package/dist/memory/core.d.ts +0 -29
  39. package/dist/memory/core.js +1 -52
  40. package/dist/memory/index.d.ts +0 -5
  41. package/dist/memory/index.js +0 -10
  42. package/dist/memory/indexer.d.ts +0 -21
  43. package/dist/memory/indexer.js +0 -44
  44. package/dist/memory/providers/examples.d.ts +0 -5
  45. package/dist/memory/providers/examples.js +4 -64
  46. package/dist/memory/providers/factory.d.ts +0 -44
  47. package/dist/memory/providers/factory.js +0 -46
  48. package/dist/memory/providers/index.d.ts +0 -26
  49. package/dist/memory/providers/index.js +0 -28
  50. package/dist/memory/providers/ollama.d.ts +0 -6
  51. package/dist/memory/providers/ollama.js +1 -8
  52. package/dist/memory/providers/openai.d.ts +0 -6
  53. package/dist/memory/providers/openai.js +1 -8
  54. package/dist/memory/providers/openrouter.d.ts +0 -6
  55. package/dist/memory/providers/openrouter.js +0 -8
  56. package/dist/memory/providers/text-only.d.ts +0 -13
  57. package/dist/memory/providers/text-only.js +0 -17
  58. package/dist/memory/providers/types.d.ts +0 -39
  59. package/dist/memory/providers/types.js +0 -7
  60. package/dist/memory/providers/voyage.d.ts +0 -22
  61. package/dist/memory/providers/voyage.js +1 -24
  62. package/dist/memory/search/hybrid.d.ts +0 -12
  63. package/dist/memory/search/hybrid.js +1 -22
  64. package/dist/memory/store/sqlite.d.ts +0 -72
  65. package/dist/memory/store/sqlite.js +4 -127
  66. package/dist/plugin/config/index.d.ts +0 -112
  67. package/dist/plugin/config/index.js +0 -115
  68. package/dist/plugin/index.d.ts +0 -13
  69. package/dist/plugin/index.js +1 -123
  70. package/dist/plugin/tools/command-registry.d.ts +0 -6
  71. package/dist/plugin/tools/command-registry.js +0 -14
  72. package/dist/plugin/tools/context.d.ts +0 -12
  73. package/dist/plugin/tools/context.js +0 -58
  74. package/dist/plugin/tools/maskSave.d.ts +0 -3
  75. package/dist/plugin/tools/maskSave.js +0 -3
  76. package/dist/plugin/tools/memoryGet.d.ts +0 -3
  77. package/dist/plugin/tools/memoryGet.js +0 -3
  78. package/dist/plugin/tools/memoryIndexer.d.ts +0 -3
  79. package/dist/plugin/tools/memoryIndexer.js +0 -10
  80. package/dist/plugin/tools/memorySearch.d.ts +0 -31
  81. package/dist/plugin/tools/memorySearch.js +0 -79
  82. package/dist/plugin/tools/memoryWrite.d.ts +0 -8
  83. package/dist/plugin/tools/memoryWrite.js +0 -32
  84. package/dist/plugin/tools/retrospect.d.ts +0 -3
  85. package/dist/plugin/tools/retrospect.js +0 -3
  86. package/dist/plugin/tools/slashcommand.d.ts +0 -11
  87. package/dist/plugin/tools/slashcommand.js +0 -38
  88. package/dist/plugin/tools/squad.d.ts +0 -12
  89. package/dist/plugin/tools/squad.js +11 -83
  90. package/dist/plugin/tools/weave.d.ts +0 -6
  91. package/dist/plugin/tools/weave.js +0 -78
  92. package/dist/plugin/types.d.ts +0 -20
  93. package/dist/plugin/types.js +0 -7
  94. package/dist/retrospect/index.d.ts +0 -7
  95. package/dist/retrospect/index.js +0 -9
  96. package/dist/retrospect/mask-save.d.ts +0 -12
  97. package/dist/retrospect/mask-save.js +1 -80
  98. package/dist/retrospect/retrospect.d.ts +0 -18
  99. package/dist/retrospect/retrospect.js +0 -63
  100. package/dist/retrospect/strategies/base.d.ts +0 -15
  101. package/dist/retrospect/strategies/base.js +0 -7
  102. package/dist/retrospect/strategies/deep.d.ts +0 -12
  103. package/dist/retrospect/strategies/deep.js +0 -24
  104. package/dist/retrospect/strategies/index.d.ts +0 -12
  105. package/dist/retrospect/strategies/index.js +0 -12
  106. package/dist/retrospect/strategies/quick.d.ts +0 -12
  107. package/dist/retrospect/strategies/quick.js +0 -19
  108. package/dist/retrospect/strategies/standard.d.ts +0 -12
  109. package/dist/retrospect/strategies/standard.js +0 -15
  110. package/dist/retrospect/types.d.ts +0 -7
  111. package/dist/retrospect/types.js +0 -7
  112. package/dist/shared/config.d.ts +0 -105
  113. package/dist/shared/config.js +0 -33
  114. package/dist/shared/errors.d.ts +0 -18
  115. package/dist/shared/errors.js +0 -19
  116. package/dist/shared/generate-agents.d.ts +0 -69
  117. package/dist/shared/generate-agents.js +2 -86
  118. package/dist/shared/image.d.ts +0 -67
  119. package/dist/shared/image.js +6 -104
  120. package/dist/shared/index.d.ts +0 -5
  121. package/dist/shared/index.js +0 -7
  122. package/dist/shared/model-registry.d.ts +0 -72
  123. package/dist/shared/model-registry.js +5 -95
  124. package/dist/shared/types.d.ts +0 -15
  125. package/dist/shared/types.js +0 -3
  126. package/dist/shared-context/dag.d.ts +0 -105
  127. package/dist/shared-context/dag.js +3 -114
  128. package/dist/shared-context/index.d.ts +0 -5
  129. package/dist/shared-context/index.js +0 -15
  130. package/dist/shared-context/logger.d.ts +0 -37
  131. package/dist/shared-context/logger.js +0 -41
  132. package/dist/shared-context/parallel-executor.d.ts +0 -54
  133. package/dist/shared-context/parallel-executor.js +4 -56
  134. package/dist/shared-context/session.d.ts +0 -56
  135. package/dist/shared-context/session.js +0 -47
  136. package/dist/shared-context/squad.d.ts +0 -68
  137. package/dist/shared-context/squad.js +0 -63
  138. package/dist/shared-context/storage.d.ts +0 -132
  139. package/dist/shared-context/storage.js +0 -116
  140. package/dist/shared-context/task.d.ts +0 -120
  141. package/dist/shared-context/task.js +0 -152
  142. package/dist/shared-context/test/dag.test.js +9 -14
  143. package/dist/shared-context/test/logger.test.d.ts +0 -8
  144. package/dist/shared-context/test/logger.test.js +0 -52
  145. package/dist/shared-context/test/session.test.d.ts +0 -7
  146. package/dist/shared-context/test/session.test.js +0 -63
  147. package/dist/shared-context/test/squad.test.d.ts +0 -10
  148. package/dist/shared-context/test/squad.test.js +2 -68
  149. package/dist/shared-context/test/storage.test.d.ts +0 -8
  150. package/dist/shared-context/test/storage.test.js +0 -68
  151. package/dist/shared-context/test/task.test.d.ts +0 -7
  152. package/dist/shared-context/test/task.test.js +0 -54
  153. package/dist/shared-context/test/watchdog.test.d.ts +0 -7
  154. package/dist/shared-context/test/watchdog.test.js +3 -58
  155. package/dist/shared-context/types.d.ts +0 -215
  156. package/dist/shared-context/types.js +0 -125
  157. package/dist/shared-context/watchdog.d.ts +0 -127
  158. package/dist/shared-context/watchdog.js +0 -148
  159. package/dist/shared-context/worktree.d.ts +0 -68
  160. package/dist/shared-context/worktree.js +2 -34
  161. package/dist/verify/budget.d.ts +0 -29
  162. package/dist/verify/budget.js +0 -34
  163. package/dist/verify/critical-files.d.ts +0 -17
  164. package/dist/verify/critical-files.js +0 -37
  165. package/dist/verify/escalation.d.ts +0 -20
  166. package/dist/verify/escalation.js +0 -22
  167. package/dist/verify/index.d.ts +0 -5
  168. package/dist/verify/index.js +0 -11
  169. package/dist/verify/prompts.d.ts +0 -20
  170. package/dist/verify/prompts.js +0 -20
  171. package/dist/verify/types.d.ts +0 -26
  172. package/dist/verify/types.js +1 -12
  173. package/dist/verify/verifier.d.ts +0 -29
  174. package/dist/verify/verifier.js +0 -54
  175. package/dist/version.d.ts +1 -16
  176. package/dist/version.js +1 -16
  177. package/dist/weave/bridge.d.ts +0 -35
  178. package/dist/weave/bridge.js +0 -51
  179. package/dist/weave/environment/detector.d.ts +0 -6
  180. package/dist/weave/environment/detector.js +4 -45
  181. package/dist/weave/environment/index.d.ts +0 -19
  182. package/dist/weave/environment/index.js +1 -39
  183. package/dist/weave/environment/issues.d.ts +0 -35
  184. package/dist/weave/environment/issues.js +0 -59
  185. package/dist/weave/git.d.ts +0 -8
  186. package/dist/weave/git.js +0 -8
  187. package/dist/weave/index.d.ts +0 -13
  188. package/dist/weave/index.js +2 -28
  189. package/dist/weave/knowledge/global.d.ts +0 -39
  190. package/dist/weave/knowledge/global.js +2 -78
  191. package/dist/weave/loop.js +0 -3
  192. package/dist/weave/orchestrator.d.ts +0 -69
  193. package/dist/weave/orchestrator.js +1 -101
  194. package/dist/weave/phase-manager.d.ts +0 -64
  195. package/dist/weave/phase-manager.js +0 -89
  196. package/dist/weave/security/secret-scan.d.ts +0 -14
  197. package/dist/weave/security/secret-scan.js +0 -19
  198. package/dist/weave/stages/build.js +0 -15
  199. package/dist/weave/stages/execute.d.ts +0 -42
  200. package/dist/weave/stages/execute.js +4 -86
  201. package/dist/weave/stages/handoff.d.ts +0 -7
  202. package/dist/weave/stages/handoff.js +0 -43
  203. package/dist/weave/stages/index.d.ts +0 -3
  204. package/dist/weave/stages/index.js +0 -3
  205. package/dist/weave/stages/intake.d.ts +0 -8
  206. package/dist/weave/stages/intake.js +5 -65
  207. package/dist/weave/stages/map.d.ts +0 -1
  208. package/dist/weave/stages/openspec.d.ts +0 -1
  209. package/dist/weave/stages/plan.d.ts +0 -11
  210. package/dist/weave/stages/plan.js +1 -53
  211. package/dist/weave/stages/refine.d.ts +0 -7
  212. package/dist/weave/stages/refine.js +0 -7
  213. package/dist/weave/stages/research.d.ts +0 -6
  214. package/dist/weave/stages/research.js +0 -6
  215. package/dist/weave/stages/spec.d.ts +0 -12
  216. package/dist/weave/stages/spec.js +0 -17
  217. package/dist/weave/types.d.ts +0 -20
  218. package/dist/weave/types.js +0 -5
  219. package/dist/weave/verification/commands.d.ts +0 -12
  220. package/dist/weave/verification/commands.js +0 -19
  221. package/dist/weave/verification/index.d.ts +0 -6
  222. package/dist/weave/verification/index.js +1 -19
  223. package/dist/weave/verification/playwright.d.ts +0 -47
  224. package/dist/weave/verification/playwright.js +1 -90
  225. package/dist/weave/worktree.d.ts +0 -16
  226. package/dist/weave/worktree.js +0 -23
  227. package/dist/weave/yaml-repair.d.ts +0 -39
  228. package/dist/weave/yaml-repair.js +13 -116
  229. package/package.json +1 -1
@@ -1,22 +1,9 @@
1
- /**
2
- * Weave Worktree Utilities
3
- *
4
- * Provides git worktree helpers tailored for Weave workflows.
5
- *
6
- * Goals:
7
- * - Enable parallel feature/phase work on isolated working directories
8
- * - Bootstrap .opencode/weave artifacts into newly created worktrees
9
- * - Keep "weave init once" principle by copying/creating required files
10
- */
11
1
  import * as fs from 'node:fs';
12
2
  import * as path from 'node:path';
13
3
  import { execFile } from 'node:child_process';
14
4
  import { promisify } from 'node:util';
15
5
  import { createWorktreeManager } from '../shared-context/worktree.js';
16
6
  const execFileAsync = promisify(execFile);
17
- // ============================================================================
18
- // Git helpers
19
- // ============================================================================
20
7
  async function git(cwd, args) {
21
8
  try {
22
9
  const { stdout } = await execFileAsync('git', args, { cwd });
@@ -44,9 +31,6 @@ function toKebabCase(input) {
44
31
  .replace(/[^a-z0-9]+/g, '-')
45
32
  .replace(/^-+|-+$/g, '');
46
33
  }
47
- // ============================================================================
48
- // Bootstrap helpers
49
- // ============================================================================
50
34
  export function ensureIgnoreOverride(projectRoot) {
51
35
  const ignorePath = path.join(projectRoot, '.ignore');
52
36
  const allowLine = '!.opencode/weave/';
@@ -148,7 +132,6 @@ function copyDirectoryRecursive(srcDir, destDir) {
148
132
  export function bootstrapWeaveArtifacts(fromRoot, toRoot) {
149
133
  ensureIgnoreOverride(toRoot);
150
134
  ensureWeaveState(toRoot);
151
- // Copy weave artifacts if they exist in the source worktree.
152
135
  copyIfExists(path.join(fromRoot, '.opencode', 'weave', 'state.yaml'), path.join(toRoot, '.opencode', 'weave', 'state.yaml'));
153
136
  copyYamlDirIfExists(path.join(fromRoot, '.opencode', 'weave', 'plans'), path.join(toRoot, '.opencode', 'weave', 'plans'));
154
137
  copyYamlDirIfExists(path.join(fromRoot, '.opencode', 'weave', 'specs'), path.join(toRoot, '.opencode', 'weave', 'specs'));
@@ -162,9 +145,6 @@ export function bootstrapGdcArtifacts(fromRoot, toRoot) {
162
145
  const destNodes = path.join(toRoot, '.gdc', 'nodes');
163
146
  copyGdcNodesRecursive(srcNodes, destNodes);
164
147
  }
165
- // ============================================================================
166
- // Public API
167
- // ============================================================================
168
148
  export async function createWeaveWorktree(options) {
169
149
  const basePath = path.resolve(options.basePath);
170
150
  const slug = toKebabCase(options.name);
@@ -230,9 +210,6 @@ export async function removeWeaveWorktree(options) {
230
210
  worktreeBase: path.join('.worktrees', 'weave'),
231
211
  branchPrefix: 'weave/',
232
212
  });
233
- // Remove worktree directory via git.
234
- // NOTE: The shared worktree manager also deletes the branch. For user-facing
235
- // flows we make branch deletion optional.
236
213
  const info = await manager.get(slug);
237
214
  if (!info)
238
215
  return;
@@ -1,19 +1,8 @@
1
- /**
2
- * YAML Repair Utility
3
- *
4
- * Provides YAML string escaping, corruption detection, and auto-repair
5
- * for Weave plan files. Handles common YAML corruption patterns:
6
- * - Unclosed/mismatched quotes
7
- * - Unescaped special characters in string values
8
- * - Tab→space conversion
9
- * - Truncated files
10
- */
11
1
  export interface RepairResult {
12
2
  file: string;
13
3
  status: 'ok' | 'repaired' | 'unrecoverable';
14
4
  error?: string;
15
5
  details?: string;
16
- /** Structured info about what's missing for user-assisted repair */
17
6
  missingInfo?: MissingInfo[];
18
7
  }
19
8
  export interface MissingInfo {
@@ -21,31 +10,13 @@ export interface MissingInfo {
21
10
  description: string;
22
11
  lineHint?: number;
23
12
  }
24
- /**
25
- * Properly escape a string value for YAML double-quoted format.
26
- * Handles all YAML special characters that would break parsing.
27
- */
28
13
  export declare function yamlEscapeString(value: string): string;
29
- /**
30
- * Attempt to repair corrupted YAML content.
31
- * Returns the repaired content or null if unrecoverable.
32
- */
33
14
  export declare function repairYamlContent(content: string): {
34
15
  repaired: string | null;
35
16
  changes: string[];
36
17
  missingInfo: MissingInfo[];
37
18
  };
38
- /**
39
- * Write a file atomically with backup.
40
- * 1. Copy existing file to .bak
41
- * 2. Write to .tmp
42
- * 3. Rename .tmp to target
43
- */
44
19
  export declare function safeWriteFile(filePath: string, content: string): void;
45
- /**
46
- * Safely read and parse a YAML file with auto-repair on failure.
47
- * Returns the parsed object, or an error message.
48
- */
49
20
  export declare function safeReadYaml(filePath: string): Promise<{
50
21
  data: any | null;
51
22
  repaired: boolean;
@@ -53,19 +24,9 @@ export declare function safeReadYaml(filePath: string): Promise<{
53
24
  changes?: string[];
54
25
  missingInfo?: MissingInfo[];
55
26
  }>;
56
- /**
57
- * Repair a single plan YAML file.
58
- */
59
27
  export declare function repairPlanFile(filePath: string): Promise<RepairResult>;
60
- /**
61
- * Scan and repair all plan YAML files in the plans/ directory.
62
- */
63
28
  export declare function repairAllPlans(basePath?: string): Promise<{
64
29
  results: RepairResult[];
65
30
  summary: string;
66
31
  }>;
67
- /**
68
- * Validate and sanitize plan structure after parsing.
69
- * Filters out invalid phases and ensures required fields exist.
70
- */
71
32
  export declare function validatePlanStructure(raw: any): any;
@@ -1,27 +1,9 @@
1
- /**
2
- * YAML Repair Utility
3
- *
4
- * Provides YAML string escaping, corruption detection, and auto-repair
5
- * for Weave plan files. Handles common YAML corruption patterns:
6
- * - Unclosed/mismatched quotes
7
- * - Unescaped special characters in string values
8
- * - Tab→space conversion
9
- * - Truncated files
10
- */
11
1
  import * as fs from 'node:fs';
12
2
  import * as path from 'node:path';
13
- // ============================================================================
14
- // YAML String Escaping
15
- // ============================================================================
16
- /**
17
- * Properly escape a string value for YAML double-quoted format.
18
- * Handles all YAML special characters that would break parsing.
19
- */
20
3
  export function yamlEscapeString(value) {
21
4
  if (value === undefined || value === null)
22
5
  return '""';
23
6
  const str = String(value);
24
- // If the string is simple (no special chars), return as-is with quotes
25
7
  if (/^[a-zA-Z0-9가-힣ぁ-んァ-ヶ\s.,;:!?@#%^&*()_+=\-\[\]{}/<>~`|']+$/.test(str)
26
8
  && !str.includes('"')
27
9
  && !str.includes('\\')
@@ -29,40 +11,30 @@ export function yamlEscapeString(value) {
29
11
  && !str.endsWith(' ')) {
30
12
  return `"${str}"`;
31
13
  }
32
- // Escape special characters for YAML double-quoted strings
33
14
  const escaped = str
34
- .replace(/\\/g, '\\\\') // backslash first
35
- .replace(/"/g, '\\"') // double quotes
36
- .replace(/\n/g, '\\n') // newlines
37
- .replace(/\r/g, '\\r') // carriage returns
38
- .replace(/\t/g, '\\t') // tabs
39
- .replace(/\0/g, '\\0'); // null bytes
15
+ .replace(/\\/g, '\\\\')
16
+ .replace(/"/g, '\\"')
17
+ .replace(/\n/g, '\\n')
18
+ .replace(/\r/g, '\\r')
19
+ .replace(/\t/g, '\\t')
20
+ .replace(/\0/g, '\\0');
40
21
  return `"${escaped}"`;
41
22
  }
42
- // ============================================================================
43
- // YAML Corruption Detection
44
- // ============================================================================
45
- /**
46
- * Detect common YAML corruption patterns and return error details.
47
- */
48
23
  function detectCorruption(content) {
49
24
  const issues = [];
50
25
  const lines = content.split('\n');
51
26
  for (let i = 0; i < lines.length; i++) {
52
27
  const line = lines[i];
53
28
  const lineNum = i + 1;
54
- // Check for unclosed double quotes in value positions
55
29
  const valueMatch = line.match(/^(\s*[\w_-]+:\s*)"(.*)/);
56
30
  if (valueMatch) {
57
31
  const afterColon = valueMatch[2];
58
- // Count unescaped quotes
59
32
  const unescaped = afterColon.replace(/\\"/g, '');
60
33
  const quoteCount = (unescaped.match(/"/g) || []).length;
61
34
  if (quoteCount % 2 !== 0) {
62
35
  issues.push(`Line ${lineNum}: Unclosed double quote in value`);
63
36
  }
64
37
  }
65
- // Check for array items with unclosed quotes
66
38
  const arrayMatch = line.match(/^(\s*-\s*)"(.*)/);
67
39
  if (arrayMatch && !line.match(/^(\s*-\s*\w+:\s*)/)) {
68
40
  const afterDash = arrayMatch[2];
@@ -72,7 +44,6 @@ function detectCorruption(content) {
72
44
  issues.push(`Line ${lineNum}: Unclosed double quote in array item`);
73
45
  }
74
46
  }
75
- // Check for tabs (YAML requires spaces)
76
47
  if (line.includes('\t') && !line.match(/:\s*".*\t.*"/)) {
77
48
  issues.push(`Line ${lineNum}: Tab character in indentation`);
78
49
  }
@@ -82,23 +53,14 @@ function detectCorruption(content) {
82
53
  issues,
83
54
  };
84
55
  }
85
- // ============================================================================
86
- // YAML Content Repair
87
- // ============================================================================
88
- /**
89
- * Attempt to repair corrupted YAML content.
90
- * Returns the repaired content or null if unrecoverable.
91
- */
92
56
  export function repairYamlContent(content) {
93
57
  const changes = [];
94
58
  const missingInfo = [];
95
59
  let repaired = content;
96
- // 1. Convert tabs to spaces (YAML requires spaces)
97
60
  if (repaired.includes('\t')) {
98
61
  repaired = repaired.replace(/\t/g, ' ');
99
62
  changes.push('Converted tabs to spaces');
100
63
  }
101
- // 2. Normalize line endings
102
64
  if (repaired.includes('\r\n')) {
103
65
  repaired = repaired.replace(/\r\n/g, '\n');
104
66
  changes.push('Normalized line endings (CRLF→LF)');
@@ -107,27 +69,22 @@ export function repairYamlContent(content) {
107
69
  repaired = repaired.replace(/\r/g, '\n');
108
70
  changes.push('Normalized line endings (CR→LF)');
109
71
  }
110
- // 3. Fix unclosed quotes in key-value pairs
111
72
  const lines = repaired.split('\n');
112
73
  const fixedLines = [];
113
74
  for (let i = 0; i < lines.length; i++) {
114
75
  let line = lines[i];
115
76
  const lineNum = i + 1;
116
- // Pattern: key: "value with "embedded" quotes or unclosed
117
77
  const kvMatch = line.match(/^(\s*)([\w_-]+):\s*"(.*)$/);
118
78
  if (kvMatch) {
119
79
  const [, indent, key, rest] = kvMatch;
120
- // Check if the rest ends with a properly closed quote
121
80
  if (!rest.endsWith('"') || hasUnbalancedQuotes(rest)) {
122
- // Fix: escape internal quotes and ensure closure
123
81
  const fixedValue = rest
124
- .replace(/"$/g, '') // remove trailing quote if any
125
- .replace(/(?<!\\)"/g, '\\"'); // escape unescaped internal quotes
82
+ .replace(/"$/g, '')
83
+ .replace(/(?<!\\)"/g, '\\"');
126
84
  line = `${indent}${key}: "${fixedValue}"`;
127
85
  changes.push(`Line ${lineNum}: Fixed unclosed/mismatched quotes in '${key}'`);
128
86
  }
129
87
  }
130
- // Pattern: array item - "value with unclosed quotes
131
88
  const arrayMatch = line.match(/^(\s*-\s*)"(.*)$/);
132
89
  if (arrayMatch && !line.match(/^(\s*-\s*\w+:\s*)/)) {
133
90
  const [, prefix, rest] = arrayMatch;
@@ -139,7 +96,6 @@ export function repairYamlContent(content) {
139
96
  changes.push(`Line ${lineNum}: Fixed unclosed quotes in array item`);
140
97
  }
141
98
  }
142
- // Pattern: array item key: "value with unclosed quotes
143
99
  const arrayKvMatch = line.match(/^(\s*-?\s*)([\w_-]+):\s*"(.*)$/);
144
100
  if (arrayKvMatch) {
145
101
  const [, indent, key, rest] = arrayKvMatch;
@@ -154,9 +110,7 @@ export function repairYamlContent(content) {
154
110
  fixedLines.push(line);
155
111
  }
156
112
  repaired = fixedLines.join('\n');
157
- // 4. Validate the repaired content by attempting a parse
158
113
  try {
159
- // Dynamic import would be async, so we do a basic structural check
160
114
  if (!hasBasicYamlStructure(repaired)) {
161
115
  missingInfo.push({
162
116
  field: 'structure',
@@ -165,78 +119,48 @@ export function repairYamlContent(content) {
165
119
  }
166
120
  }
167
121
  catch {
168
- // ignore validation errors at this stage
169
122
  }
170
123
  if (changes.length === 0 && missingInfo.length > 0) {
171
124
  return { repaired: null, changes, missingInfo };
172
125
  }
173
126
  return { repaired, changes, missingInfo };
174
127
  }
175
- /**
176
- * Check if a string (after the opening quote) has unbalanced quotes.
177
- */
178
128
  function hasUnbalancedQuotes(str) {
179
- // Remove escaped quotes
180
129
  const cleaned = str.replace(/\\"/g, '');
181
- // Count remaining quotes (should be odd number since the opening was already stripped)
182
130
  const count = (cleaned.match(/"/g) || []).length;
183
- // After opening quote was stripped, remaining should have odd count
184
- // (one for closing). Even count means unbalanced.
185
131
  return count % 2 === 0;
186
132
  }
187
- /**
188
- * Basic structural validation for a Weave plan YAML.
189
- */
190
133
  function hasBasicYamlStructure(content) {
191
134
  return content.includes('project_name:') && content.includes('phases:');
192
135
  }
193
- // ============================================================================
194
- // Safe File I/O
195
- // ============================================================================
196
- /**
197
- * Write a file atomically with backup.
198
- * 1. Copy existing file to .bak
199
- * 2. Write to .tmp
200
- * 3. Rename .tmp to target
201
- */
202
136
  export function safeWriteFile(filePath, content) {
203
- // Create backup of existing file
204
137
  if (fs.existsSync(filePath)) {
205
138
  try {
206
139
  fs.copyFileSync(filePath, `${filePath}.bak`);
207
140
  }
208
141
  catch {
209
- // Backup failed, continue anyway
210
142
  }
211
143
  }
212
144
  const tmpPath = `${filePath}.tmp`;
213
145
  try {
214
146
  fs.writeFileSync(tmpPath, content, 'utf-8');
215
- // Atomic rename
216
147
  try {
217
148
  fs.renameSync(tmpPath, filePath);
218
149
  }
219
150
  catch {
220
- // Windows fallback: rename can fail if target exists
221
151
  fs.writeFileSync(filePath, content, 'utf-8');
222
152
  try {
223
153
  fs.unlinkSync(tmpPath);
224
154
  }
225
- catch { /* ignore */ }
155
+ catch { }
226
156
  }
227
157
  }
228
158
  catch (e) {
229
- // Last resort: direct write
230
159
  fs.writeFileSync(filePath, content, 'utf-8');
231
160
  }
232
161
  }
233
- /**
234
- * Safely read and parse a YAML file with auto-repair on failure.
235
- * Returns the parsed object, or an error message.
236
- */
237
162
  export async function safeReadYaml(filePath) {
238
163
  const { parse } = await import('yaml');
239
- // 1. Try normal read + parse
240
164
  try {
241
165
  const content = fs.readFileSync(filePath, 'utf-8');
242
166
  const data = parse(content);
@@ -244,18 +168,16 @@ export async function safeReadYaml(filePath) {
244
168
  }
245
169
  catch (parseError) {
246
170
  const errorMsg = parseError instanceof Error ? parseError.message : String(parseError);
247
- // 2. Try auto-repair
248
171
  try {
249
172
  const rawContent = fs.readFileSync(filePath, 'utf-8');
250
173
  const repair = repairYamlContent(rawContent);
251
174
  if (repair.repaired) {
252
175
  try {
253
176
  const data = parse(repair.repaired);
254
- // Save corrupted backup and write repaired content
255
177
  try {
256
178
  fs.copyFileSync(filePath, `${filePath}.corrupted`);
257
179
  }
258
- catch { /* ignore backup failure */ }
180
+ catch { }
259
181
  safeWriteFile(filePath, repair.repaired);
260
182
  console.log(`[PhaseManager] Auto-repaired ${path.basename(filePath)}: ${repair.changes.join(', ')}`);
261
183
  return {
@@ -266,29 +188,25 @@ export async function safeReadYaml(filePath) {
266
188
  };
267
189
  }
268
190
  catch (repairParseError) {
269
- // Repair didn't fix the parse error
270
191
  }
271
192
  }
272
193
  }
273
- catch { /* repair attempt failed */ }
274
- // 3. Try .bak file
194
+ catch { }
275
195
  const bakPath = `${filePath}.bak`;
276
196
  if (fs.existsSync(bakPath)) {
277
197
  try {
278
198
  const bakContent = fs.readFileSync(bakPath, 'utf-8');
279
199
  const data = parse(bakContent);
280
- // Save corrupted file and restore from backup
281
200
  try {
282
201
  fs.copyFileSync(filePath, `${filePath}.corrupted`);
283
202
  }
284
- catch { /* ignore */ }
203
+ catch { }
285
204
  fs.copyFileSync(bakPath, filePath);
286
205
  console.log(`[PhaseManager] Restored ${path.basename(filePath)} from backup`);
287
206
  return { data, repaired: true, changes: ['Restored from .bak backup'] };
288
207
  }
289
- catch { /* .bak also corrupted */ }
208
+ catch { }
290
209
  }
291
- // 4. Unrecoverable
292
210
  return {
293
211
  data: null,
294
212
  repaired: false,
@@ -300,12 +218,6 @@ export async function safeReadYaml(filePath) {
300
218
  };
301
219
  }
302
220
  }
303
- // ============================================================================
304
- // Plan File Repair
305
- // ============================================================================
306
- /**
307
- * Repair a single plan YAML file.
308
- */
309
221
  export async function repairPlanFile(filePath) {
310
222
  const fileName = path.basename(filePath);
311
223
  if (!fs.existsSync(filePath)) {
@@ -330,24 +242,18 @@ export async function repairPlanFile(filePath) {
330
242
  missingInfo: result.missingInfo,
331
243
  };
332
244
  }
333
- /**
334
- * Scan and repair all plan YAML files in the plans/ directory.
335
- */
336
245
  export async function repairAllPlans(basePath = process.cwd()) {
337
246
  const weaveDir = path.join(basePath, '.opencode', 'weave');
338
247
  const plansDir = path.join(weaveDir, 'plans');
339
248
  const results = [];
340
- // Check legacy PLAN.yaml
341
249
  const legacyPath = path.join(weaveDir, 'PLAN.yaml');
342
250
  if (fs.existsSync(legacyPath)) {
343
251
  results.push(await repairPlanFile(legacyPath));
344
252
  }
345
- // Check state.yaml
346
253
  const statePath = path.join(weaveDir, 'state.yaml');
347
254
  if (fs.existsSync(statePath)) {
348
255
  results.push(await repairPlanFile(statePath));
349
256
  }
350
- // Scan plans/ directory
351
257
  if (fs.existsSync(plansDir)) {
352
258
  try {
353
259
  const files = fs.readdirSync(plansDir).filter(f => f.endsWith('.yaml'));
@@ -360,7 +266,6 @@ export async function repairAllPlans(basePath = process.cwd()) {
360
266
  console.error('[YamlRepair] Failed to scan plans directory:', e);
361
267
  }
362
268
  }
363
- // Generate summary
364
269
  const ok = results.filter(r => r.status === 'ok').length;
365
270
  const repaired = results.filter(r => r.status === 'repaired').length;
366
271
  const unrecoverable = results.filter(r => r.status === 'unrecoverable').length;
@@ -391,7 +296,6 @@ export async function repairAllPlans(basePath = process.cwd()) {
391
296
  lines.push('');
392
297
  }
393
298
  }
394
- // Advice for unrecoverable files
395
299
  if (unrecoverable > 0) {
396
300
  lines.push('---');
397
301
  lines.push('### Recovery Options for Unrecoverable Files\n');
@@ -401,18 +305,12 @@ export async function repairAllPlans(basePath = process.cwd()) {
401
305
  }
402
306
  return { results, summary: lines.join('\n') };
403
307
  }
404
- /**
405
- * Validate and sanitize plan structure after parsing.
406
- * Filters out invalid phases and ensures required fields exist.
407
- */
408
308
  export function validatePlanStructure(raw) {
409
309
  if (!raw || typeof raw !== 'object')
410
310
  return null;
411
- // Ensure required fields
412
311
  if (!raw.project_name && !raw.projectName) {
413
312
  raw.project_name = 'Unknown (recovered)';
414
313
  }
415
- // Filter invalid phases
416
314
  if (Array.isArray(raw.phases)) {
417
315
  raw.phases = raw.phases.filter((p) => {
418
316
  if (!p || typeof p !== 'object')
@@ -421,7 +319,6 @@ export function validatePlanStructure(raw) {
421
319
  return false;
422
320
  return true;
423
321
  });
424
- // Sanitize each phase
425
322
  for (const phase of raw.phases) {
426
323
  if (!phase.name)
427
324
  phase.name = phase.id;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maskweaver",
3
- "version": "0.9.4",
3
+ "version": "0.9.6",
4
4
  "description": "AI Expert Persona System - Give your AI coding assistant expert personalities (가면술사)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",