ctxinit 0.1.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.
- package/LICENSE +21 -0
- package/README.md +484 -0
- package/bin/ctx.js +3 -0
- package/dist/analysis/index.d.ts +2 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +18 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/static-analysis.d.ts +79 -0
- package/dist/analysis/static-analysis.d.ts.map +1 -0
- package/dist/analysis/static-analysis.js +279 -0
- package/dist/analysis/static-analysis.js.map +1 -0
- package/dist/bootstrap/index.d.ts +8 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +13 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/bootstrap/orchestrator.d.ts +48 -0
- package/dist/bootstrap/orchestrator.d.ts.map +1 -0
- package/dist/bootstrap/orchestrator.js +363 -0
- package/dist/bootstrap/orchestrator.js.map +1 -0
- package/dist/bootstrap/validator.d.ts +25 -0
- package/dist/bootstrap/validator.d.ts.map +1 -0
- package/dist/bootstrap/validator.js +412 -0
- package/dist/bootstrap/validator.js.map +1 -0
- package/dist/build/atomic.d.ts +74 -0
- package/dist/build/atomic.d.ts.map +1 -0
- package/dist/build/atomic.js +235 -0
- package/dist/build/atomic.js.map +1 -0
- package/dist/build/index.d.ts +10 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +26 -0
- package/dist/build/index.js.map +1 -0
- package/dist/build/lock.d.ts +102 -0
- package/dist/build/lock.d.ts.map +1 -0
- package/dist/build/lock.js +297 -0
- package/dist/build/lock.js.map +1 -0
- package/dist/build/manifest.d.ts +138 -0
- package/dist/build/manifest.d.ts.map +1 -0
- package/dist/build/manifest.js +269 -0
- package/dist/build/manifest.js.map +1 -0
- package/dist/build/orchestrator.d.ts +103 -0
- package/dist/build/orchestrator.d.ts.map +1 -0
- package/dist/build/orchestrator.js +524 -0
- package/dist/build/orchestrator.js.map +1 -0
- package/dist/cli/bootstrap.d.ts +77 -0
- package/dist/cli/bootstrap.d.ts.map +1 -0
- package/dist/cli/bootstrap.js +527 -0
- package/dist/cli/bootstrap.js.map +1 -0
- package/dist/cli/build.d.ts +32 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +156 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/diff.d.ts +23 -0
- package/dist/cli/diff.d.ts.map +1 -0
- package/dist/cli/diff.js +226 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/hooks.d.ts +29 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +176 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/init.d.ts +53 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +254 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/lint.d.ts +46 -0
- package/dist/cli/lint.d.ts.map +1 -0
- package/dist/cli/lint.js +210 -0
- package/dist/cli/lint.js.map +1 -0
- package/dist/cli/migrate.d.ts +28 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +350 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/verify.d.ts +21 -0
- package/dist/cli/verify.d.ts.map +1 -0
- package/dist/cli/verify.js +209 -0
- package/dist/cli/verify.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +262 -0
- package/dist/cli.js.map +1 -0
- package/dist/compiler/agents-compiler.d.ts +24 -0
- package/dist/compiler/agents-compiler.d.ts.map +1 -0
- package/dist/compiler/agents-compiler.js +192 -0
- package/dist/compiler/agents-compiler.js.map +1 -0
- package/dist/compiler/base-compiler.d.ts +152 -0
- package/dist/compiler/base-compiler.d.ts.map +1 -0
- package/dist/compiler/base-compiler.js +180 -0
- package/dist/compiler/base-compiler.js.map +1 -0
- package/dist/compiler/claude-compiler.d.ts +24 -0
- package/dist/compiler/claude-compiler.d.ts.map +1 -0
- package/dist/compiler/claude-compiler.js +182 -0
- package/dist/compiler/claude-compiler.js.map +1 -0
- package/dist/compiler/cursor-compiler.d.ts +33 -0
- package/dist/compiler/cursor-compiler.d.ts.map +1 -0
- package/dist/compiler/cursor-compiler.js +136 -0
- package/dist/compiler/cursor-compiler.js.map +1 -0
- package/dist/compiler/index.d.ts +7 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +24 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/compiler/rule-selector.d.ts +115 -0
- package/dist/compiler/rule-selector.d.ts.map +1 -0
- package/dist/compiler/rule-selector.js +273 -0
- package/dist/compiler/rule-selector.js.map +1 -0
- package/dist/compiler/token-estimator.d.ts +74 -0
- package/dist/compiler/token-estimator.d.ts.map +1 -0
- package/dist/compiler/token-estimator.js +191 -0
- package/dist/compiler/token-estimator.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +18 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +48 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +175 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/git/gitignore.d.ts +59 -0
- package/dist/git/gitignore.d.ts.map +1 -0
- package/dist/git/gitignore.js +268 -0
- package/dist/git/gitignore.js.map +1 -0
- package/dist/git/hooks.d.ts +34 -0
- package/dist/git/hooks.d.ts.map +1 -0
- package/dist/git/hooks.js +129 -0
- package/dist/git/hooks.js.map +1 -0
- package/dist/git/husky.d.ts +52 -0
- package/dist/git/husky.d.ts.map +1 -0
- package/dist/git/husky.js +219 -0
- package/dist/git/husky.js.map +1 -0
- package/dist/git/index.d.ts +9 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +15 -0
- package/dist/git/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/base-provider.d.ts +43 -0
- package/dist/llm/base-provider.d.ts.map +1 -0
- package/dist/llm/base-provider.js +91 -0
- package/dist/llm/base-provider.js.map +1 -0
- package/dist/llm/index.d.ts +17 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +36 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/prompts/bootstrap-prompt.d.ts +27 -0
- package/dist/llm/prompts/bootstrap-prompt.d.ts.map +1 -0
- package/dist/llm/prompts/bootstrap-prompt.js +278 -0
- package/dist/llm/prompts/bootstrap-prompt.js.map +1 -0
- package/dist/llm/prompts/index.d.ts +5 -0
- package/dist/llm/prompts/index.d.ts.map +1 -0
- package/dist/llm/prompts/index.js +11 -0
- package/dist/llm/prompts/index.js.map +1 -0
- package/dist/llm/provider-factory.d.ts +27 -0
- package/dist/llm/provider-factory.d.ts.map +1 -0
- package/dist/llm/provider-factory.js +213 -0
- package/dist/llm/provider-factory.js.map +1 -0
- package/dist/llm/providers/claude-api.d.ts +21 -0
- package/dist/llm/providers/claude-api.d.ts.map +1 -0
- package/dist/llm/providers/claude-api.js +110 -0
- package/dist/llm/providers/claude-api.js.map +1 -0
- package/dist/llm/providers/claude-code.d.ts +21 -0
- package/dist/llm/providers/claude-code.d.ts.map +1 -0
- package/dist/llm/providers/claude-code.js +120 -0
- package/dist/llm/providers/claude-code.js.map +1 -0
- package/dist/llm/providers/codex-cli.d.ts +25 -0
- package/dist/llm/providers/codex-cli.d.ts.map +1 -0
- package/dist/llm/providers/codex-cli.js +129 -0
- package/dist/llm/providers/codex-cli.js.map +1 -0
- package/dist/llm/providers/cursor-cli.d.ts +24 -0
- package/dist/llm/providers/cursor-cli.d.ts.map +1 -0
- package/dist/llm/providers/cursor-cli.js +106 -0
- package/dist/llm/providers/cursor-cli.js.map +1 -0
- package/dist/llm/providers/gemini-api.d.ts +20 -0
- package/dist/llm/providers/gemini-api.d.ts.map +1 -0
- package/dist/llm/providers/gemini-api.js +121 -0
- package/dist/llm/providers/gemini-api.js.map +1 -0
- package/dist/llm/providers/gemini-cli.d.ts +20 -0
- package/dist/llm/providers/gemini-cli.d.ts.map +1 -0
- package/dist/llm/providers/gemini-cli.js +109 -0
- package/dist/llm/providers/gemini-cli.js.map +1 -0
- package/dist/llm/providers/interactive.d.ts +42 -0
- package/dist/llm/providers/interactive.d.ts.map +1 -0
- package/dist/llm/providers/interactive.js +200 -0
- package/dist/llm/providers/interactive.js.map +1 -0
- package/dist/llm/providers/openai-api.d.ts +21 -0
- package/dist/llm/providers/openai-api.d.ts.map +1 -0
- package/dist/llm/providers/openai-api.js +107 -0
- package/dist/llm/providers/openai-api.js.map +1 -0
- package/dist/llm/types.d.ts +128 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +8 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/parser/index.d.ts +3 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +19 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/path-security.d.ts +40 -0
- package/dist/parser/path-security.d.ts.map +1 -0
- package/dist/parser/path-security.js +183 -0
- package/dist/parser/path-security.js.map +1 -0
- package/dist/parser/rule-parser.d.ts +50 -0
- package/dist/parser/rule-parser.d.ts.map +1 -0
- package/dist/parser/rule-parser.js +203 -0
- package/dist/parser/rule-parser.js.map +1 -0
- package/dist/schemas/config.d.ts +202 -0
- package/dist/schemas/config.d.ts.map +1 -0
- package/dist/schemas/config.js +96 -0
- package/dist/schemas/config.js.map +1 -0
- package/dist/schemas/index.d.ts +3 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +19 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/rule.d.ts +67 -0
- package/dist/schemas/rule.d.ts.map +1 -0
- package/dist/schemas/rule.js +44 -0
- package/dist/schemas/rule.js.map +1 -0
- package/package.json +69 -0
- package/templates/architecture.md +35 -0
- package/templates/bootstrap-prompt.md +242 -0
- package/templates/config.yaml +25 -0
- package/templates/project.md +44 -0
- package/templates/rules/example.md +36 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Bootstrap Output Validator
|
|
4
|
+
*
|
|
5
|
+
* Validates LLM-generated context files for:
|
|
6
|
+
* - Valid file/directory references
|
|
7
|
+
* - Valid glob patterns
|
|
8
|
+
* - Correct YAML frontmatter structure
|
|
9
|
+
* - LLM-specific best practices
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.validateBootstrapOutput = validateBootstrapOutput;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
53
|
+
/**
|
|
54
|
+
* Validate bootstrap output
|
|
55
|
+
*/
|
|
56
|
+
async function validateBootstrapOutput(output, projectRoot, analysis) {
|
|
57
|
+
const errors = [];
|
|
58
|
+
const warnings = [];
|
|
59
|
+
const suggestions = [];
|
|
60
|
+
// Validate project.md
|
|
61
|
+
if (output.projectMd) {
|
|
62
|
+
const projectValidation = validateMarkdownContent(output.projectMd, 'project.md', projectRoot, analysis);
|
|
63
|
+
errors.push(...projectValidation.errors);
|
|
64
|
+
warnings.push(...projectValidation.warnings);
|
|
65
|
+
}
|
|
66
|
+
// Validate architecture.md
|
|
67
|
+
if (output.architectureMd) {
|
|
68
|
+
const archValidation = validateMarkdownContent(output.architectureMd, 'architecture.md', projectRoot, analysis);
|
|
69
|
+
errors.push(...archValidation.errors);
|
|
70
|
+
warnings.push(...archValidation.warnings);
|
|
71
|
+
}
|
|
72
|
+
// Validate rules
|
|
73
|
+
for (const rule of output.rules) {
|
|
74
|
+
const ruleValidation = await validateRule(rule, projectRoot, analysis);
|
|
75
|
+
errors.push(...ruleValidation.errors);
|
|
76
|
+
warnings.push(...ruleValidation.warnings);
|
|
77
|
+
suggestions.push(...ruleValidation.suggestions);
|
|
78
|
+
}
|
|
79
|
+
// Check for best practices
|
|
80
|
+
const bestPractices = checkBestPractices(output, analysis);
|
|
81
|
+
warnings.push(...bestPractices.warnings);
|
|
82
|
+
suggestions.push(...bestPractices.suggestions);
|
|
83
|
+
return {
|
|
84
|
+
valid: errors.length === 0,
|
|
85
|
+
errors,
|
|
86
|
+
warnings,
|
|
87
|
+
suggestions,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Validate markdown content for file references
|
|
92
|
+
*/
|
|
93
|
+
function validateMarkdownContent(content, fileName, projectRoot, _analysis) {
|
|
94
|
+
const errors = [];
|
|
95
|
+
const warnings = [];
|
|
96
|
+
// Extract @file references
|
|
97
|
+
const fileRefs = extractFileReferences(content);
|
|
98
|
+
for (const ref of fileRefs) {
|
|
99
|
+
const fullPath = path.join(projectRoot, ref);
|
|
100
|
+
if (!fs.existsSync(fullPath)) {
|
|
101
|
+
// Check if it's a directory
|
|
102
|
+
const dirPath = fullPath.replace(/\/$/, '');
|
|
103
|
+
if (!fs.existsSync(dirPath)) {
|
|
104
|
+
errors.push(`${fileName}: Invalid file reference '@${ref}' - file does not exist`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Extract markdown links
|
|
109
|
+
const links = extractMarkdownLinks(content);
|
|
110
|
+
for (const link of links) {
|
|
111
|
+
// Skip external URLs
|
|
112
|
+
if (link.startsWith('http://') || link.startsWith('https://')) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Check relative paths
|
|
116
|
+
if (!link.startsWith('#')) {
|
|
117
|
+
const fullPath = path.join(projectRoot, link);
|
|
118
|
+
if (!fs.existsSync(fullPath)) {
|
|
119
|
+
warnings.push(`${fileName}: Potentially broken link '${link}'`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Check for generic/vague content
|
|
124
|
+
const genericPhrases = [
|
|
125
|
+
'write clean code',
|
|
126
|
+
'follow best practices',
|
|
127
|
+
'be careful',
|
|
128
|
+
'use appropriate',
|
|
129
|
+
'ensure quality',
|
|
130
|
+
];
|
|
131
|
+
for (const phrase of genericPhrases) {
|
|
132
|
+
if (content.toLowerCase().includes(phrase)) {
|
|
133
|
+
warnings.push(`${fileName}: Contains generic phrase '${phrase}' - be more specific`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return { errors, warnings };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Validate a rule file
|
|
140
|
+
*/
|
|
141
|
+
async function validateRule(rule, projectRoot, _analysis) {
|
|
142
|
+
const errors = [];
|
|
143
|
+
const warnings = [];
|
|
144
|
+
const suggestions = [];
|
|
145
|
+
// Parse frontmatter
|
|
146
|
+
const frontmatter = parseFrontmatter(rule.content);
|
|
147
|
+
if (!frontmatter) {
|
|
148
|
+
errors.push(`${rule.path}: Missing or invalid YAML frontmatter`);
|
|
149
|
+
return { valid: false, errors, warnings, suggestions };
|
|
150
|
+
}
|
|
151
|
+
// Validate required frontmatter fields
|
|
152
|
+
if (!frontmatter.id) {
|
|
153
|
+
errors.push(`${rule.path}: Missing required 'id' in frontmatter`);
|
|
154
|
+
}
|
|
155
|
+
else if (!/^[a-z0-9-]+$/.test(frontmatter.id)) {
|
|
156
|
+
warnings.push(`${rule.path}: Rule ID '${frontmatter.id}' should be lowercase with hyphens`);
|
|
157
|
+
}
|
|
158
|
+
if (!frontmatter.description) {
|
|
159
|
+
warnings.push(`${rule.path}: Missing 'description' in frontmatter`);
|
|
160
|
+
}
|
|
161
|
+
// Validate globs
|
|
162
|
+
if (frontmatter.globs && Array.isArray(frontmatter.globs)) {
|
|
163
|
+
for (const glob of frontmatter.globs) {
|
|
164
|
+
const globValidation = validateGlobPattern(glob, projectRoot);
|
|
165
|
+
if (!globValidation.valid) {
|
|
166
|
+
errors.push(`${rule.path}: Invalid glob pattern '${glob}': ${globValidation.reason}`);
|
|
167
|
+
}
|
|
168
|
+
else if (globValidation.warning) {
|
|
169
|
+
warnings.push(`${rule.path}: Glob warning for '${glob}': ${globValidation.warning}`);
|
|
170
|
+
}
|
|
171
|
+
// Check if glob matches any files
|
|
172
|
+
const matches = await (0, fast_glob_1.default)(glob, { cwd: projectRoot, onlyFiles: true, dot: true });
|
|
173
|
+
if (matches.length === 0) {
|
|
174
|
+
warnings.push(`${rule.path}: Glob '${glob}' matches no files in project`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
warnings.push(`${rule.path}: Missing 'globs' array in frontmatter`);
|
|
180
|
+
}
|
|
181
|
+
// Validate priority
|
|
182
|
+
if (frontmatter.priority !== undefined) {
|
|
183
|
+
if (typeof frontmatter.priority !== 'number' || frontmatter.priority < 0 || frontmatter.priority > 100) {
|
|
184
|
+
errors.push(`${rule.path}: Priority must be a number between 0 and 100`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Validate content
|
|
188
|
+
const contentValidation = validateMarkdownContent(rule.content, rule.path, projectRoot, _analysis);
|
|
189
|
+
errors.push(...contentValidation.errors);
|
|
190
|
+
warnings.push(...contentValidation.warnings);
|
|
191
|
+
// Check content quality
|
|
192
|
+
const bodyContent = rule.content.replace(/^---[\s\S]*?---/, '').trim();
|
|
193
|
+
if (bodyContent.length < 100) {
|
|
194
|
+
warnings.push(`${rule.path}: Rule content is very short (${bodyContent.length} chars)`);
|
|
195
|
+
}
|
|
196
|
+
// Check for imperative style
|
|
197
|
+
const sentences = bodyContent.split(/[.!]\s+/);
|
|
198
|
+
let nonImperativeCount = 0;
|
|
199
|
+
for (const sentence of sentences) {
|
|
200
|
+
const trimmed = sentence.trim();
|
|
201
|
+
if (trimmed.length > 10) {
|
|
202
|
+
// Check for non-imperative patterns
|
|
203
|
+
if (/^(you should|you must|we should|it is|there are|this is)/i.test(trimmed)) {
|
|
204
|
+
nonImperativeCount++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (nonImperativeCount > 2) {
|
|
209
|
+
suggestions.push(`${rule.path}: Consider using more imperative style (e.g., "Use X" instead of "You should use X")`);
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
valid: errors.length === 0,
|
|
213
|
+
errors,
|
|
214
|
+
warnings,
|
|
215
|
+
suggestions,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Parse YAML frontmatter from content
|
|
220
|
+
*/
|
|
221
|
+
function parseFrontmatter(content) {
|
|
222
|
+
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
223
|
+
if (!match)
|
|
224
|
+
return null;
|
|
225
|
+
try {
|
|
226
|
+
const yaml = match[1];
|
|
227
|
+
const frontmatter = {};
|
|
228
|
+
// Simple YAML parser for frontmatter
|
|
229
|
+
const lines = yaml.split('\n');
|
|
230
|
+
let currentKey = null;
|
|
231
|
+
let inArray = false;
|
|
232
|
+
let arrayValues = [];
|
|
233
|
+
for (const line of lines) {
|
|
234
|
+
const trimmed = line.trim();
|
|
235
|
+
if (trimmed.startsWith('- ') && inArray && currentKey) {
|
|
236
|
+
// Array item
|
|
237
|
+
const value = trimmed.slice(2).trim().replace(/^["']|["']$/g, '');
|
|
238
|
+
arrayValues.push(value);
|
|
239
|
+
}
|
|
240
|
+
else if (trimmed.includes(':')) {
|
|
241
|
+
// Save previous array if exists
|
|
242
|
+
if (inArray && currentKey && arrayValues.length > 0) {
|
|
243
|
+
frontmatter[currentKey] = arrayValues;
|
|
244
|
+
arrayValues = [];
|
|
245
|
+
inArray = false;
|
|
246
|
+
}
|
|
247
|
+
const colonIndex = trimmed.indexOf(':');
|
|
248
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
249
|
+
const value = trimmed.slice(colonIndex + 1).trim();
|
|
250
|
+
if (value === '' || value === '|' || value === '>') {
|
|
251
|
+
// Start of array or multiline
|
|
252
|
+
currentKey = key;
|
|
253
|
+
inArray = true;
|
|
254
|
+
arrayValues = [];
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// Simple value
|
|
258
|
+
currentKey = key;
|
|
259
|
+
let parsedValue = value.replace(/^["']|["']$/g, '');
|
|
260
|
+
// Parse numbers and booleans
|
|
261
|
+
if (parsedValue === 'true')
|
|
262
|
+
parsedValue = true;
|
|
263
|
+
else if (parsedValue === 'false')
|
|
264
|
+
parsedValue = false;
|
|
265
|
+
else if (/^\d+$/.test(parsedValue))
|
|
266
|
+
parsedValue = parseInt(parsedValue, 10);
|
|
267
|
+
frontmatter[key] = parsedValue;
|
|
268
|
+
inArray = false;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Save final array if exists
|
|
273
|
+
if (inArray && currentKey && arrayValues.length > 0) {
|
|
274
|
+
frontmatter[currentKey] = arrayValues;
|
|
275
|
+
}
|
|
276
|
+
return frontmatter;
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Validate a glob pattern
|
|
284
|
+
*/
|
|
285
|
+
function validateGlobPattern(pattern, _projectRoot) {
|
|
286
|
+
// Check for common glob syntax errors
|
|
287
|
+
if (pattern.includes('[') && !pattern.includes(']')) {
|
|
288
|
+
return { valid: false, reason: 'Unclosed bracket' };
|
|
289
|
+
}
|
|
290
|
+
if (pattern.includes('{') && !pattern.includes('}')) {
|
|
291
|
+
return { valid: false, reason: 'Unclosed brace' };
|
|
292
|
+
}
|
|
293
|
+
// Check for overly broad patterns
|
|
294
|
+
if (pattern === '**' || pattern === '**/*') {
|
|
295
|
+
return { valid: true, warning: 'Pattern matches all files - consider being more specific' };
|
|
296
|
+
}
|
|
297
|
+
// Check for common mistakes
|
|
298
|
+
if (pattern.includes('***')) {
|
|
299
|
+
return { valid: false, reason: 'Invalid glob: ***' };
|
|
300
|
+
}
|
|
301
|
+
// Check for missing ** in deep patterns
|
|
302
|
+
if (/^[^*]+\/\*\.[a-z]+$/.test(pattern) && !pattern.includes('**')) {
|
|
303
|
+
return {
|
|
304
|
+
valid: true,
|
|
305
|
+
warning: `Pattern '${pattern}' only matches one level - use ** for recursive matching`,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
// Validate by trying to compile the pattern
|
|
309
|
+
try {
|
|
310
|
+
// Use os.tmpdir() for cross-platform compatibility (Windows support)
|
|
311
|
+
fast_glob_1.default.sync(pattern, { cwd: os.tmpdir(), onlyFiles: true });
|
|
312
|
+
return { valid: true };
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
return { valid: false, reason: 'Invalid glob syntax' };
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Extract @file references from content
|
|
320
|
+
*/
|
|
321
|
+
function extractFileReferences(content) {
|
|
322
|
+
const refs = [];
|
|
323
|
+
const regex = /@([a-zA-Z0-9_\-./]+)/g;
|
|
324
|
+
let match;
|
|
325
|
+
while ((match = regex.exec(content)) !== null) {
|
|
326
|
+
// Filter out common false positives
|
|
327
|
+
const ref = match[1];
|
|
328
|
+
if (!ref.includes('@') && !ref.startsWith('param') && !ref.startsWith('returns')) {
|
|
329
|
+
refs.push(ref);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return refs;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Extract markdown links from content
|
|
336
|
+
*/
|
|
337
|
+
function extractMarkdownLinks(content) {
|
|
338
|
+
const links = [];
|
|
339
|
+
// [text](url) style links
|
|
340
|
+
const linkRegex = /\[([^\]]*)\]\(([^)]+)\)/g;
|
|
341
|
+
let match;
|
|
342
|
+
while ((match = linkRegex.exec(content)) !== null) {
|
|
343
|
+
links.push(match[2]);
|
|
344
|
+
}
|
|
345
|
+
return links;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Check for best practices in generated content
|
|
349
|
+
*/
|
|
350
|
+
function checkBestPractices(output, analysis) {
|
|
351
|
+
const warnings = [];
|
|
352
|
+
const suggestions = [];
|
|
353
|
+
// Check rule coverage
|
|
354
|
+
const hasProjectIdentity = output.rules.some((r) => r.path.includes('project-identity') || r.content.includes('mission'));
|
|
355
|
+
if (!hasProjectIdentity) {
|
|
356
|
+
suggestions.push('Consider adding a project-identity rule with mission and tech stack');
|
|
357
|
+
}
|
|
358
|
+
const hasArchitectureMap = output.rules.some((r) => r.path.includes('architecture') || r.path.includes('structure'));
|
|
359
|
+
if (!hasArchitectureMap) {
|
|
360
|
+
suggestions.push('Consider adding an architecture-map rule with directory purposes');
|
|
361
|
+
}
|
|
362
|
+
const hasCommands = output.rules.some((r) => r.path.includes('command') || r.content.includes('npm run') || r.content.includes('yarn'));
|
|
363
|
+
if (!hasCommands && analysis.packageInfo?.scripts) {
|
|
364
|
+
suggestions.push('Consider adding a commands rule with available npm scripts');
|
|
365
|
+
}
|
|
366
|
+
// Check for language-specific rules
|
|
367
|
+
const primaryLanguages = analysis.languages.slice(0, 2).map((l) => l.name.toLowerCase());
|
|
368
|
+
for (const lang of primaryLanguages) {
|
|
369
|
+
const hasLangRule = output.rules.some((r) => r.path.toLowerCase().includes(lang) || r.content.toLowerCase().includes(`${lang} patterns`));
|
|
370
|
+
if (!hasLangRule) {
|
|
371
|
+
suggestions.push(`Consider adding ${lang}-specific coding patterns rule`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Check total rule count
|
|
375
|
+
if (output.rules.length < 3) {
|
|
376
|
+
warnings.push('Very few rules generated - consider adding more specific guidance');
|
|
377
|
+
}
|
|
378
|
+
else if (output.rules.length > 20) {
|
|
379
|
+
warnings.push('Many rules generated - LLMs may struggle with too many instructions');
|
|
380
|
+
}
|
|
381
|
+
// Check for token efficiency
|
|
382
|
+
const totalContent = (output.projectMd || '').length +
|
|
383
|
+
(output.architectureMd || '').length +
|
|
384
|
+
output.rules.reduce((sum, r) => sum + r.content.length, 0);
|
|
385
|
+
if (totalContent > 50000) {
|
|
386
|
+
warnings.push(`Total content is ${Math.round(totalContent / 1000)}KB - consider condensing for token efficiency`);
|
|
387
|
+
}
|
|
388
|
+
// Check for duplicate content
|
|
389
|
+
const ruleContents = output.rules.map((r) => r.content.toLowerCase());
|
|
390
|
+
for (let i = 0; i < ruleContents.length; i++) {
|
|
391
|
+
for (let j = i + 1; j < ruleContents.length; j++) {
|
|
392
|
+
const similarity = calculateSimilarity(ruleContents[i], ruleContents[j]);
|
|
393
|
+
if (similarity > 0.7) {
|
|
394
|
+
warnings.push(`Rules '${output.rules[i].path}' and '${output.rules[j].path}' have similar content (${Math.round(similarity * 100)}%)`);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return { warnings, suggestions };
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Calculate simple similarity between two strings
|
|
402
|
+
*/
|
|
403
|
+
function calculateSimilarity(a, b) {
|
|
404
|
+
const wordsA = new Set(a.split(/\s+/).filter((w) => w.length > 3));
|
|
405
|
+
const wordsB = new Set(b.split(/\s+/).filter((w) => w.length > 3));
|
|
406
|
+
if (wordsA.size === 0 || wordsB.size === 0)
|
|
407
|
+
return 0;
|
|
408
|
+
const intersection = new Set([...wordsA].filter((w) => wordsB.has(w)));
|
|
409
|
+
const union = new Set([...wordsA, ...wordsB]);
|
|
410
|
+
return intersection.size / union.size;
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/bootstrap/validator.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCH,0DAoDC;AArFD,uCAAyB;AACzB,uCAAyB;AACzB,2CAA6B;AAC7B,0DAA2B;AA2B3B;;GAEG;AACI,KAAK,UAAU,uBAAuB,CAC3C,MAA0B,EAC1B,WAAmB,EACnB,QAA0B;IAE1B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,sBAAsB;IACtB,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,MAAM,iBAAiB,GAAG,uBAAuB,CAC/C,MAAM,CAAC,SAAS,EAChB,YAAY,EACZ,WAAW,EACX,QAAQ,CACT,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,2BAA2B;IAC3B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,MAAM,cAAc,GAAG,uBAAuB,CAC5C,MAAM,CAAC,cAAc,EACrB,iBAAiB,EACjB,WAAW,EACX,QAAQ,CACT,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,iBAAiB;IACjB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;QACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC1C,WAAW,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;IAED,2BAA2B;IAC3B,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3D,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACzC,WAAW,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAE/C,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;QACN,QAAQ;QACR,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,OAAe,EACf,QAAgB,EAChB,WAAmB,EACnB,SAA2B;IAE3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAEhD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,4BAA4B;YAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC5C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,8BAA8B,GAAG,yBAAyB,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,KAAK,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,qBAAqB;QACrB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,SAAS;QACX,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;YAC9C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,8BAA8B,IAAI,GAAG,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,MAAM,cAAc,GAAG;QACrB,kBAAkB;QAClB,uBAAuB;QACvB,YAAY;QACZ,iBAAiB;QACjB,gBAAgB;KACjB,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,cAAc,EAAE,CAAC;QACpC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3C,QAAQ,CAAC,IAAI,CAAC,GAAG,QAAQ,8BAA8B,MAAM,sBAAsB,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,YAAY,CACzB,IAAuC,EACvC,WAAmB,EACnB,SAA2B;IAE3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,oBAAoB;IACpB,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,uCAAuC,CAAC,CAAC;QACjE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACzD,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,wCAAwC,CAAC,CAAC;IACpE,CAAC;SAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC;QAChD,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,cAAc,WAAW,CAAC,EAAE,oCAAoC,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,wCAAwC,CAAC,CAAC;IACtE,CAAC;IAED,iBAAiB;IACjB,IAAI,WAAW,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;YACrC,MAAM,cAAc,GAAG,mBAAmB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YAC9D,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,2BAA2B,IAAI,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;YACxF,CAAC;iBAAM,IAAI,cAAc,CAAC,OAAO,EAAE,CAAC;gBAClC,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,uBAAuB,IAAI,MAAM,cAAc,CAAC,OAAO,EAAE,CAAC,CAAC;YACvF,CAAC;YAED,kCAAkC;YAClC,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAE,EAAC,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACjF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,WAAW,IAAI,+BAA+B,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,wCAAwC,CAAC,CAAC;IACtE,CAAC;IAED,oBAAoB;IACpB,IAAI,WAAW,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACvC,IAAI,OAAO,WAAW,CAAC,QAAQ,KAAK,QAAQ,IAAI,WAAW,CAAC,QAAQ,GAAG,CAAC,IAAI,WAAW,CAAC,QAAQ,GAAG,GAAG,EAAE,CAAC;YACvG,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,+CAA+C,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,MAAM,iBAAiB,GAAG,uBAAuB,CAC/C,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,IAAI,EACT,WAAW,EACX,SAAS,CACV,CAAC;IACF,MAAM,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAE7C,wBAAwB;IACxB,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAEvE,IAAI,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,iCAAiC,WAAW,CAAC,MAAM,SAAS,CAAC,CAAC;IAC1F,CAAC;IAED,6BAA6B;IAC7B,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/C,IAAI,kBAAkB,GAAG,CAAC,CAAC;IAE3B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;YACxB,oCAAoC;YACpC,IAAI,2DAA2D,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9E,kBAAkB,EAAE,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,kBAAkB,GAAG,CAAC,EAAE,CAAC;QAC3B,WAAW,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,sFAAsF,CAAC,CAAC;IACvH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;QAC1B,MAAM;QACN,QAAQ;QACR,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,OAAe;IACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,WAAW,GAAoB,EAAE,CAAC;QAExC,qCAAqC;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,WAAW,GAAa,EAAE,CAAC;QAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAE5B,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;gBACtD,aAAa;gBACb,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;gBAClE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;iBAAM,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACjC,gCAAgC;gBAChC,IAAI,OAAO,IAAI,UAAU,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACnD,WAAuC,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC;oBACnE,WAAW,GAAG,EAAE,CAAC;oBACjB,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC;gBAED,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBACxC,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;gBAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBAEnD,IAAI,KAAK,KAAK,EAAE,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;oBACnD,8BAA8B;oBAC9B,UAAU,GAAG,GAAG,CAAC;oBACjB,OAAO,GAAG,IAAI,CAAC;oBACf,WAAW,GAAG,EAAE,CAAC;gBACnB,CAAC;qBAAM,CAAC;oBACN,eAAe;oBACf,UAAU,GAAG,GAAG,CAAC;oBACjB,IAAI,WAAW,GAA8B,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;oBAE/E,6BAA6B;oBAC7B,IAAI,WAAW,KAAK,MAAM;wBAAE,WAAW,GAAG,IAAyB,CAAC;yBAC/D,IAAI,WAAW,KAAK,OAAO;wBAAE,WAAW,GAAG,KAA0B,CAAC;yBACtE,IAAI,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;wBAAE,WAAW,GAAG,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAsB,CAAC;oBAEhG,WAAuC,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC;oBAC5D,OAAO,GAAG,KAAK,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QAED,6BAA6B;QAC7B,IAAI,OAAO,IAAI,UAAU,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnD,WAAuC,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC;QACrE,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAC1B,OAAe,EACf,YAAoB;IAEpB,sCAAsC;IACtC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACpD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;IACpD,CAAC;IAED,kCAAkC;IAClC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC3C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,0DAA0D,EAAE,CAAC;IAC9F,CAAC;IAED,4BAA4B;IAC5B,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvD,CAAC;IAED,wCAAwC;IACxC,IAAI,qBAAqB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnE,OAAO;YACL,KAAK,EAAE,IAAI;YACX,OAAO,EAAE,YAAY,OAAO,0DAA0D;SACvF,CAAC;IACJ,CAAC;IAED,4CAA4C;IAC5C,IAAI,CAAC;QACH,qEAAqE;QACrE,mBAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,qBAAqB,EAAE,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,OAAe;IAC5C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,uBAAuB,CAAC;IACtC,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9C,oCAAoC;QACpC,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACjF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,0BAA0B;IAC1B,MAAM,SAAS,GAAG,0BAA0B,CAAC;IAC7C,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAClD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,kBAAkB,CACzB,MAA0B,EAC1B,QAA0B;IAE1B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,sBAAsB;IACtB,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACjD,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CACrE,CAAC;IACF,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,WAAW,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACjD,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAChE,CAAC;IACF,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,WAAW,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;IACvF,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAC1F,CAAC;IACF,IAAI,CAAC,WAAW,IAAI,QAAQ,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;QAClD,WAAW,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IACjF,CAAC;IAED,oCAAoC;IACpC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACzF,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1C,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,IAAI,WAAW,CAAC,CAC5F,CAAC;QACF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,WAAW,CAAC,IAAI,CAAC,mBAAmB,IAAI,gCAAgC,CAAC,CAAC;QAC5E,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IACrF,CAAC;SAAM,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAC;IACvF,CAAC;IAED,6BAA6B;IAC7B,MAAM,YAAY,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM;QAClD,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,MAAM;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAE7D,IAAI,YAAY,GAAG,KAAK,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,+CAA+C,CAAC,CAAC;IACpH,CAAC;IAED,8BAA8B;IAC9B,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACjD,MAAM,UAAU,GAAG,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACzE,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,UAAU,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,2BAA2B,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YACzI,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB,CAAC,CAAS,EAAE,CAAS;IAC/C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnE,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IAE9C,OAAO,YAAY,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic File Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides safe file writing with:
|
|
5
|
+
* - Temp file → atomic rename pattern
|
|
6
|
+
* - Multi-file transactions (all-or-nothing)
|
|
7
|
+
* - Cleanup on error
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Pending file write in a transaction
|
|
11
|
+
*/
|
|
12
|
+
export interface PendingWrite {
|
|
13
|
+
/** Target file path */
|
|
14
|
+
targetPath: string;
|
|
15
|
+
/** Content to write */
|
|
16
|
+
content: string;
|
|
17
|
+
/** Temp file path (set during write) */
|
|
18
|
+
tempPath?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Transaction result
|
|
22
|
+
*/
|
|
23
|
+
export interface TransactionResult {
|
|
24
|
+
/** Whether all files were written successfully */
|
|
25
|
+
success: boolean;
|
|
26
|
+
/** Files that were successfully written */
|
|
27
|
+
writtenFiles: string[];
|
|
28
|
+
/** Errors encountered */
|
|
29
|
+
errors: Array<{
|
|
30
|
+
path: string;
|
|
31
|
+
error: Error;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Generate temp file path for atomic write
|
|
36
|
+
*
|
|
37
|
+
* @param targetPath - Target file path
|
|
38
|
+
* @returns Temp file path with pid suffix
|
|
39
|
+
*/
|
|
40
|
+
export declare function getTempPath(targetPath: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Write file atomically using temp file + rename
|
|
43
|
+
*
|
|
44
|
+
* @param targetPath - Target file path
|
|
45
|
+
* @param content - Content to write
|
|
46
|
+
* @throws Error if write or rename fails
|
|
47
|
+
*/
|
|
48
|
+
export declare function atomicWrite(targetPath: string, content: string): Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* Write file atomically (synchronous version)
|
|
51
|
+
*
|
|
52
|
+
* @param targetPath - Target file path
|
|
53
|
+
* @param content - Content to write
|
|
54
|
+
* @throws Error if write or rename fails
|
|
55
|
+
*/
|
|
56
|
+
export declare function atomicWriteSync(targetPath: string, content: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Execute a multi-file transaction (all-or-nothing)
|
|
59
|
+
*
|
|
60
|
+
* If any file fails to write, all temp files are cleaned up
|
|
61
|
+
* and no target files are modified.
|
|
62
|
+
*
|
|
63
|
+
* @param writes - Array of pending writes
|
|
64
|
+
* @returns Transaction result
|
|
65
|
+
*/
|
|
66
|
+
export declare function transaction(writes: PendingWrite[]): Promise<TransactionResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Cleanup stale temp files from a previous crashed build
|
|
69
|
+
*
|
|
70
|
+
* @param directory - Directory to scan for temp files
|
|
71
|
+
* @param pattern - Pattern to match temp files (default: *.tmp.*)
|
|
72
|
+
*/
|
|
73
|
+
export declare function cleanupStaleTempFiles(directory: string, pattern?: RegExp): Promise<string[]>;
|
|
74
|
+
//# sourceMappingURL=atomic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../../src/build/atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,yBAAyB;IACzB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;CAC/C;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAItD;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBpF;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAsBzE;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmEpF;AAiBD;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAsB,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB"}
|