Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/commands/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export class ChangeCommand {
} else {
console.error(`变更 "${changeName}" 存在问题`);
report.issues.forEach(issue => {
const label = issue.level === 'ERROR' ? 'ERROR' : 'WARNING';
const label = issue.level === 'ERROR' ? '错误' : '警告';
const prefix = issue.level === 'ERROR' ? '✗' : '⚠';
console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
});
Expand Down
2 changes: 1 addition & 1 deletion src/commands/spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ export function registerSpecCommand(rootProgram: typeof program) {
} else {
console.error(`规范 '${specId}' 存在问题`);
report.issues.forEach(issue => {
const label = issue.level === 'ERROR' ? 'ERROR' : issue.level;
const label = issue.level === 'ERROR' ? '错误' : issue.level === 'WARNING' ? '警告' : '信息';
const prefix = issue.level === 'ERROR' ? '✗' : issue.level === 'WARNING' ? '⚠' : 'ℹ';
console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
});
Expand Down
6 changes: 3 additions & 3 deletions src/commands/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ export class ValidateCommand {
} else {
console.error(`${type === 'change' ? '变更' : '规范'} '${id}' 存在问题`);
for (const issue of report.issues) {
const label = issue.level === 'ERROR' ? 'ERROR' : issue.level;
const label = issue.level === 'ERROR' ? '错误' : issue.level === 'WARNING' ? '警告' : '信息';
const prefix = issue.level === 'ERROR' ? '✗' : issue.level === 'WARNING' ? '⚠' : 'ℹ';
console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
}
Expand Down Expand Up @@ -247,14 +247,14 @@ export class ValidateCommand {
const currentIndex = index++;
const task = queue[currentIndex];
running++;
if (spinner) spinner.text = `Validating (${currentIndex + 1}/${queue.length})...`;
if (spinner) spinner.text = `正在验证 (${currentIndex + 1}/${queue.length})...`;
task()
.then(res => {
results.push(res);
if (res.valid) passed++; else failed++;
})
.catch((error: any) => {
const message = error?.message || 'Unknown error';
const message = error?.message || '未知错误';
const res: BulkItemResult = { id: getPlannedId(currentIndex, changeIds, specIds) ?? 'unknown', type: getPlannedType(currentIndex, changeIds, specIds) ?? 'change', valid: false, issues: [{ level: 'ERROR', path: 'file', message }], durationMs: 0 };
results.push(res);
failed++;
Expand Down
2 changes: 1 addition & 1 deletion src/commands/workflow/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function templatesCommand(options: TemplatesOptions): Promise<void>
return;
}

console.log(`Schema: ${schemaName}`);
console.log(`架构: ${schemaName}`);
console.log(`来源:${source}`);
console.log();

Expand Down
6 changes: 3 additions & 3 deletions src/core/artifact-graph/instruction-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export function loadTemplate(
const schemaDir = getSchemaDir(schemaName, projectRoot);
if (!schemaDir) {
throw new TemplateLoadError(
`Schema '${schemaName}' not found`,
`架构 '${schemaName}' 未找到`,
templatePath
);
}
Expand All @@ -141,7 +141,7 @@ export function loadTemplate(

if (!fs.existsSync(fullPath)) {
throw new TemplateLoadError(
`Template not found: ${fullPath}`,
`模板文件未找到:${fullPath}`,
fullPath
);
}
Expand All @@ -151,7 +151,7 @@ export function loadTemplate(
} catch (err) {
const ioError = err instanceof Error ? err : new Error(String(err));
throw new TemplateLoadError(
`Failed to read template: ${ioError.message}`,
`读取模板文件失败:${ioError.message}`,
fullPath
);
}
Expand Down
8 changes: 4 additions & 4 deletions src/core/artifact-graph/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function resolveSchema(name: string, projectRoot?: string): SchemaYaml {
if (!schemaDir) {
const availableSchemas = listSchemas(projectRoot);
throw new Error(
`Schema '${normalizedName}' not found. Available schemas: ${availableSchemas.join(', ')}`
`架构 '${normalizedName}' 未找到。可用架构:${availableSchemas.join(', ')}`
);
}

Expand All @@ -127,7 +127,7 @@ export function resolveSchema(name: string, projectRoot?: string): SchemaYaml {
} catch (err) {
const ioError = err instanceof Error ? err : new Error(String(err));
throw new SchemaLoadError(
`Failed to read schema at '${schemaPath}': ${ioError.message}`,
`读取架构文件失败 '${schemaPath}'${ioError.message}`,
schemaPath,
ioError
);
Expand All @@ -138,14 +138,14 @@ export function resolveSchema(name: string, projectRoot?: string): SchemaYaml {
} catch (err) {
if (err instanceof SchemaValidationError) {
throw new SchemaLoadError(
`Invalid schema at '${schemaPath}': ${err.message}`,
`架构文件无效 '${schemaPath}'${err.message}`,
schemaPath,
err
);
}
const parseError = err instanceof Error ? err : new Error(String(err));
throw new SchemaLoadError(
`Failed to parse schema at '${schemaPath}': ${parseError.message}`,
`解析架构文件失败 '${schemaPath}'${parseError.message}`,
schemaPath,
parseError
);
Expand Down
38 changes: 19 additions & 19 deletions src/core/project-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function readProjectConfig(projectRoot: string): ProjectConfig | null {
const raw = parseYaml(content);

if (!raw || typeof raw !== 'object') {
console.warn(`openspec/config.yaml is not a valid YAML object`);
console.warn(`openspec/config.yaml 不是有效的 YAML 对象`);
return null;
}

Expand All @@ -90,7 +90,7 @@ export function readProjectConfig(projectRoot: string): ProjectConfig | null {
if (schemaResult.success) {
config.schema = schemaResult.data;
} else if (raw.schema !== undefined) {
console.warn(`Invalid 'schema' field in config (must be non-empty string)`);
console.warn(`配置中的 'schema' 字段无效(必须是非空字符串)`);
}

// Parse context field with size limit
Expand All @@ -102,14 +102,14 @@ export function readProjectConfig(projectRoot: string): ProjectConfig | null {
const contextSize = Buffer.byteLength(contextResult.data, 'utf-8');
if (contextSize > MAX_CONTEXT_SIZE) {
console.warn(
`Context too large (${(contextSize / 1024).toFixed(1)}KB, limit: ${MAX_CONTEXT_SIZE / 1024}KB)`
`上下文过大(${(contextSize / 1024).toFixed(1)}KB,限制:${MAX_CONTEXT_SIZE / 1024}KB`
);
console.warn(`Ignoring context field`);
console.warn(`忽略 context 字段`);
} else {
config.context = contextResult.data;
}
} else {
console.warn(`Invalid 'context' field in config (must be string)`);
console.warn(`配置中的 'context' 字段无效(必须是字符串)`);
}
}

Expand All @@ -134,12 +134,12 @@ export function readProjectConfig(projectRoot: string): ProjectConfig | null {
}
if (validRules.length < rulesArrayResult.data.length) {
console.warn(
`Some rules for '${artifactId}' are empty strings, ignoring them`
`'${artifactId}' 的某些规则是空字符串,已忽略`
);
}
} else {
console.warn(
`Rules for '${artifactId}' must be an array of strings, ignoring this artifact's rules`
`'${artifactId}' 的规则必须是字符串数组,已忽略该产出物的规则`
);
}
}
Expand All @@ -148,14 +148,14 @@ export function readProjectConfig(projectRoot: string): ProjectConfig | null {
config.rules = parsedRules;
}
} else {
console.warn(`Invalid 'rules' field in config (must be object)`);
console.warn(`配置中的 'rules' 字段无效(必须是对象)`);
}
}

// Return partial config even if some fields failed
return Object.keys(config).length > 0 ? (config as ProjectConfig) : null;
} catch (error) {
console.warn(`Failed to parse openspec/config.yaml:`, error);
console.warn(`解析 openspec/config.yaml 失败:`, error);
return null;
}
}
Expand All @@ -181,8 +181,8 @@ export function validateConfigRules(
if (!validArtifactIds.has(artifactId)) {
const validIds = Array.from(validArtifactIds).sort().join(', ');
warnings.push(
`Unknown artifact ID in rules: "${artifactId}". ` +
`Valid IDs for schema "${schemaName}": ${validIds}`
`规则中存在未知的产出物 ID:"${artifactId}"` +
`架构 "${schemaName}" 的有效 ID:${validIds}`
);
}
}
Expand Down Expand Up @@ -237,28 +237,28 @@ export function suggestSchemas(
const builtIn = availableSchemas.filter((s) => s.isBuiltIn).map((s) => s.name);
const projectLocal = availableSchemas.filter((s) => !s.isBuiltIn).map((s) => s.name);

let message = `Schema '${invalidSchemaName}' not found in openspec/config.yaml\n\n`;
let message = `架构 '${invalidSchemaName}' openspec/config.yaml 中未找到\n\n`;

if (suggestions.length > 0) {
message += `Did you mean one of these?\n`;
message += `您是否想要其中之一?\n`;
suggestions.forEach((s) => {
const type = s.isBuiltIn ? 'built-in' : 'project-local';
const type = s.isBuiltIn ? '内置' : '项目本地';
message += ` - ${s.name} (${type})\n`;
});
message += '\n';
}

message += `Available schemas:\n`;
message += `可用架构:\n`;
if (builtIn.length > 0) {
message += ` Built-in: ${builtIn.join(', ')}\n`;
message += ` 内置:${builtIn.join(', ')}\n`;
}
if (projectLocal.length > 0) {
message += ` Project-local: ${projectLocal.join(', ')}\n`;
message += ` 项目本地:${projectLocal.join(', ')}\n`;
} else {
message += ` Project-local: (none found)\n`;
message += ` 项目本地:(未找到)\n`;
}

message += `\nFix: Edit openspec/config.yaml and change 'schema: ${invalidSchemaName}' to a valid schema name`;
message += `\n修复方法:编辑 openspec/config.yaml,将 'schema: ${invalidSchemaName}' 改为有效的架构名称`;

return message;
}
4 changes: 2 additions & 2 deletions test/commands/artifact-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ describe('artifact-workflow CLI commands', () => {
it('shows template paths for default schema', async () => {
const result = await runCLI(['templates'], { cwd: tempDir });
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain('Schema: spec-driven');
expect(result.stdout).toContain('架构: spec-driven');
expect(result.stdout).toContain('proposal:');
expect(result.stdout).toContain('design:');
expect(result.stdout).toContain('specs:');
Expand All @@ -300,7 +300,7 @@ describe('artifact-workflow CLI commands', () => {
it('shows template paths for specified schema', async () => {
const result = await runCLI(['templates', '--schema', 'spec-driven'], { cwd: tempDir });
expect(result.exitCode).toBe(0);
expect(result.stdout).toContain('Schema: spec-driven');
expect(result.stdout).toContain('架构: spec-driven');
expect(result.stdout).toContain('proposal:');
expect(result.stdout).toContain('design:');
});
Expand Down
4 changes: 2 additions & 2 deletions test/core/artifact-graph/instruction-loader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ rules:
generateInstructions(context, 'proposal', tempDir);

expect(consoleWarnSpy).toHaveBeenCalledWith(
expect.stringContaining('Unknown artifact ID in rules: "invalid-artifact"')
expect.stringContaining('规则中存在未知的产出物 ID:"invalid-artifact"')
);
});

Expand Down Expand Up @@ -475,7 +475,7 @@ rules:
// Note: We may have gotten warnings from other tests, so check that
// the count didn't increase by more than 1 from the first call
const callCount = consoleWarnSpy.mock.calls.filter(call =>
call[0]?.includes('Unknown artifact ID in rules')
call[0]?.includes('规则中存在未知的产出物 ID')
).length;

expect(callCount).toBeGreaterThanOrEqual(1);
Expand Down
4 changes: 2 additions & 2 deletions test/core/artifact-graph/resolver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ version: [[[invalid yaml
} catch (e) {
expect(e).toBeInstanceOf(SchemaLoadError);
const error = e as SchemaLoadError;
expect(error.message).toContain('Failed to parse');
expect(error.message).toContain('解析架构文件失败');
expect(error.message).toContain(schemaPath);
}
});
Expand All @@ -243,7 +243,7 @@ version: [[[invalid yaml
});

it('should throw when schema not found', () => {
expect(() => resolveSchema('nonexistent-schema')).toThrow(/not found/);
expect(() => resolveSchema('nonexistent-schema')).toThrow(/未找到/);
});

it('should list available schemas in error message', () => {
Expand Down
Loading