@clawplays/ospec-cli 0.1.1 → 0.2.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/README.md +172 -488
- package/README.zh-CN.md +169 -485
- package/dist/cli.js +104 -8
- package/dist/commands/DocsCommand.js +3 -2
- package/dist/commands/InitCommand.js +69 -11
- package/dist/commands/SkillCommand.js +41 -19
- package/dist/commands/StatusCommand.js +27 -8
- package/dist/commands/UpdateCommand.js +19 -5
- package/dist/services/ProjectService.js +173 -359
- package/dist/services/templates/ProjectTemplateBuilder.js +4 -10
- package/dist/services/templates/TemplateInputFactory.js +14 -7
- package/dist/utils/subcommandHelp.js +5 -5
- package/package.json +9 -2
- package/scripts/postinstall.js +13 -7
|
@@ -2463,7 +2463,23 @@ class ProjectService {
|
|
|
2463
2463
|
|
|
2464
2464
|
|
|
2465
2465
|
|
|
2466
|
-
|
|
2466
|
+
let activeChangeCount = 0;
|
|
2467
|
+
if (structure.initialized) {
|
|
2468
|
+
const execution = await this.getExecutionStatus(rootDir);
|
|
2469
|
+
activeChangeCount = execution.totalActiveChanges;
|
|
2470
|
+
}
|
|
2471
|
+
else {
|
|
2472
|
+
const activeDir = path_1.default.join(rootDir, constants_1.DIR_NAMES.CHANGES, constants_1.DIR_NAMES.ACTIVE);
|
|
2473
|
+
if (await this.fileService.exists(activeDir)) {
|
|
2474
|
+
try {
|
|
2475
|
+
const entries = await fs_extra_1.default.readdir(activeDir, { withFileTypes: true });
|
|
2476
|
+
activeChangeCount = entries.filter(entry => entry.isDirectory()).length;
|
|
2477
|
+
}
|
|
2478
|
+
catch {
|
|
2479
|
+
activeChangeCount = 0;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2467
2483
|
|
|
2468
2484
|
|
|
2469
2485
|
|
|
@@ -2527,7 +2543,7 @@ class ProjectService {
|
|
|
2527
2543
|
|
|
2528
2544
|
|
|
2529
2545
|
|
|
2530
|
-
activeChangeCount
|
|
2546
|
+
activeChangeCount,
|
|
2531
2547
|
|
|
2532
2548
|
|
|
2533
2549
|
|
|
@@ -5114,413 +5130,211 @@ class ProjectService {
|
|
|
5114
5130
|
|
|
5115
5131
|
|
|
5116
5132
|
async getBootstrapUpgradePlan(rootDir) {
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
5133
|
const docsRoot = path_1.default.join(rootDir, constants_1.DIR_NAMES.DOCS, constants_1.DIR_NAMES.PROJECT);
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
5134
|
const readMarkdown = async (filePath) => {
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
5135
|
if (!(await this.fileService.exists(filePath))) {
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
5136
|
return '';
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
5137
|
}
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
5138
|
try {
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
5139
|
const parsed = (0, gray_matter_1.default)(await this.fileService.readFile(filePath));
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
5140
|
return parsed.content.trim();
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
5141
|
}
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
5142
|
catch {
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
5143
|
return '';
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
5144
|
}
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
5145
|
};
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
5146
|
const extractBulletList = (content) => content
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
5147
|
.split(/\r?\n/)
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
5148
|
.map(line => line.trim())
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
5149
|
.filter(line => /^-\s+/.test(line))
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
5150
|
.map(line => line.replace(/^-\s+/, '').trim())
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
|
|
5267
|
-
|
|
5268
5151
|
.filter(Boolean);
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
5152
|
const extractParagraph = (content) => content
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
5153
|
.split(/\r?\n\r?\n/)
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
5154
|
.map(block => block.trim())
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
5155
|
.find(block => block && !block.startsWith('#') && !block.startsWith('- '))
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5305
|
-
|
|
5306
|
-
|
|
5307
|
-
|
|
5308
5156
|
?.replace(/\r?\n/g, ' ')
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
|
|
5313
|
-
|
|
5314
|
-
|
|
5315
|
-
|
|
5316
5157
|
.trim() || '';
|
|
5317
|
-
|
|
5318
|
-
|
|
5319
|
-
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
const [overviewContent, techStackContent, architectureContent] = await Promise.all([
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5158
|
+
const [overviewContent, techStackContent, architectureContent, readmeContent, localizedReadmeContent, inferredSummary, inferredTechStack] = await Promise.all([
|
|
5332
5159
|
readMarkdown(path_1.default.join(docsRoot, 'overview.md')),
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
5160
|
readMarkdown(path_1.default.join(docsRoot, 'tech-stack.md')),
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
|
|
5347
|
-
|
|
5348
5161
|
readMarkdown(path_1.default.join(docsRoot, 'architecture.md')),
|
|
5349
|
-
|
|
5350
|
-
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5162
|
+
readMarkdown(path_1.default.join(rootDir, constants_1.FILE_NAMES.README)),
|
|
5163
|
+
readMarkdown(path_1.default.join(rootDir, 'README.zh-CN.md')),
|
|
5164
|
+
this.inferBootstrapSummary(rootDir),
|
|
5165
|
+
this.inferBootstrapTechStack(rootDir),
|
|
5166
|
+
]);
|
|
5167
|
+
const summary = extractParagraph(overviewContent) ||
|
|
5168
|
+
extractParagraph(readmeContent) ||
|
|
5169
|
+
extractParagraph(localizedReadmeContent) ||
|
|
5170
|
+
inferredSummary;
|
|
5171
|
+
const explicitTechStack = extractBulletList(techStackContent);
|
|
5172
|
+
const documentLanguage = this.detectDocumentLanguageFromTexts([
|
|
5173
|
+
overviewContent,
|
|
5174
|
+
techStackContent,
|
|
5175
|
+
architectureContent,
|
|
5176
|
+
readmeContent,
|
|
5177
|
+
localizedReadmeContent,
|
|
5356
5178
|
]);
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
5179
|
const modules = await this.inferBootstrapModules(rootDir);
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
5180
|
const apiDocs = await this.scanApiDocs(rootDir);
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
|
|
5377
|
-
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
5181
|
const designDocs = await this.scanDesignDocs(rootDir);
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
5182
|
const planningDocs = await this.scanPlanningDocs(rootDir);
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
5183
|
return {
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
5184
|
projectName: path_1.default.basename(path_1.default.resolve(rootDir)),
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
summary: extractParagraph(overviewContent),
|
|
5413
|
-
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
techStack: extractBulletList(techStackContent),
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5185
|
+
summary,
|
|
5186
|
+
techStack: explicitTechStack.length > 0 ? explicitTechStack : inferredTechStack,
|
|
5428
5187
|
architecture: extractParagraph(architectureContent),
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
5188
|
modules,
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
5189
|
apiAreas: apiDocs
|
|
5445
|
-
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
5190
|
.filter(item => item.name.toLowerCase() !== 'readme.md')
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
5191
|
.map(item => item.name.replace(/\.md$/i, '').replace(/-/g, ' ')),
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
5192
|
designDocs: designDocs
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
5193
|
.filter(item => item.name.toLowerCase() !== 'readme.md')
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
5194
|
.map(item => item.name.replace(/\.md$/i, '').replace(/-/g, ' ')),
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
5195
|
planningDocs: planningDocs
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
5196
|
.filter(item => item.name.toLowerCase() !== 'readme.md')
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
5197
|
.map(item => item.name.replace(/\.md$/i, '').replace(/-/g, ' ')),
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5198
|
+
documentLanguage,
|
|
5516
5199
|
};
|
|
5200
|
+
}
|
|
5517
5201
|
|
|
5202
|
+
async inferBootstrapSummary(rootDir) {
|
|
5203
|
+
const packageJsonPath = path_1.default.join(rootDir, 'package.json');
|
|
5204
|
+
if (await this.fileService.exists(packageJsonPath)) {
|
|
5205
|
+
try {
|
|
5206
|
+
const packageJson = await this.fileService.readJSON(packageJsonPath);
|
|
5207
|
+
if (typeof packageJson?.description === 'string' && packageJson.description.trim().length > 0) {
|
|
5208
|
+
return packageJson.description.trim();
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5211
|
+
catch {
|
|
5212
|
+
}
|
|
5213
|
+
}
|
|
5214
|
+
const pyprojectPath = path_1.default.join(rootDir, 'pyproject.toml');
|
|
5215
|
+
if (await this.fileService.exists(pyprojectPath)) {
|
|
5216
|
+
try {
|
|
5217
|
+
const content = await this.fileService.readFile(pyprojectPath);
|
|
5218
|
+
const match = content.match(/^\s*description\s*=\s*["'](.+?)["']\s*$/m);
|
|
5219
|
+
if (match?.[1]?.trim()) {
|
|
5220
|
+
return match[1].trim();
|
|
5221
|
+
}
|
|
5222
|
+
}
|
|
5223
|
+
catch {
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
return '';
|
|
5227
|
+
}
|
|
5518
5228
|
|
|
5229
|
+
async inferBootstrapTechStack(rootDir) {
|
|
5230
|
+
const stack = new Set();
|
|
5231
|
+
const add = (...items) => {
|
|
5232
|
+
for (const item of items) {
|
|
5233
|
+
if (typeof item === 'string' && item.trim().length > 0) {
|
|
5234
|
+
stack.add(item.trim());
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
};
|
|
5238
|
+
const packageJsonPath = path_1.default.join(rootDir, 'package.json');
|
|
5239
|
+
if (await this.fileService.exists(packageJsonPath)) {
|
|
5240
|
+
add('Node.js');
|
|
5241
|
+
try {
|
|
5242
|
+
const packageJson = await this.fileService.readJSON(packageJsonPath);
|
|
5243
|
+
const deps = {
|
|
5244
|
+
...(packageJson?.dependencies || {}),
|
|
5245
|
+
...(packageJson?.devDependencies || {}),
|
|
5246
|
+
...(packageJson?.peerDependencies || {}),
|
|
5247
|
+
};
|
|
5248
|
+
const depNames = Object.keys(deps);
|
|
5249
|
+
if (depNames.some(name => name === 'typescript' || name.startsWith('@types/'))) {
|
|
5250
|
+
add('TypeScript');
|
|
5251
|
+
}
|
|
5252
|
+
if (depNames.includes('react')) {
|
|
5253
|
+
add('React');
|
|
5254
|
+
}
|
|
5255
|
+
if (depNames.includes('next')) {
|
|
5256
|
+
add('Next.js');
|
|
5257
|
+
}
|
|
5258
|
+
if (depNames.includes('vue')) {
|
|
5259
|
+
add('Vue');
|
|
5260
|
+
}
|
|
5261
|
+
if (depNames.includes('nuxt') || depNames.includes('nuxt3')) {
|
|
5262
|
+
add('Nuxt');
|
|
5263
|
+
}
|
|
5264
|
+
if (depNames.includes('svelte')) {
|
|
5265
|
+
add('Svelte');
|
|
5266
|
+
}
|
|
5267
|
+
if (depNames.includes('astro')) {
|
|
5268
|
+
add('Astro');
|
|
5269
|
+
}
|
|
5270
|
+
if (depNames.includes('express')) {
|
|
5271
|
+
add('Express');
|
|
5272
|
+
}
|
|
5273
|
+
if (depNames.includes('@nestjs/core')) {
|
|
5274
|
+
add('NestJS');
|
|
5275
|
+
}
|
|
5276
|
+
if (depNames.includes('fastify')) {
|
|
5277
|
+
add('Fastify');
|
|
5278
|
+
}
|
|
5279
|
+
if (depNames.includes('electron')) {
|
|
5280
|
+
add('Electron');
|
|
5281
|
+
}
|
|
5282
|
+
if (depNames.includes('vite')) {
|
|
5283
|
+
add('Vite');
|
|
5284
|
+
}
|
|
5285
|
+
}
|
|
5286
|
+
catch {
|
|
5287
|
+
}
|
|
5288
|
+
}
|
|
5289
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'tsconfig.json'))) {
|
|
5290
|
+
add('TypeScript');
|
|
5291
|
+
}
|
|
5292
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'requirements.txt')) ||
|
|
5293
|
+
await this.fileService.exists(path_1.default.join(rootDir, 'pyproject.toml'))) {
|
|
5294
|
+
add('Python');
|
|
5295
|
+
}
|
|
5296
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'manage.py'))) {
|
|
5297
|
+
add('Django');
|
|
5298
|
+
}
|
|
5299
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'go.mod'))) {
|
|
5300
|
+
add('Go');
|
|
5301
|
+
}
|
|
5302
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'Cargo.toml'))) {
|
|
5303
|
+
add('Rust');
|
|
5304
|
+
}
|
|
5305
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'composer.json'))) {
|
|
5306
|
+
add('PHP');
|
|
5307
|
+
}
|
|
5308
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'Gemfile'))) {
|
|
5309
|
+
add('Ruby');
|
|
5310
|
+
}
|
|
5311
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'pom.xml')) ||
|
|
5312
|
+
await this.fileService.exists(path_1.default.join(rootDir, 'build.gradle')) ||
|
|
5313
|
+
await this.fileService.exists(path_1.default.join(rootDir, 'build.gradle.kts'))) {
|
|
5314
|
+
add('Java');
|
|
5315
|
+
}
|
|
5316
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'pubspec.yaml'))) {
|
|
5317
|
+
add('Dart');
|
|
5318
|
+
}
|
|
5319
|
+
if (await this.fileService.exists(path_1.default.join(rootDir, 'Dockerfile'))) {
|
|
5320
|
+
add('Docker');
|
|
5321
|
+
}
|
|
5322
|
+
return Array.from(stack);
|
|
5323
|
+
}
|
|
5519
5324
|
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5325
|
+
detectDocumentLanguageFromTexts(contents) {
|
|
5326
|
+
for (const content of contents) {
|
|
5327
|
+
if (typeof content !== 'string' || content.trim().length === 0) {
|
|
5328
|
+
continue;
|
|
5329
|
+
}
|
|
5330
|
+
if (/[一-龥]/.test(content)) {
|
|
5331
|
+
return 'zh-CN';
|
|
5332
|
+
}
|
|
5333
|
+
if (/[A-Za-z]/.test(content)) {
|
|
5334
|
+
return 'en-US';
|
|
5335
|
+
}
|
|
5336
|
+
}
|
|
5337
|
+
return undefined;
|
|
5524
5338
|
}
|
|
5525
5339
|
|
|
5526
5340
|
|
|
@@ -142,7 +142,6 @@ ${context.architecture}
|
|
|
142
142
|
## Navigation
|
|
143
143
|
|
|
144
144
|
- Project overview: [project/overview.md](project/overview.md)
|
|
145
|
-
- Bootstrap summary: [project/bootstrap-summary.md](project/bootstrap-summary.md)
|
|
146
145
|
- Tech stack: [project/tech-stack.md](project/tech-stack.md)
|
|
147
146
|
- Architecture: [project/architecture.md](project/architecture.md)
|
|
148
147
|
- Module map: [project/module-map.md](project/module-map.md)
|
|
@@ -157,7 +156,6 @@ ${context.architecture}
|
|
|
157
156
|
## 文档导航
|
|
158
157
|
|
|
159
158
|
- 项目概览:[project/overview.md](project/overview.md)
|
|
160
|
-
- 初始化摘要:[project/bootstrap-summary.md](project/bootstrap-summary.md)
|
|
161
159
|
- 技术栈:[project/tech-stack.md](project/tech-stack.md)
|
|
162
160
|
- 架构说明:[project/architecture.md](project/architecture.md)
|
|
163
161
|
- 模块地图:[project/module-map.md](project/module-map.md)
|
|
@@ -283,8 +281,7 @@ ${context.summary}
|
|
|
283
281
|
|
|
284
282
|
## Current Goals
|
|
285
283
|
|
|
286
|
-
-
|
|
287
|
-
- Use [bootstrap-summary.md](bootstrap-summary.md) as the recorded bootstrap output
|
|
284
|
+
- Keep the project knowledge docs aligned with the real repository state
|
|
288
285
|
- Establish layered skill files
|
|
289
286
|
- Manage delivery through the change workflow`
|
|
290
287
|
: `# 项目概览
|
|
@@ -299,8 +296,7 @@ ${context.summary}
|
|
|
299
296
|
|
|
300
297
|
## 当前目标
|
|
301
298
|
|
|
302
|
-
-
|
|
303
|
-
- 以 [bootstrap-summary.md](bootstrap-summary.md) 记录初始化结果与脚手架输出
|
|
299
|
+
- 保持项目知识文档与仓库真实状态一致
|
|
304
300
|
- 建立分层 SKILL 体系
|
|
305
301
|
- 使用 change workflow 管理需求交付`;
|
|
306
302
|
return this.withFrontmatter({
|
|
@@ -1008,11 +1004,9 @@ scan(rootDir)
|
|
|
1008
1004
|
const docsLink = this.formatReferenceList(refs, this.copy(context.documentLanguage, '待补充', 'TBD'));
|
|
1009
1005
|
const relatedDocs = this.isEnglish(context.documentLanguage)
|
|
1010
1006
|
? `- Module map: [../../../docs/project/module-map.md](../../../docs/project/module-map.md)
|
|
1011
|
-
- API overview: [../../../docs/project/api-overview.md](../../../docs/project/api-overview.md)
|
|
1012
|
-
- Bootstrap summary: [../../../docs/project/bootstrap-summary.md](../../../docs/project/bootstrap-summary.md)`
|
|
1007
|
+
- API overview: [../../../docs/project/api-overview.md](../../../docs/project/api-overview.md)`
|
|
1013
1008
|
: `- 项目模块地图:[../../../docs/project/module-map.md](../../../docs/project/module-map.md)
|
|
1014
|
-
- API 总览:[../../../docs/project/api-overview.md](../../../docs/project/api-overview.md)
|
|
1015
|
-
- 初始化摘要:[../../../docs/project/bootstrap-summary.md](../../../docs/project/bootstrap-summary.md)`;
|
|
1009
|
+
- API 总览:[../../../docs/project/api-overview.md](../../../docs/project/api-overview.md)`;
|
|
1016
1010
|
const templates = {
|
|
1017
1011
|
web: {
|
|
1018
1012
|
zh: `# ${moduleName} 模块
|
|
@@ -89,20 +89,28 @@ class TemplateInputFactory {
|
|
|
89
89
|
const presetPlanningDocs = (presetDefaults?.planningDocs ?? []).map(item => item.trim()).filter(Boolean);
|
|
90
90
|
const presetSummary = presetDefaults?.summary?.trim();
|
|
91
91
|
const presetArchitecture = presetDefaults?.architecture?.trim();
|
|
92
|
+
const documentLanguage = this.normalizeDocumentLanguage(input?.documentLanguage);
|
|
93
|
+
const placeholderText = documentLanguage === 'en-US' ? 'TBD' : '待补充';
|
|
94
|
+
const defaultSummary = documentLanguage === 'en-US'
|
|
95
|
+
? `${fallbackName} has been initialized with OSpec and is ready for change-based delivery. Fill in the missing project context as the repository becomes clearer.`
|
|
96
|
+
: `${fallbackName} 已通过 OSpec 初始化,当前已具备按 change 推进交付的基础条件。请继续补充缺失的项目上下文。`;
|
|
97
|
+
const defaultArchitecture = documentLanguage === 'en-US'
|
|
98
|
+
? 'OSpec initialized the protocol shell and baseline project knowledge docs. Refine the architecture details as the repository direction becomes clearer.'
|
|
99
|
+
: 'OSpec 已初始化协议壳和基础项目知识文档,后续可结合仓库实际方向继续细化架构。';
|
|
92
100
|
const projectName = normalizedInputProjectName || fallbackName;
|
|
93
101
|
const summary = normalizedInputSummary ||
|
|
94
102
|
presetSummary ||
|
|
95
|
-
|
|
103
|
+
defaultSummary;
|
|
96
104
|
const techStack = normalizedInputTechStack.length > 0
|
|
97
105
|
? Array.from(new Set(normalizedInputTechStack))
|
|
98
106
|
: inferredTechStack.length > 0
|
|
99
107
|
? Array.from(new Set(inferredTechStack))
|
|
100
108
|
: presetTechStack.length > 0
|
|
101
109
|
? Array.from(new Set(presetTechStack))
|
|
102
|
-
: [
|
|
110
|
+
: [placeholderText];
|
|
103
111
|
const architecture = normalizedInputArchitecture ||
|
|
104
112
|
presetArchitecture ||
|
|
105
|
-
|
|
113
|
+
defaultArchitecture;
|
|
106
114
|
const modules = normalizedInputModules.length > 0
|
|
107
115
|
? Array.from(new Set(normalizedInputModules))
|
|
108
116
|
: inferredModules.length > 0
|
|
@@ -116,22 +124,21 @@ class TemplateInputFactory {
|
|
|
116
124
|
? Array.from(new Set(inferredApiAreas))
|
|
117
125
|
: presetApiAreas.length > 0
|
|
118
126
|
? Array.from(new Set(presetApiAreas))
|
|
119
|
-
: [
|
|
127
|
+
: [placeholderText];
|
|
120
128
|
const designDocs = normalizedInputDesignDocs.length > 0
|
|
121
129
|
? Array.from(new Set(normalizedInputDesignDocs))
|
|
122
130
|
: inferredDesignDocs.length > 0
|
|
123
131
|
? Array.from(new Set(inferredDesignDocs))
|
|
124
132
|
: presetDesignDocs.length > 0
|
|
125
133
|
? Array.from(new Set(presetDesignDocs))
|
|
126
|
-
: [
|
|
134
|
+
: [placeholderText];
|
|
127
135
|
const planningDocs = normalizedInputPlanningDocs.length > 0
|
|
128
136
|
? Array.from(new Set(normalizedInputPlanningDocs))
|
|
129
137
|
: inferredPlanningDocs.length > 0
|
|
130
138
|
? Array.from(new Set(inferredPlanningDocs))
|
|
131
139
|
: presetPlanningDocs.length > 0
|
|
132
140
|
? Array.from(new Set(presetPlanningDocs))
|
|
133
|
-
: [
|
|
134
|
-
const documentLanguage = this.normalizeDocumentLanguage(input?.documentLanguage);
|
|
141
|
+
: [placeholderText];
|
|
135
142
|
const executeScaffoldCommands = Boolean(input?.executeScaffoldCommands);
|
|
136
143
|
const fieldSources = {
|
|
137
144
|
projectName: normalizedInputProjectName ? 'user' : 'placeholder',
|