@clawplays/ospec-cli 0.1.1
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/.ospec/templates/hooks/post-merge +8 -0
- package/.ospec/templates/hooks/pre-commit +8 -0
- package/LICENSE +21 -0
- package/README.md +549 -0
- package/README.zh-CN.md +549 -0
- package/assets/for-ai/en-US/ai-guide.md +98 -0
- package/assets/for-ai/en-US/execution-protocol.md +64 -0
- package/assets/for-ai/zh-CN/ai-guide.md +102 -0
- package/assets/for-ai/zh-CN/execution-protocol.md +68 -0
- package/assets/git-hooks/post-merge +12 -0
- package/assets/git-hooks/pre-commit +12 -0
- package/assets/global-skills/claude/ospec-change/SKILL.md +116 -0
- package/assets/global-skills/codex/ospec-change/SKILL.md +117 -0
- package/assets/global-skills/codex/ospec-change/agents/openai.yaml +7 -0
- package/assets/global-skills/codex/ospec-change/skill.yaml +19 -0
- package/assets/project-conventions/en-US/development-guide.md +32 -0
- package/assets/project-conventions/en-US/naming-conventions.md +51 -0
- package/assets/project-conventions/en-US/skill-conventions.md +40 -0
- package/assets/project-conventions/en-US/workflow-conventions.md +70 -0
- package/assets/project-conventions/zh-CN/development-guide.md +32 -0
- package/assets/project-conventions/zh-CN/naming-conventions.md +51 -0
- package/assets/project-conventions/zh-CN/skill-conventions.md +40 -0
- package/assets/project-conventions/zh-CN/workflow-conventions.md +74 -0
- package/dist/adapters/codex-stitch-adapter.js +420 -0
- package/dist/adapters/gemini-stitch-adapter.js +408 -0
- package/dist/adapters/playwright-checkpoint-adapter.js +2260 -0
- package/dist/advanced/BatchOperations.d.ts +36 -0
- package/dist/advanced/BatchOperations.js +159 -0
- package/dist/advanced/CachingLayer.d.ts +66 -0
- package/dist/advanced/CachingLayer.js +136 -0
- package/dist/advanced/FeatureUpdater.d.ts +46 -0
- package/dist/advanced/FeatureUpdater.js +151 -0
- package/dist/advanced/PerformanceMonitor.d.ts +52 -0
- package/dist/advanced/PerformanceMonitor.js +129 -0
- package/dist/advanced/StatePersistence.d.ts +61 -0
- package/dist/advanced/StatePersistence.js +168 -0
- package/dist/advanced/index.d.ts +14 -0
- package/dist/advanced/index.js +22 -0
- package/dist/cli/commands/config.d.ts +5 -0
- package/dist/cli/commands/config.js +6 -0
- package/dist/cli/commands/feature.d.ts +5 -0
- package/dist/cli/commands/feature.js +6 -0
- package/dist/cli/commands/index.d.ts +5 -0
- package/dist/cli/commands/index.js +6 -0
- package/dist/cli/commands/project.d.ts +5 -0
- package/dist/cli/commands/project.js +6 -0
- package/dist/cli/commands/validate.d.ts +5 -0
- package/dist/cli/commands/validate.js +6 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +6 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +1007 -0
- package/dist/commands/ArchiveCommand.d.ts +14 -0
- package/dist/commands/ArchiveCommand.js +241 -0
- package/dist/commands/BaseCommand.d.ts +33 -0
- package/dist/commands/BaseCommand.js +46 -0
- package/dist/commands/BatchCommand.d.ts +5 -0
- package/dist/commands/BatchCommand.js +42 -0
- package/dist/commands/ChangesCommand.d.ts +3 -0
- package/dist/commands/ChangesCommand.js +71 -0
- package/dist/commands/DocsCommand.d.ts +5 -0
- package/dist/commands/DocsCommand.js +118 -0
- package/dist/commands/FinalizeCommand.d.ts +3 -0
- package/dist/commands/FinalizeCommand.js +24 -0
- package/dist/commands/IndexCommand.d.ts +5 -0
- package/dist/commands/IndexCommand.js +57 -0
- package/dist/commands/InitCommand.d.ts +5 -0
- package/dist/commands/InitCommand.js +65 -0
- package/dist/commands/NewCommand.d.ts +11 -0
- package/dist/commands/NewCommand.js +262 -0
- package/dist/commands/PluginsCommand.d.ts +58 -0
- package/dist/commands/PluginsCommand.js +2491 -0
- package/dist/commands/ProgressCommand.d.ts +5 -0
- package/dist/commands/ProgressCommand.js +103 -0
- package/dist/commands/QueueCommand.d.ts +10 -0
- package/dist/commands/QueueCommand.js +147 -0
- package/dist/commands/RunCommand.d.ts +13 -0
- package/dist/commands/RunCommand.js +200 -0
- package/dist/commands/SkillCommand.d.ts +31 -0
- package/dist/commands/SkillCommand.js +1216 -0
- package/dist/commands/SkillsCommand.d.ts +5 -0
- package/dist/commands/SkillsCommand.js +68 -0
- package/dist/commands/StatusCommand.d.ts +6 -0
- package/dist/commands/StatusCommand.js +140 -0
- package/dist/commands/UpdateCommand.d.ts +8 -0
- package/dist/commands/UpdateCommand.js +251 -0
- package/dist/commands/VerifyCommand.d.ts +5 -0
- package/dist/commands/VerifyCommand.js +278 -0
- package/dist/commands/WorkflowCommand.d.ts +12 -0
- package/dist/commands/WorkflowCommand.js +150 -0
- package/dist/commands/index.d.ts +43 -0
- package/dist/commands/index.js +85 -0
- package/dist/core/constants.d.ts +41 -0
- package/dist/core/constants.js +73 -0
- package/dist/core/errors.d.ts +36 -0
- package/dist/core/errors.js +72 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/index.js +23 -0
- package/dist/core/types.d.ts +369 -0
- package/dist/core/types.js +3 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +27 -0
- package/dist/presets/ProjectPresets.d.ts +41 -0
- package/dist/presets/ProjectPresets.js +190 -0
- package/dist/scaffolds/ProjectScaffoldPresets.d.ts +20 -0
- package/dist/scaffolds/ProjectScaffoldPresets.js +151 -0
- package/dist/services/ConfigManager.d.ts +14 -0
- package/dist/services/ConfigManager.js +386 -0
- package/dist/services/FeatureManager.d.ts +5 -0
- package/dist/services/FeatureManager.js +6 -0
- package/dist/services/FileService.d.ts +21 -0
- package/dist/services/FileService.js +152 -0
- package/dist/services/IndexBuilder.d.ts +12 -0
- package/dist/services/IndexBuilder.js +130 -0
- package/dist/services/Logger.d.ts +20 -0
- package/dist/services/Logger.js +48 -0
- package/dist/services/ProjectAssetRegistry.d.ts +12 -0
- package/dist/services/ProjectAssetRegistry.js +96 -0
- package/dist/services/ProjectAssetService.d.ts +49 -0
- package/dist/services/ProjectAssetService.js +223 -0
- package/dist/services/ProjectScaffoldCommandService.d.ts +73 -0
- package/dist/services/ProjectScaffoldCommandService.js +159 -0
- package/dist/services/ProjectScaffoldService.d.ts +44 -0
- package/dist/services/ProjectScaffoldService.js +507 -0
- package/dist/services/ProjectService.d.ts +209 -0
- package/dist/services/ProjectService.js +13239 -0
- package/dist/services/QueueService.d.ts +17 -0
- package/dist/services/QueueService.js +142 -0
- package/dist/services/RunService.d.ts +40 -0
- package/dist/services/RunService.js +420 -0
- package/dist/services/SkillParser.d.ts +30 -0
- package/dist/services/SkillParser.js +88 -0
- package/dist/services/StateManager.d.ts +16 -0
- package/dist/services/StateManager.js +127 -0
- package/dist/services/TemplateEngine.d.ts +43 -0
- package/dist/services/TemplateEngine.js +119 -0
- package/dist/services/TemplateGenerator.d.ts +40 -0
- package/dist/services/TemplateGenerator.js +273 -0
- package/dist/services/ValidationService.d.ts +19 -0
- package/dist/services/ValidationService.js +44 -0
- package/dist/services/Validator.d.ts +5 -0
- package/dist/services/Validator.js +6 -0
- package/dist/services/index.d.ts +52 -0
- package/dist/services/index.js +91 -0
- package/dist/services/templates/ExecutionTemplateBuilder.d.ts +12 -0
- package/dist/services/templates/ExecutionTemplateBuilder.js +300 -0
- package/dist/services/templates/ProjectTemplateBuilder.d.ts +38 -0
- package/dist/services/templates/ProjectTemplateBuilder.js +1897 -0
- package/dist/services/templates/TemplateBuilderBase.d.ts +19 -0
- package/dist/services/templates/TemplateBuilderBase.js +60 -0
- package/dist/services/templates/TemplateInputFactory.d.ts +16 -0
- package/dist/services/templates/TemplateInputFactory.js +298 -0
- package/dist/services/templates/templateTypes.d.ts +90 -0
- package/dist/services/templates/templateTypes.js +3 -0
- package/dist/tools/build-index.js +632 -0
- package/dist/utils/DateUtils.d.ts +18 -0
- package/dist/utils/DateUtils.js +40 -0
- package/dist/utils/PathUtils.d.ts +9 -0
- package/dist/utils/PathUtils.js +66 -0
- package/dist/utils/StringUtils.d.ts +26 -0
- package/dist/utils/StringUtils.js +47 -0
- package/dist/utils/helpers.d.ts +5 -0
- package/dist/utils/helpers.js +6 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +23 -0
- package/dist/utils/logger.d.ts +5 -0
- package/dist/utils/logger.js +6 -0
- package/dist/utils/path.d.ts +5 -0
- package/dist/utils/path.js +6 -0
- package/dist/utils/subcommandHelp.d.ts +11 -0
- package/dist/utils/subcommandHelp.js +119 -0
- package/dist/workflow/ArchiveGate.d.ts +30 -0
- package/dist/workflow/ArchiveGate.js +93 -0
- package/dist/workflow/ConfigurableWorkflow.d.ts +89 -0
- package/dist/workflow/ConfigurableWorkflow.js +186 -0
- package/dist/workflow/HookSystem.d.ts +38 -0
- package/dist/workflow/HookSystem.js +66 -0
- package/dist/workflow/IndexRegenerator.d.ts +49 -0
- package/dist/workflow/IndexRegenerator.js +147 -0
- package/dist/workflow/PluginWorkflowComposer.d.ts +138 -0
- package/dist/workflow/PluginWorkflowComposer.js +239 -0
- package/dist/workflow/SkillUpdateEngine.d.ts +26 -0
- package/dist/workflow/SkillUpdateEngine.js +113 -0
- package/dist/workflow/VerificationSystem.d.ts +24 -0
- package/dist/workflow/VerificationSystem.js +116 -0
- package/dist/workflow/WorkflowEngine.d.ts +15 -0
- package/dist/workflow/WorkflowEngine.js +57 -0
- package/dist/workflow/index.d.ts +19 -0
- package/dist/workflow/index.js +32 -0
- package/package.json +78 -0
- package/scripts/postinstall.js +43 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FeatureProjectReference, TemplateDocumentLanguage } from './templateTypes';
|
|
2
|
+
type FrontmatterValue = string | number | boolean | string[];
|
|
3
|
+
export declare abstract class TemplateBuilderBase {
|
|
4
|
+
protected getCurrentDate(): string;
|
|
5
|
+
protected isEnglish(language: TemplateDocumentLanguage): boolean;
|
|
6
|
+
protected copy(language: TemplateDocumentLanguage, zh: string, en: string): string;
|
|
7
|
+
protected formatList(items: string[], emptyFallback: string): string;
|
|
8
|
+
protected formatChecklist(items: string[], emptyFallback: string): string;
|
|
9
|
+
protected formatLinkedList(items: Array<{
|
|
10
|
+
displayName: string;
|
|
11
|
+
path: string;
|
|
12
|
+
}>, emptyFallback: string): string;
|
|
13
|
+
protected formatReferenceList(items: FeatureProjectReference[], emptyFallback: string): string;
|
|
14
|
+
protected formatReferenceChecklist(items: FeatureProjectReference[], emptyFallback: string): string;
|
|
15
|
+
protected withFrontmatter(fields: Record<string, FrontmatterValue | undefined>, body: string): string;
|
|
16
|
+
private toYamlValue;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=TemplateBuilderBase.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateBuilderBase = void 0;
|
|
4
|
+
class TemplateBuilderBase {
|
|
5
|
+
getCurrentDate() {
|
|
6
|
+
return new Date().toISOString().slice(0, 10);
|
|
7
|
+
}
|
|
8
|
+
isEnglish(language) {
|
|
9
|
+
return language === 'en-US';
|
|
10
|
+
}
|
|
11
|
+
copy(language, zh, en) {
|
|
12
|
+
return this.isEnglish(language) ? en : zh;
|
|
13
|
+
}
|
|
14
|
+
formatList(items, emptyFallback) {
|
|
15
|
+
const normalized = items.map(item => item.trim()).filter(Boolean);
|
|
16
|
+
const source = normalized.length > 0 ? normalized : [emptyFallback];
|
|
17
|
+
return source.map(item => `- ${item}`).join('\n');
|
|
18
|
+
}
|
|
19
|
+
formatChecklist(items, emptyFallback) {
|
|
20
|
+
const normalized = items.map(item => item.trim()).filter(Boolean);
|
|
21
|
+
const source = normalized.length > 0 ? normalized : [emptyFallback];
|
|
22
|
+
return source.map(item => `- [ ] ${item}`).join('\n');
|
|
23
|
+
}
|
|
24
|
+
formatLinkedList(items, emptyFallback) {
|
|
25
|
+
if (items.length === 0) {
|
|
26
|
+
return `- ${emptyFallback}`;
|
|
27
|
+
}
|
|
28
|
+
return items.map(item => `- ${item.displayName}: \`${item.path}\``).join('\n');
|
|
29
|
+
}
|
|
30
|
+
formatReferenceList(items, emptyFallback) {
|
|
31
|
+
if (items.length === 0) {
|
|
32
|
+
return `- ${emptyFallback}`;
|
|
33
|
+
}
|
|
34
|
+
return items.map(item => `- ${item.title}: \`${item.path}\``).join('\n');
|
|
35
|
+
}
|
|
36
|
+
formatReferenceChecklist(items, emptyFallback) {
|
|
37
|
+
if (items.length === 0) {
|
|
38
|
+
return `- [ ] ${emptyFallback}`;
|
|
39
|
+
}
|
|
40
|
+
return items.map(item => `- [ ] ${item.path}`).join('\n');
|
|
41
|
+
}
|
|
42
|
+
withFrontmatter(fields, body) {
|
|
43
|
+
const frontmatter = Object.entries(fields)
|
|
44
|
+
.filter(([, value]) => value !== undefined)
|
|
45
|
+
.map(([key, value]) => `${key}: ${this.toYamlValue(value)}`)
|
|
46
|
+
.join('\n');
|
|
47
|
+
return `---\n${frontmatter}\n---\n\n${body.trim()}\n`;
|
|
48
|
+
}
|
|
49
|
+
toYamlValue(value) {
|
|
50
|
+
if (Array.isArray(value)) {
|
|
51
|
+
return `[${value.map(item => JSON.stringify(item)).join(', ')}]`;
|
|
52
|
+
}
|
|
53
|
+
if (typeof value === 'string') {
|
|
54
|
+
return /^[a-z0-9_.-]+$/i.test(value) ? value : JSON.stringify(value);
|
|
55
|
+
}
|
|
56
|
+
return String(value);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.TemplateBuilderBase = TemplateBuilderBase;
|
|
60
|
+
//# sourceMappingURL=TemplateBuilderBase.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ProjectMode } from '../../core/types';
|
|
2
|
+
import { FeatureTemplateInput, NormalizedFeatureTemplateInput, NormalizedProjectBootstrapInput, ProjectBootstrapInput } from './templateTypes';
|
|
3
|
+
export declare class TemplateInputFactory {
|
|
4
|
+
normalizeFeatureTemplateInput(input: string | FeatureTemplateInput): NormalizedFeatureTemplateInput;
|
|
5
|
+
normalizeProjectBootstrapInput(input: ProjectBootstrapInput | undefined, fallbackName: string, mode: ProjectMode, inferredDefaults?: Partial<ProjectBootstrapInput>, presetDefaults?: Partial<ProjectBootstrapInput>): NormalizedProjectBootstrapInput;
|
|
6
|
+
private normalizeFeatureProjectContext;
|
|
7
|
+
private normalizeDocumentLanguage;
|
|
8
|
+
private pickFieldKeys;
|
|
9
|
+
private isPlaceholderItem;
|
|
10
|
+
private slugify;
|
|
11
|
+
private normalizeModuleDisplayName;
|
|
12
|
+
private normalizeDocDisplayName;
|
|
13
|
+
private buildPlannedFiles;
|
|
14
|
+
private buildModuleApiPlans;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=TemplateInputFactory.d.ts.map
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateInputFactory = void 0;
|
|
4
|
+
const constants_1 = require("../../core/constants");
|
|
5
|
+
class TemplateInputFactory {
|
|
6
|
+
normalizeFeatureTemplateInput(input) {
|
|
7
|
+
const englishDefaults = {
|
|
8
|
+
background: 'Why is this change needed? What problem exists today?',
|
|
9
|
+
goals: ['What problem is solved after this change? What do users or developers gain?'],
|
|
10
|
+
inScope: ['TBD'],
|
|
11
|
+
outOfScope: ['TBD'],
|
|
12
|
+
acceptanceCriteria: ['Acceptance item 1', 'Acceptance item 2'],
|
|
13
|
+
};
|
|
14
|
+
if (typeof input === 'string') {
|
|
15
|
+
return {
|
|
16
|
+
feature: input,
|
|
17
|
+
mode: 'standard',
|
|
18
|
+
placement: 'active',
|
|
19
|
+
affects: [],
|
|
20
|
+
flags: [],
|
|
21
|
+
optionalSteps: [],
|
|
22
|
+
background: '为什么要做这个 change?当前存在哪些问题?',
|
|
23
|
+
goals: ['做完之后能解决什么问题?用户或开发者能得到什么?'],
|
|
24
|
+
inScope: ['待补充'],
|
|
25
|
+
outOfScope: ['待补充'],
|
|
26
|
+
acceptanceCriteria: ['条件一', '条件二'],
|
|
27
|
+
projectContext: this.normalizeFeatureProjectContext(),
|
|
28
|
+
documentLanguage: 'zh-CN',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const documentLanguage = this.normalizeDocumentLanguage(input.documentLanguage);
|
|
32
|
+
const normalized = {
|
|
33
|
+
feature: input.feature,
|
|
34
|
+
mode: input.mode ?? 'standard',
|
|
35
|
+
placement: input.placement === constants_1.DIR_NAMES.QUEUED ? constants_1.DIR_NAMES.QUEUED : constants_1.DIR_NAMES.ACTIVE,
|
|
36
|
+
affects: input.affects ?? [],
|
|
37
|
+
flags: input.flags ?? [],
|
|
38
|
+
optionalSteps: input.optionalSteps ?? [],
|
|
39
|
+
background: input.background?.trim() || '为什么要做这个 change?当前存在哪些问题?',
|
|
40
|
+
goals: input.goals?.map(item => item.trim()).filter(Boolean) ?? [
|
|
41
|
+
'做完之后能解决什么问题?用户或开发者能得到什么?',
|
|
42
|
+
],
|
|
43
|
+
inScope: input.inScope?.map(item => item.trim()).filter(Boolean) ?? ['待补充'],
|
|
44
|
+
outOfScope: input.outOfScope?.map(item => item.trim()).filter(Boolean) ?? ['待补充'],
|
|
45
|
+
acceptanceCriteria: input.acceptanceCriteria?.map(item => item.trim()).filter(Boolean) ?? [
|
|
46
|
+
'条件一',
|
|
47
|
+
'条件二',
|
|
48
|
+
],
|
|
49
|
+
projectContext: this.normalizeFeatureProjectContext(input.projectContext),
|
|
50
|
+
documentLanguage,
|
|
51
|
+
};
|
|
52
|
+
if (documentLanguage === 'en-US') {
|
|
53
|
+
if (!input.background?.trim()) {
|
|
54
|
+
normalized.background = englishDefaults.background;
|
|
55
|
+
}
|
|
56
|
+
if (!input.goals?.some(item => item.trim().length > 0)) {
|
|
57
|
+
normalized.goals = [...englishDefaults.goals];
|
|
58
|
+
}
|
|
59
|
+
if (!input.inScope?.some(item => item.trim().length > 0)) {
|
|
60
|
+
normalized.inScope = [...englishDefaults.inScope];
|
|
61
|
+
}
|
|
62
|
+
if (!input.outOfScope?.some(item => item.trim().length > 0)) {
|
|
63
|
+
normalized.outOfScope = [...englishDefaults.outOfScope];
|
|
64
|
+
}
|
|
65
|
+
if (!input.acceptanceCriteria?.some(item => item.trim().length > 0)) {
|
|
66
|
+
normalized.acceptanceCriteria = [...englishDefaults.acceptanceCriteria];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return normalized;
|
|
70
|
+
}
|
|
71
|
+
normalizeProjectBootstrapInput(input, fallbackName, mode, inferredDefaults, presetDefaults) {
|
|
72
|
+
const normalizedInputProjectName = input?.projectName?.trim();
|
|
73
|
+
const normalizedInputSummary = input?.summary?.trim();
|
|
74
|
+
const normalizedInputArchitecture = input?.architecture?.trim();
|
|
75
|
+
const normalizedInputTechStack = (input?.techStack ?? []).map(item => item.trim()).filter(Boolean);
|
|
76
|
+
const normalizedInputModules = (input?.modules ?? []).map(item => item.trim()).filter(Boolean);
|
|
77
|
+
const normalizedInputApiAreas = (input?.apiAreas ?? []).map(item => item.trim()).filter(Boolean);
|
|
78
|
+
const normalizedInputDesignDocs = (input?.designDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
79
|
+
const normalizedInputPlanningDocs = (input?.planningDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
80
|
+
const inferredTechStack = (inferredDefaults?.techStack ?? []).map(item => item.trim()).filter(Boolean);
|
|
81
|
+
const inferredModules = (inferredDefaults?.modules ?? []).map(item => item.trim()).filter(Boolean);
|
|
82
|
+
const inferredApiAreas = (inferredDefaults?.apiAreas ?? []).map(item => item.trim()).filter(Boolean);
|
|
83
|
+
const inferredDesignDocs = (inferredDefaults?.designDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
84
|
+
const inferredPlanningDocs = (inferredDefaults?.planningDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
85
|
+
const presetTechStack = (presetDefaults?.techStack ?? []).map(item => item.trim()).filter(Boolean);
|
|
86
|
+
const presetModules = (presetDefaults?.modules ?? []).map(item => item.trim()).filter(Boolean);
|
|
87
|
+
const presetApiAreas = (presetDefaults?.apiAreas ?? []).map(item => item.trim()).filter(Boolean);
|
|
88
|
+
const presetDesignDocs = (presetDefaults?.designDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
89
|
+
const presetPlanningDocs = (presetDefaults?.planningDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
90
|
+
const presetSummary = presetDefaults?.summary?.trim();
|
|
91
|
+
const presetArchitecture = presetDefaults?.architecture?.trim();
|
|
92
|
+
const projectName = normalizedInputProjectName || fallbackName;
|
|
93
|
+
const summary = normalizedInputSummary ||
|
|
94
|
+
presetSummary ||
|
|
95
|
+
`${fallbackName} 已通过 OSpec 初始化,当前处于项目知识层搭建阶段。`;
|
|
96
|
+
const techStack = normalizedInputTechStack.length > 0
|
|
97
|
+
? Array.from(new Set(normalizedInputTechStack))
|
|
98
|
+
: inferredTechStack.length > 0
|
|
99
|
+
? Array.from(new Set(inferredTechStack))
|
|
100
|
+
: presetTechStack.length > 0
|
|
101
|
+
? Array.from(new Set(presetTechStack))
|
|
102
|
+
: ['待补充'];
|
|
103
|
+
const architecture = normalizedInputArchitecture ||
|
|
104
|
+
presetArchitecture ||
|
|
105
|
+
'当前先建立项目知识层、分层技能层和执行层骨架,后续继续细化架构。';
|
|
106
|
+
const modules = normalizedInputModules.length > 0
|
|
107
|
+
? Array.from(new Set(normalizedInputModules))
|
|
108
|
+
: inferredModules.length > 0
|
|
109
|
+
? Array.from(new Set(inferredModules))
|
|
110
|
+
: presetModules.length > 0
|
|
111
|
+
? Array.from(new Set(presetModules))
|
|
112
|
+
: ['core', 'modules/<module>'];
|
|
113
|
+
const apiAreas = normalizedInputApiAreas.length > 0
|
|
114
|
+
? Array.from(new Set(normalizedInputApiAreas))
|
|
115
|
+
: inferredApiAreas.length > 0
|
|
116
|
+
? Array.from(new Set(inferredApiAreas))
|
|
117
|
+
: presetApiAreas.length > 0
|
|
118
|
+
? Array.from(new Set(presetApiAreas))
|
|
119
|
+
: ['待补充'];
|
|
120
|
+
const designDocs = normalizedInputDesignDocs.length > 0
|
|
121
|
+
? Array.from(new Set(normalizedInputDesignDocs))
|
|
122
|
+
: inferredDesignDocs.length > 0
|
|
123
|
+
? Array.from(new Set(inferredDesignDocs))
|
|
124
|
+
: presetDesignDocs.length > 0
|
|
125
|
+
? Array.from(new Set(presetDesignDocs))
|
|
126
|
+
: ['待补充'];
|
|
127
|
+
const planningDocs = normalizedInputPlanningDocs.length > 0
|
|
128
|
+
? Array.from(new Set(normalizedInputPlanningDocs))
|
|
129
|
+
: inferredPlanningDocs.length > 0
|
|
130
|
+
? Array.from(new Set(inferredPlanningDocs))
|
|
131
|
+
: presetPlanningDocs.length > 0
|
|
132
|
+
? Array.from(new Set(presetPlanningDocs))
|
|
133
|
+
: ['待补充'];
|
|
134
|
+
const documentLanguage = this.normalizeDocumentLanguage(input?.documentLanguage);
|
|
135
|
+
const executeScaffoldCommands = Boolean(input?.executeScaffoldCommands);
|
|
136
|
+
const fieldSources = {
|
|
137
|
+
projectName: normalizedInputProjectName ? 'user' : 'placeholder',
|
|
138
|
+
summary: normalizedInputSummary ? 'user' : presetSummary ? 'preset' : 'placeholder',
|
|
139
|
+
techStack: normalizedInputTechStack.length > 0
|
|
140
|
+
? 'user'
|
|
141
|
+
: inferredTechStack.length > 0
|
|
142
|
+
? 'inferred'
|
|
143
|
+
: presetTechStack.length > 0
|
|
144
|
+
? 'preset'
|
|
145
|
+
: 'placeholder',
|
|
146
|
+
architecture: normalizedInputArchitecture
|
|
147
|
+
? 'user'
|
|
148
|
+
: presetArchitecture
|
|
149
|
+
? 'preset'
|
|
150
|
+
: 'placeholder',
|
|
151
|
+
modules: normalizedInputModules.length > 0
|
|
152
|
+
? 'user'
|
|
153
|
+
: inferredModules.length > 0
|
|
154
|
+
? 'inferred'
|
|
155
|
+
: presetModules.length > 0
|
|
156
|
+
? 'preset'
|
|
157
|
+
: 'placeholder',
|
|
158
|
+
apiAreas: normalizedInputApiAreas.length > 0
|
|
159
|
+
? 'user'
|
|
160
|
+
: inferredApiAreas.length > 0
|
|
161
|
+
? 'inferred'
|
|
162
|
+
: presetApiAreas.length > 0
|
|
163
|
+
? 'preset'
|
|
164
|
+
: 'placeholder',
|
|
165
|
+
designDocs: normalizedInputDesignDocs.length > 0
|
|
166
|
+
? 'user'
|
|
167
|
+
: inferredDesignDocs.length > 0
|
|
168
|
+
? 'inferred'
|
|
169
|
+
: presetDesignDocs.length > 0
|
|
170
|
+
? 'preset'
|
|
171
|
+
: 'placeholder',
|
|
172
|
+
planningDocs: normalizedInputPlanningDocs.length > 0
|
|
173
|
+
? 'user'
|
|
174
|
+
: inferredPlanningDocs.length > 0
|
|
175
|
+
? 'inferred'
|
|
176
|
+
: presetPlanningDocs.length > 0
|
|
177
|
+
? 'preset'
|
|
178
|
+
: 'placeholder',
|
|
179
|
+
};
|
|
180
|
+
const userProvidedFields = this.pickFieldKeys(fieldSources, 'user');
|
|
181
|
+
const inferredFields = this.pickFieldKeys(fieldSources, 'inferred');
|
|
182
|
+
const placeholderFields = this.pickFieldKeys(fieldSources, 'placeholder');
|
|
183
|
+
const usedFallbacks = [...inferredFields, ...placeholderFields];
|
|
184
|
+
const modulePlans = this.buildPlannedFiles(modules, 'module', value => this.normalizeModuleDisplayName(value), slug => `${constants_1.DIR_NAMES.SRC}/${constants_1.DIR_NAMES.MODULES}/${slug}/${constants_1.FILE_NAMES.SKILL_MD}`, displayName => displayName.toLowerCase() === 'core');
|
|
185
|
+
const moduleApiPlans = this.buildModuleApiPlans(modulePlans);
|
|
186
|
+
const apiAreaPlans = this.buildPlannedFiles(apiAreas, 'api', value => this.normalizeDocDisplayName(value, constants_1.DIR_NAMES.API), slug => `${constants_1.DIR_NAMES.DOCS}/${constants_1.DIR_NAMES.API}/${slug}.md`);
|
|
187
|
+
const designDocPlans = this.buildPlannedFiles(designDocs, 'design', value => this.normalizeDocDisplayName(value, constants_1.DIR_NAMES.DESIGN), slug => `${constants_1.DIR_NAMES.DOCS}/${constants_1.DIR_NAMES.DESIGN}/${slug}.md`);
|
|
188
|
+
const planningDocPlans = this.buildPlannedFiles(planningDocs, 'plan', value => this.normalizeDocDisplayName(value, constants_1.DIR_NAMES.PLANNING), slug => `${constants_1.DIR_NAMES.DOCS}/${constants_1.DIR_NAMES.PLANNING}/${slug}.md`);
|
|
189
|
+
return {
|
|
190
|
+
projectPresetId: input?.projectPresetId ?? null,
|
|
191
|
+
projectName,
|
|
192
|
+
summary,
|
|
193
|
+
techStack,
|
|
194
|
+
architecture,
|
|
195
|
+
modules,
|
|
196
|
+
apiAreas,
|
|
197
|
+
designDocs,
|
|
198
|
+
planningDocs,
|
|
199
|
+
documentLanguage,
|
|
200
|
+
executeScaffoldCommands,
|
|
201
|
+
mode,
|
|
202
|
+
modulePlans,
|
|
203
|
+
moduleApiPlans,
|
|
204
|
+
apiAreaPlans,
|
|
205
|
+
designDocPlans,
|
|
206
|
+
planningDocPlans,
|
|
207
|
+
fieldSources,
|
|
208
|
+
usedFallbacks,
|
|
209
|
+
userProvidedFields,
|
|
210
|
+
inferredFields,
|
|
211
|
+
placeholderFields,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
normalizeFeatureProjectContext(context) {
|
|
215
|
+
return {
|
|
216
|
+
projectDocs: context?.projectDocs ?? [],
|
|
217
|
+
moduleSkills: context?.moduleSkills ?? [],
|
|
218
|
+
apiDocs: context?.apiDocs ?? [],
|
|
219
|
+
designDocs: context?.designDocs ?? [],
|
|
220
|
+
planningDocs: context?.planningDocs ?? [],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
normalizeDocumentLanguage(input) {
|
|
224
|
+
return input === 'en-US' ? 'en-US' : 'zh-CN';
|
|
225
|
+
}
|
|
226
|
+
pickFieldKeys(fieldSources, source) {
|
|
227
|
+
return Object.entries(fieldSources)
|
|
228
|
+
.filter(([, value]) => value === source)
|
|
229
|
+
.map(([key]) => key);
|
|
230
|
+
}
|
|
231
|
+
isPlaceholderItem(value) {
|
|
232
|
+
const normalized = value.trim().toLowerCase();
|
|
233
|
+
return (normalized.length === 0 ||
|
|
234
|
+
normalized === '待补充' ||
|
|
235
|
+
normalized === 'todo' ||
|
|
236
|
+
normalized === 'tbd' ||
|
|
237
|
+
normalized.includes('<') ||
|
|
238
|
+
normalized.includes('>'));
|
|
239
|
+
}
|
|
240
|
+
slugify(value) {
|
|
241
|
+
return value
|
|
242
|
+
.toLowerCase()
|
|
243
|
+
.replace(/\.md$/i, '')
|
|
244
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
245
|
+
.replace(/^-+|-+$/g, '');
|
|
246
|
+
}
|
|
247
|
+
normalizeModuleDisplayName(value) {
|
|
248
|
+
return value
|
|
249
|
+
.replace(/^src[\\/]+modules[\\/]+/i, '')
|
|
250
|
+
.replace(/^modules[\\/]+/i, '')
|
|
251
|
+
.replace(/[\\/]+/g, ' ')
|
|
252
|
+
.trim();
|
|
253
|
+
}
|
|
254
|
+
normalizeDocDisplayName(value, section) {
|
|
255
|
+
const normalizedSection = section.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
256
|
+
return value
|
|
257
|
+
.replace(new RegExp(`^docs[\\\\/]${normalizedSection}[\\\\/]`, 'i'), '')
|
|
258
|
+
.replace(/\.md$/i, '')
|
|
259
|
+
.replace(/[\\/]+/g, ' ')
|
|
260
|
+
.trim();
|
|
261
|
+
}
|
|
262
|
+
buildPlannedFiles(items, prefix, normalizeDisplayName, buildPath, shouldSkip) {
|
|
263
|
+
const plans = [];
|
|
264
|
+
const usedSlugs = new Set();
|
|
265
|
+
for (const item of items) {
|
|
266
|
+
const displayName = normalizeDisplayName(item);
|
|
267
|
+
if (!displayName || this.isPlaceholderItem(displayName) || shouldSkip?.(displayName)) {
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
const baseSlug = this.slugify(displayName) || prefix;
|
|
271
|
+
let slug = baseSlug;
|
|
272
|
+
let counter = 2;
|
|
273
|
+
while (usedSlugs.has(slug)) {
|
|
274
|
+
slug = `${baseSlug}-${counter}`;
|
|
275
|
+
counter += 1;
|
|
276
|
+
}
|
|
277
|
+
usedSlugs.add(slug);
|
|
278
|
+
const relativePath = buildPath(slug).replace(/\\/g, '/');
|
|
279
|
+
plans.push({
|
|
280
|
+
name: slug,
|
|
281
|
+
displayName,
|
|
282
|
+
fileName: relativePath.split('/').pop() || relativePath,
|
|
283
|
+
path: relativePath,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
return plans;
|
|
287
|
+
}
|
|
288
|
+
buildModuleApiPlans(modulePlans) {
|
|
289
|
+
return modulePlans.map(plan => ({
|
|
290
|
+
name: `module-${plan.name}`,
|
|
291
|
+
displayName: `${plan.displayName} module api`,
|
|
292
|
+
fileName: `module-${plan.name}.md`,
|
|
293
|
+
path: `${constants_1.DIR_NAMES.DOCS}/${constants_1.DIR_NAMES.API}/module-${plan.name}.md`,
|
|
294
|
+
}));
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
exports.TemplateInputFactory = TemplateInputFactory;
|
|
298
|
+
//# sourceMappingURL=TemplateInputFactory.js.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { ProjectMode } from '../../core/types';
|
|
2
|
+
import { ProjectPresetId } from '../../presets/ProjectPresets';
|
|
3
|
+
export type TemplateDocumentLanguage = 'zh-CN' | 'en-US';
|
|
4
|
+
export interface FeatureTemplateInput {
|
|
5
|
+
feature: string;
|
|
6
|
+
mode?: ProjectMode;
|
|
7
|
+
placement?: 'active' | 'queued';
|
|
8
|
+
affects?: string[];
|
|
9
|
+
flags?: string[];
|
|
10
|
+
optionalSteps?: string[];
|
|
11
|
+
background?: string;
|
|
12
|
+
goals?: string[];
|
|
13
|
+
inScope?: string[];
|
|
14
|
+
outOfScope?: string[];
|
|
15
|
+
acceptanceCriteria?: string[];
|
|
16
|
+
projectContext?: FeatureProjectContext;
|
|
17
|
+
documentLanguage?: TemplateDocumentLanguage;
|
|
18
|
+
}
|
|
19
|
+
export interface NormalizedFeatureTemplateInput {
|
|
20
|
+
feature: string;
|
|
21
|
+
mode: ProjectMode;
|
|
22
|
+
placement: 'active' | 'queued';
|
|
23
|
+
affects: string[];
|
|
24
|
+
flags: string[];
|
|
25
|
+
optionalSteps: string[];
|
|
26
|
+
background: string;
|
|
27
|
+
goals: string[];
|
|
28
|
+
inScope: string[];
|
|
29
|
+
outOfScope: string[];
|
|
30
|
+
acceptanceCriteria: string[];
|
|
31
|
+
projectContext: FeatureProjectContext;
|
|
32
|
+
documentLanguage: TemplateDocumentLanguage;
|
|
33
|
+
}
|
|
34
|
+
export interface FeatureProjectReference {
|
|
35
|
+
title: string;
|
|
36
|
+
path: string;
|
|
37
|
+
}
|
|
38
|
+
export interface FeatureProjectContext {
|
|
39
|
+
projectDocs?: FeatureProjectReference[];
|
|
40
|
+
moduleSkills?: FeatureProjectReference[];
|
|
41
|
+
apiDocs?: FeatureProjectReference[];
|
|
42
|
+
designDocs?: FeatureProjectReference[];
|
|
43
|
+
planningDocs?: FeatureProjectReference[];
|
|
44
|
+
}
|
|
45
|
+
export interface ProjectBootstrapInput {
|
|
46
|
+
projectPresetId?: ProjectPresetId | null;
|
|
47
|
+
projectName?: string;
|
|
48
|
+
summary?: string;
|
|
49
|
+
techStack?: string[];
|
|
50
|
+
architecture?: string;
|
|
51
|
+
modules?: string[];
|
|
52
|
+
apiAreas?: string[];
|
|
53
|
+
designDocs?: string[];
|
|
54
|
+
planningDocs?: string[];
|
|
55
|
+
documentLanguage?: TemplateDocumentLanguage;
|
|
56
|
+
executeScaffoldCommands?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export type BootstrapFieldKey = 'projectName' | 'summary' | 'techStack' | 'architecture' | 'modules' | 'apiAreas' | 'designDocs' | 'planningDocs';
|
|
59
|
+
export type BootstrapFieldSource = 'user' | 'inferred' | 'preset' | 'placeholder';
|
|
60
|
+
export interface PlannedProjectFile {
|
|
61
|
+
name: string;
|
|
62
|
+
displayName: string;
|
|
63
|
+
fileName: string;
|
|
64
|
+
path: string;
|
|
65
|
+
}
|
|
66
|
+
export interface NormalizedProjectBootstrapInput {
|
|
67
|
+
projectPresetId: ProjectPresetId | null;
|
|
68
|
+
projectName: string;
|
|
69
|
+
summary: string;
|
|
70
|
+
techStack: string[];
|
|
71
|
+
architecture: string;
|
|
72
|
+
modules: string[];
|
|
73
|
+
apiAreas: string[];
|
|
74
|
+
designDocs: string[];
|
|
75
|
+
planningDocs: string[];
|
|
76
|
+
documentLanguage: TemplateDocumentLanguage;
|
|
77
|
+
executeScaffoldCommands: boolean;
|
|
78
|
+
mode: ProjectMode;
|
|
79
|
+
modulePlans: PlannedProjectFile[];
|
|
80
|
+
moduleApiPlans: PlannedProjectFile[];
|
|
81
|
+
apiAreaPlans: PlannedProjectFile[];
|
|
82
|
+
designDocPlans: PlannedProjectFile[];
|
|
83
|
+
planningDocPlans: PlannedProjectFile[];
|
|
84
|
+
fieldSources: Record<BootstrapFieldKey, BootstrapFieldSource>;
|
|
85
|
+
usedFallbacks: BootstrapFieldKey[];
|
|
86
|
+
userProvidedFields: BootstrapFieldKey[];
|
|
87
|
+
inferredFields: BootstrapFieldKey[];
|
|
88
|
+
placeholderFields: BootstrapFieldKey[];
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=templateTypes.d.ts.map
|