speccore 8.3.333 → 8.3.341
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/.agents/skills/spec-ask/SKILL.md +4 -0
- package/.agents/skills/spec-unitize/SKILL.md +9 -1
- package/.agents/skills/speccore-router/SKILL.md +12 -11
- package/README.en.md +3 -11
- package/README.md +3 -13
- package/dist/cli.js +64 -206
- package/dist/cli.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +530 -481
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +6 -0
- package/dist/commands/ask.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +9 -7
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/doc2spec.d.ts +44 -1
- package/dist/commands/doc2spec.d.ts.map +1 -1
- package/dist/commands/doc2spec.js +257 -5
- package/dist/commands/doc2spec.js.map +1 -1
- package/dist/commands/doctor.js +3 -3
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/done.js +1 -5
- package/dist/commands/done.js.map +1 -1
- package/dist/commands/execute.js +118 -66
- package/dist/commands/execute.js.map +1 -1
- package/dist/commands/help.js +6 -54
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +71 -47
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/iteration/create.d.ts.map +1 -1
- package/dist/commands/iteration/create.js +72 -10
- package/dist/commands/iteration/create.js.map +1 -1
- package/dist/commands/iteration/taskify.d.ts.map +1 -1
- package/dist/commands/iteration/taskify.js +133 -35
- package/dist/commands/iteration/taskify.js.map +1 -1
- package/dist/commands/pr.d.ts.map +1 -1
- package/dist/commands/pr.js +24 -2
- package/dist/commands/pr.js.map +1 -1
- package/dist/commands/prompts.d.ts +6 -0
- package/dist/commands/prompts.d.ts.map +1 -1
- package/dist/commands/prompts.js +19 -10
- package/dist/commands/prompts.js.map +1 -1
- package/dist/commands/search.js +1 -1
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/status-panel.d.ts.map +1 -1
- package/dist/commands/status-panel.js +23 -34
- package/dist/commands/status-panel.js.map +1 -1
- package/dist/commands/unitize.d.ts +3 -0
- package/dist/commands/unitize.d.ts.map +1 -1
- package/dist/commands/unitize.js +32 -9
- package/dist/commands/unitize.js.map +1 -1
- package/dist/commands/update-env-configs.d.ts.map +1 -1
- package/dist/commands/update-env-configs.js +2 -1
- package/dist/commands/update-env-configs.js.map +1 -1
- package/dist/commands/update.d.ts +4 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +41 -1
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/welcome.d.ts.map +1 -1
- package/dist/commands/welcome.js +41 -0
- package/dist/commands/welcome.js.map +1 -1
- package/dist/core/analyze-engine.js +3 -3
- package/dist/core/analyze-engine.js.map +1 -1
- package/dist/core/arbitration/l3-human-arbiter.js +1 -1
- package/dist/core/arbitration/l3-human-arbiter.js.map +1 -1
- package/dist/core/arbitration/verdict-generator.js +1 -1
- package/dist/core/arbitration/verdict-generator.js.map +1 -1
- package/dist/core/ask-context.d.ts.map +1 -1
- package/dist/core/ask-context.js +14 -3
- package/dist/core/ask-context.js.map +1 -1
- package/dist/core/ask-engine.d.ts.map +1 -1
- package/dist/core/ask-engine.js +55 -49
- package/dist/core/ask-engine.js.map +1 -1
- package/dist/core/code-graph/reporter.d.ts.map +1 -1
- package/dist/core/code-graph/reporter.js +3 -12
- package/dist/core/code-graph/reporter.js.map +1 -1
- package/dist/core/code-graph/requirement-linker.js +1 -1
- package/dist/core/code-graph/requirement-linker.js.map +1 -1
- package/dist/core/code-scanner.js +1 -1
- package/dist/core/code-scanner.js.map +1 -1
- package/dist/core/deploy/engine.d.ts.map +1 -1
- package/dist/core/deploy/engine.js +58 -44
- package/dist/core/deploy/engine.js.map +1 -1
- package/dist/core/environment-config.d.ts +13 -0
- package/dist/core/environment-config.d.ts.map +1 -1
- package/dist/core/environment-config.js +28 -1
- package/dist/core/environment-config.js.map +1 -1
- package/dist/core/error-diagnosis.js +2 -2
- package/dist/core/error-diagnosis.js.map +1 -1
- package/dist/core/git-integration.d.ts +5 -7
- package/dist/core/git-integration.d.ts.map +1 -1
- package/dist/core/git-integration.js +137 -12
- package/dist/core/git-integration.js.map +1 -1
- package/dist/core/global-knowledge.d.ts.map +1 -1
- package/dist/core/global-knowledge.js +25 -11
- package/dist/core/global-knowledge.js.map +1 -1
- package/dist/core/handoff-generator.d.ts.map +1 -1
- package/dist/core/handoff-generator.js +3 -1
- package/dist/core/handoff-generator.js.map +1 -1
- package/dist/core/index-guard.d.ts.map +1 -1
- package/dist/core/index-guard.js +4 -26
- package/dist/core/index-guard.js.map +1 -1
- package/dist/core/intent-recognition.d.ts +1 -1
- package/dist/core/intent-recognition.d.ts.map +1 -1
- package/dist/core/intent-recognition.js +68 -68
- package/dist/core/intent-recognition.js.map +1 -1
- package/dist/core/knowledge-graph.d.ts.map +1 -1
- package/dist/core/knowledge-graph.js +6 -4
- package/dist/core/knowledge-graph.js.map +1 -1
- package/dist/core/name-validator.d.ts.map +1 -1
- package/dist/core/name-validator.js +41 -20
- package/dist/core/name-validator.js.map +1 -1
- package/dist/core/pinyin-initials.d.ts +10 -0
- package/dist/core/pinyin-initials.d.ts.map +1 -0
- package/dist/core/pinyin-initials.js +44 -0
- package/dist/core/pinyin-initials.js.map +1 -0
- package/dist/core/prompt-builder.js +1 -1
- package/dist/core/prompt-builder.js.map +1 -1
- package/dist/core/prompt-plugins/analyze-graph-plugin.js +1 -1
- package/dist/core/prompt-plugins/analyze-graph-plugin.js.map +1 -1
- package/dist/core/reindex-engine.js +4 -4
- package/dist/core/reindex-engine.js.map +1 -1
- package/dist/core/skeleton-residue.d.ts +13 -0
- package/dist/core/skeleton-residue.d.ts.map +1 -1
- package/dist/core/skeleton-residue.js +83 -14
- package/dist/core/skeleton-residue.js.map +1 -1
- package/dist/core/spec-merger.d.ts.map +1 -1
- package/dist/core/spec-merger.js +3 -2
- package/dist/core/spec-merger.js.map +1 -1
- package/dist/core/state.d.ts +10 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/state.js +20 -1
- package/dist/core/state.js.map +1 -1
- package/dist/core/structured-extractor.d.ts +6 -0
- package/dist/core/structured-extractor.d.ts.map +1 -1
- package/dist/core/structured-extractor.js +6 -0
- package/dist/core/structured-extractor.js.map +1 -1
- package/dist/core/task-paths.d.ts +12 -0
- package/dist/core/task-paths.d.ts.map +1 -1
- package/dist/core/task-paths.js +33 -1
- package/dist/core/task-paths.js.map +1 -1
- package/dist/core/unified-config.d.ts +7 -1
- package/dist/core/unified-config.d.ts.map +1 -1
- package/dist/core/unified-config.js +70 -21
- package/dist/core/unified-config.js.map +1 -1
- package/dist/core/unit-staffing.d.ts +21 -4
- package/dist/core/unit-staffing.d.ts.map +1 -1
- package/dist/core/unit-staffing.js +59 -12
- package/dist/core/unit-staffing.js.map +1 -1
- package/dist/core/usage-analytics.js +1 -1
- package/dist/core/usage-analytics.js.map +1 -1
- package/dist/core/validator.d.ts.map +1 -1
- package/dist/core/validator.js +45 -5
- package/dist/core/validator.js.map +1 -1
- package/dist/core/verify-report-aggregator.d.ts.map +1 -1
- package/dist/core/verify-report-aggregator.js +19 -2
- package/dist/core/verify-report-aggregator.js.map +1 -1
- package/dist/utils/task-utils.d.ts +4 -1
- package/dist/utils/task-utils.d.ts.map +1 -1
- package/dist/utils/task-utils.js +30 -4
- package/dist/utils/task-utils.js.map +1 -1
- package/package.json +4 -3
- package/templates/deploy-examples.yaml +33 -5
- package/templates/html/speccore-ask-explain.html +1 -1
- package/templates/html/speccore-ask-guide.html +1 -1
- package/templates/html/speccore-ask-match.html +1 -1
- package/templates/html/speccore-ask-pipeline.html +1 -1
- package/templates/html/speccore-ask-result.html +1 -1
- package/templates/html/speccore-help.html +2 -2
- package/templates/speccore-yml-example.yml +174 -54
- package/templates/verify-spec-example.yaml +66 -1
- package/dist/commands/audit.d.ts +0 -12
- package/dist/commands/audit.d.ts.map +0 -1
- package/dist/commands/audit.js +0 -540
- package/dist/commands/audit.js.map +0 -1
- package/dist/commands/backup.d.ts +0 -18
- package/dist/commands/backup.d.ts.map +0 -1
- package/dist/commands/backup.js +0 -102
- package/dist/commands/backup.js.map +0 -1
- package/dist/commands/baseline.d.ts +0 -13
- package/dist/commands/baseline.d.ts.map +0 -1
- package/dist/commands/baseline.js +0 -227
- package/dist/commands/baseline.js.map +0 -1
- package/dist/commands/chain.d.ts +0 -55
- package/dist/commands/chain.d.ts.map +0 -1
- package/dist/commands/chain.js +0 -501
- package/dist/commands/chain.js.map +0 -1
- package/dist/commands/clarify.d.ts +0 -17
- package/dist/commands/clarify.d.ts.map +0 -1
- package/dist/commands/clarify.js +0 -351
- package/dist/commands/clarify.js.map +0 -1
- package/dist/commands/code-index.d.ts +0 -21
- package/dist/commands/code-index.d.ts.map +0 -1
- package/dist/commands/code-index.js +0 -193
- package/dist/commands/code-index.js.map +0 -1
- package/dist/commands/context.d.ts +0 -10
- package/dist/commands/context.d.ts.map +0 -1
- package/dist/commands/context.js +0 -213
- package/dist/commands/context.js.map +0 -1
- package/dist/commands/current.d.ts +0 -10
- package/dist/commands/current.d.ts.map +0 -1
- package/dist/commands/current.js +0 -53
- package/dist/commands/current.js.map +0 -1
- package/dist/commands/dev.d.ts +0 -18
- package/dist/commands/dev.d.ts.map +0 -1
- package/dist/commands/dev.js +0 -854
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/diff.d.ts +0 -10
- package/dist/commands/diff.d.ts.map +0 -1
- package/dist/commands/diff.js +0 -160
- package/dist/commands/diff.js.map +0 -1
- package/dist/commands/global-status.d.ts +0 -9
- package/dist/commands/global-status.d.ts.map +0 -1
- package/dist/commands/global-status.js +0 -135
- package/dist/commands/global-status.js.map +0 -1
- package/dist/commands/graph.d.ts +0 -25
- package/dist/commands/graph.d.ts.map +0 -1
- package/dist/commands/graph.js +0 -523
- package/dist/commands/graph.js.map +0 -1
- package/dist/commands/handover.d.ts +0 -11
- package/dist/commands/handover.d.ts.map +0 -1
- package/dist/commands/handover.js +0 -170
- package/dist/commands/handover.js.map +0 -1
- package/dist/commands/health.d.ts +0 -7
- package/dist/commands/health.d.ts.map +0 -1
- package/dist/commands/health.js +0 -80
- package/dist/commands/health.js.map +0 -1
- package/dist/commands/history.d.ts +0 -9
- package/dist/commands/history.d.ts.map +0 -1
- package/dist/commands/history.js +0 -117
- package/dist/commands/history.js.map +0 -1
- package/dist/commands/impact.d.ts +0 -12
- package/dist/commands/impact.d.ts.map +0 -1
- package/dist/commands/impact.js +0 -238
- package/dist/commands/impact.js.map +0 -1
- package/dist/commands/import.d.ts +0 -19
- package/dist/commands/import.d.ts.map +0 -1
- package/dist/commands/import.js +0 -673
- package/dist/commands/import.js.map +0 -1
- package/dist/commands/knowledge.d.ts +0 -6
- package/dist/commands/knowledge.d.ts.map +0 -1
- package/dist/commands/knowledge.js +0 -94
- package/dist/commands/knowledge.js.map +0 -1
- package/dist/commands/lifecycle.d.ts +0 -9
- package/dist/commands/lifecycle.d.ts.map +0 -1
- package/dist/commands/lifecycle.js +0 -288
- package/dist/commands/lifecycle.js.map +0 -1
- package/dist/commands/merge-check.d.ts +0 -10
- package/dist/commands/merge-check.d.ts.map +0 -1
- package/dist/commands/merge-check.js +0 -183
- package/dist/commands/merge-check.js.map +0 -1
- package/dist/commands/notify.d.ts +0 -13
- package/dist/commands/notify.d.ts.map +0 -1
- package/dist/commands/notify.js +0 -63
- package/dist/commands/notify.js.map +0 -1
- package/dist/commands/rag-index.d.ts +0 -19
- package/dist/commands/rag-index.d.ts.map +0 -1
- package/dist/commands/rag-index.js +0 -286
- package/dist/commands/rag-index.js.map +0 -1
- package/dist/commands/recommend.d.ts +0 -13
- package/dist/commands/recommend.d.ts.map +0 -1
- package/dist/commands/recommend.js +0 -37
- package/dist/commands/recommend.js.map +0 -1
- package/dist/commands/refresh.d.ts +0 -21
- package/dist/commands/refresh.d.ts.map +0 -1
- package/dist/commands/refresh.js +0 -211
- package/dist/commands/refresh.js.map +0 -1
- package/dist/commands/rollback.d.ts +0 -8
- package/dist/commands/rollback.d.ts.map +0 -1
- package/dist/commands/rollback.js +0 -113
- package/dist/commands/rollback.js.map +0 -1
- package/dist/commands/status.d.ts +0 -7
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -262
- package/dist/commands/status.js.map +0 -1
- package/dist/commands/trace.d.ts +0 -12
- package/dist/commands/trace.d.ts.map +0 -1
- package/dist/commands/trace.js +0 -163
- package/dist/commands/trace.js.map +0 -1
- package/dist/commands/tracker.d.ts +0 -2
- package/dist/commands/tracker.d.ts.map +0 -1
- package/dist/commands/tracker.js +0 -28
- package/dist/commands/tracker.js.map +0 -1
- package/dist/commands/verdict.d.ts +0 -16
- package/dist/commands/verdict.d.ts.map +0 -1
- package/dist/commands/verdict.js +0 -189
- package/dist/commands/verdict.js.map +0 -1
- package/dist/commands/workspace.d.ts +0 -20
- package/dist/commands/workspace.d.ts.map +0 -1
- package/dist/commands/workspace.js +0 -142
- package/dist/commands/workspace.js.map +0 -1
- package/dist/core/constraint-set.d.ts +0 -67
- package/dist/core/constraint-set.d.ts.map +0 -1
- package/dist/core/constraint-set.js +0 -151
- package/dist/core/constraint-set.js.map +0 -1
- package/dist/core/smart-recommend.d.ts +0 -16
- package/dist/core/smart-recommend.d.ts.map +0 -1
- package/dist/core/smart-recommend.js +0 -149
- package/dist/core/smart-recommend.js.map +0 -1
- package/dist/core/task-type-registry.d.ts +0 -110
- package/dist/core/task-type-registry.d.ts.map +0 -1
- package/dist/core/task-type-registry.js +0 -334
- package/dist/core/task-type-registry.js.map +0 -1
- package/dist/utils/mermaid-render.d.ts +0 -39
- package/dist/utils/mermaid-render.d.ts.map +0 -1
- package/dist/utils/mermaid-render.js +0 -284
- package/dist/utils/mermaid-render.js.map +0 -1
|
@@ -48,6 +48,8 @@ const readline_1 = require("readline");
|
|
|
48
48
|
const prompt_builder_1 = require("../../core/prompt-builder");
|
|
49
49
|
const index_guard_1 = require("../../core/index-guard");
|
|
50
50
|
const spec_paths_1 = require("../../core/spec-paths");
|
|
51
|
+
const task_paths_1 = require("../../core/task-paths");
|
|
52
|
+
const unit_staffing_1 = require("../../core/unit-staffing");
|
|
51
53
|
const spec_skeleton_1 = require("../../core/spec-skeleton");
|
|
52
54
|
const questions_1 = require("../../core/questions");
|
|
53
55
|
const pipeline_engine_1 = require("../../core/pipeline-engine");
|
|
@@ -232,14 +234,26 @@ function buildTaskTopic(sec, taskType) {
|
|
|
232
234
|
return (0, global_counters_1.toSlug)(sec.name);
|
|
233
235
|
}
|
|
234
236
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
*
|
|
237
|
+
* v8.3.337+: 解析模块目录名——功能单元目录名直接对齐(与 features/、020-specs/ 一致),
|
|
238
|
+
* 去掉 Task-NNN 计数器序号。非目录名格式(自创英文名/中文名)返回空,回退原 topic 链。
|
|
239
|
+
* 目录名格式校验:小写字母/数字/连字符组成(功能单元命名 v8.3.271+ 契约)。
|
|
238
240
|
*/
|
|
239
|
-
function
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
241
|
+
function resolveModuleDirName(sec) {
|
|
242
|
+
const functionalUnit = sec?.functionalUnit || '';
|
|
243
|
+
if (functionalUnit && /^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(functionalUnit)) {
|
|
244
|
+
return functionalUnit;
|
|
245
|
+
}
|
|
246
|
+
return '';
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* 生成子任务目录名(v8.3.337+ 改造)
|
|
250
|
+
* 格式: Task-{模块名}——与模块目录名(功能单元名)一致,不再拼端名。
|
|
251
|
+
* 端名已由目录层级承载({模块}/{端}/{子任务}),拼入子任务 ID 是冗余;
|
|
252
|
+
* 多端同名子任务分处不同端目录无目录冲突,Git 分支重名由 createTaskBranch hash 兜底。
|
|
253
|
+
* 例: 模块 admin-web-01-yudingguanli → 子任务 Task-admin-web-01-yudingguanli
|
|
254
|
+
*/
|
|
255
|
+
function generateSubtaskId(moduleDirName) {
|
|
256
|
+
return `Task-${moduleDirName}`;
|
|
243
257
|
}
|
|
244
258
|
/** 拆分约束常量(简化版:每个功能单元按涉及的端拆分,每端1个子任务) */
|
|
245
259
|
const SPLIT_RULES = {
|
|
@@ -1084,9 +1098,15 @@ async function iterationTaskifyCommand(options) {
|
|
|
1084
1098
|
const aiIdToTaskId = new Map();
|
|
1085
1099
|
for (const sec of sections) {
|
|
1086
1100
|
// v8.3.294+: bugfix 任务目录名拼「模块英文-内容英文」,其余类型保持原链
|
|
1101
|
+
// v8.3.337+: 模块目录名优先对齐功能单元目录名(无计数器),非目录名回退原链
|
|
1087
1102
|
const taskType = sec._taskType || 'feature';
|
|
1088
1103
|
const taskTopic = buildTaskTopic(sec, taskType);
|
|
1089
|
-
const
|
|
1104
|
+
const moduleName = resolveModuleDirName(sec);
|
|
1105
|
+
let taskId;
|
|
1106
|
+
if (moduleName)
|
|
1107
|
+
taskId = moduleName;
|
|
1108
|
+
else
|
|
1109
|
+
taskId = (await (0, global_counters_1.nextTaskId)(sec.name, taskTopic)).id;
|
|
1090
1110
|
sec._taskId = taskId;
|
|
1091
1111
|
const aiId = sec._aiId;
|
|
1092
1112
|
if (aiId)
|
|
@@ -1533,12 +1553,17 @@ async function iterationTaskifyCommand(options) {
|
|
|
1533
1553
|
}
|
|
1534
1554
|
logger_1.logger.info(`Found ${sections.length} sections to split`);
|
|
1535
1555
|
logger_1.logger.info(`Platforms: ${platforms.join(', ')}`);
|
|
1536
|
-
// ── 预分配任务 ID
|
|
1556
|
+
// ── 预分配任务 ID(v8.3.337+: 模块目录名优先对齐功能单元目录名)──
|
|
1537
1557
|
for (const section of sections) {
|
|
1538
1558
|
// v8.3.294+: bugfix 任务目录名拼「模块英文-内容英文」,其余类型保持原链
|
|
1539
1559
|
const taskType = section._taskType || 'feature';
|
|
1540
1560
|
const topic = buildTaskTopic(section, taskType);
|
|
1541
|
-
const
|
|
1561
|
+
const moduleName = resolveModuleDirName(section);
|
|
1562
|
+
let taskId;
|
|
1563
|
+
if (moduleName)
|
|
1564
|
+
taskId = moduleName;
|
|
1565
|
+
else
|
|
1566
|
+
taskId = (await (0, global_counters_1.nextTaskId)(section.name, topic)).id;
|
|
1542
1567
|
section._taskId = taskId;
|
|
1543
1568
|
}
|
|
1544
1569
|
// ── Strict mode: preview + confirm each task's split plan ──
|
|
@@ -1959,11 +1984,11 @@ async function createTaskFromSection(iterationDir, taskId, section, allPlatforms
|
|
|
1959
1984
|
logger_1.logger.warn(` ⚠️ 未找到 020-specs/ 分析文档,任务级 REQ.md/TECH.md 将生成空模板`);
|
|
1960
1985
|
logger_1.logger.warn(` 建议先运行: speccore analyze -I ${iterationName} --auto`);
|
|
1961
1986
|
}
|
|
1962
|
-
// 预生成所有端的子任务 ID
|
|
1987
|
+
// 预生成所有端的子任务 ID(子任务名 = Task-{模块名},不拼端名)
|
|
1963
1988
|
const taskNum = taskId.replace(/^Task-/, '');
|
|
1964
1989
|
const subtaskIdMap = new Map();
|
|
1965
1990
|
for (const p of taskPlatforms) {
|
|
1966
|
-
subtaskIdMap.set(p, generateSubtaskId(taskNum
|
|
1991
|
+
subtaskIdMap.set(p, generateSubtaskId(taskNum));
|
|
1967
1992
|
}
|
|
1968
1993
|
// ── 1. 任务目录指引(功能模块分组) ──
|
|
1969
1994
|
await (0, fs_extra_1.ensureDir)(taskDir);
|
|
@@ -2565,7 +2590,7 @@ ${!isBk && docSet.hasComponentTree ? '| COMPONENT_TREE.md | ⏳ | ./COMPONENT_TR
|
|
|
2565
2590
|
// 从端列表查找第一个后端端名作为 fallback(v6.48.0+)
|
|
2566
2591
|
const allPlatforms = await (0, spec_paths_1.parsePlatformList)();
|
|
2567
2592
|
const fallbackBackend = allPlatforms.find(p => p === 'backend' || p.startsWith('后台') || /-(service|api|server|backend)$/i.test(p)) || 'backend';
|
|
2568
|
-
const fallbackSubtaskId = subtaskIdMap.get(fallbackBackend) || generateSubtaskId(taskNum
|
|
2593
|
+
const fallbackSubtaskId = subtaskIdMap.get(fallbackBackend) || generateSubtaskId(taskNum);
|
|
2569
2594
|
const autoSubtaskDir = (0, path_1.join)(taskDir, fallbackBackend, fallbackSubtaskId);
|
|
2570
2595
|
await (0, fs_extra_1.ensureDir)((0, path_1.join)(autoSubtaskDir, '.meta'));
|
|
2571
2596
|
await (0, fs_extra_1.writeFile)((0, path_1.join)(autoSubtaskDir, '.meta', 'type'), taskType);
|
|
@@ -2585,7 +2610,7 @@ ${!isBk && docSet.hasComponentTree ? '| COMPONENT_TREE.md | ⏳ | ./COMPONENT_TR
|
|
|
2585
2610
|
await (0, fs_extra_1.writeFile)((0, path_1.join)(autoSubtaskDir, 'TASK.md'), `# ${section.name} — ${fallbackBackend}(自动补充)
|
|
2586
2611
|
|
|
2587
2612
|
## 子任务信息
|
|
2588
|
-
- **子任务 ID**: \`${
|
|
2613
|
+
- **子任务 ID**: \`${fallbackSubtaskId}-auto\`
|
|
2589
2614
|
- **所属模块**: \`${taskId}\`
|
|
2590
2615
|
- **功能单元**: ${featureName}
|
|
2591
2616
|
- **端**: ${fallbackBackend}
|
|
@@ -2608,7 +2633,8 @@ ${!isBk && docSet.hasComponentTree ? '| COMPONENT_TREE.md | ⏳ | ./COMPONENT_TR
|
|
|
2608
2633
|
if (docSet.hasMonitor)
|
|
2609
2634
|
await (0, fs_extra_1.writeFile)((0, path_1.join)(autoSubtaskDir, 'MONITOR.md'), generateMonitorTemplate(section, monitorMaterial));
|
|
2610
2635
|
taskPlatforms.push(fallbackBackend);
|
|
2611
|
-
|
|
2636
|
+
// 自动补充的后端子任务名也遵循 Task-{模块名}-auto(后缀区分自动补充来源)
|
|
2637
|
+
subtaskIdMap.set(fallbackBackend, `${fallbackSubtaskId}-auto`);
|
|
2612
2638
|
}
|
|
2613
2639
|
// ─ 5. 任务上下文 CONTEXT.md ─
|
|
2614
2640
|
const sourceFile = section._sourceFile || '';
|
|
@@ -4131,6 +4157,8 @@ function readStaffing(iterationDir) {
|
|
|
4131
4157
|
name: m.name,
|
|
4132
4158
|
platforms: m.directions,
|
|
4133
4159
|
capacity: m.capacity,
|
|
4160
|
+
roles: m.roles,
|
|
4161
|
+
initials: m.initials,
|
|
4134
4162
|
}));
|
|
4135
4163
|
return members.length > 0 ? members : null;
|
|
4136
4164
|
}
|
|
@@ -4163,25 +4191,86 @@ async function resolveUnitOwnerFromMatrix(iterationDir, sectionName, platform) {
|
|
|
4163
4191
|
return undefined;
|
|
4164
4192
|
}
|
|
4165
4193
|
/**
|
|
4166
|
-
*
|
|
4194
|
+
* 端名 → 需求岗位映射(v8.3.337+):按端名关键词推断技术岗位维度。
|
|
4195
|
+
* 用于 autoAssign 双维匹配——岗位(技术栈维度)+ 方向(业务端维度)正交筛选。
|
|
4196
|
+
*/
|
|
4197
|
+
function platformToRoles(platform) {
|
|
4198
|
+
const p = platform.toLowerCase();
|
|
4199
|
+
const roles = [];
|
|
4200
|
+
if (/web|admin|h5|frontend|pc|小程序/.test(p))
|
|
4201
|
+
roles.push('web');
|
|
4202
|
+
if (/service|api|server|backend|后台/.test(p))
|
|
4203
|
+
roles.push('后端');
|
|
4204
|
+
if (/app|mobile|移动|android|ios/.test(p))
|
|
4205
|
+
roles.push('移动端');
|
|
4206
|
+
return roles;
|
|
4207
|
+
}
|
|
4208
|
+
/** 岗位别名归一(成员表自由填写:web/前端、后端/服务端、移动端/APP 同义) */
|
|
4209
|
+
const ROLE_ALIASES = {
|
|
4210
|
+
'web': ['前端', 'frontend'],
|
|
4211
|
+
'后端': ['backend', '服务端', 'server'],
|
|
4212
|
+
'移动端': ['mobile', 'app'],
|
|
4213
|
+
};
|
|
4214
|
+
/** 成员岗位是否命中任务所需岗位之一(v8.3.339+: 通配成员恒命中) */
|
|
4215
|
+
function memberRoleMatches(memberRoles, needRoles) {
|
|
4216
|
+
if (needRoles.length === 0 || memberRoles.length === 0)
|
|
4217
|
+
return false;
|
|
4218
|
+
if (memberRoles.includes(unit_staffing_1.WILDCARD))
|
|
4219
|
+
return true; // 全栈成员岗位恒命中
|
|
4220
|
+
for (const need of needRoles) {
|
|
4221
|
+
const n = need.toLowerCase();
|
|
4222
|
+
const aliases = ROLE_ALIASES[n] ?? [];
|
|
4223
|
+
for (const r of memberRoles) {
|
|
4224
|
+
const rl = r.toLowerCase();
|
|
4225
|
+
if (rl === n || rl.includes(n) || n.includes(rl))
|
|
4226
|
+
return true;
|
|
4227
|
+
if (aliases.some((a) => rl.includes(a.toLowerCase()) || a.toLowerCase().includes(rl)))
|
|
4228
|
+
return true;
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
return false;
|
|
4232
|
+
}
|
|
4233
|
+
/**
|
|
4234
|
+
* 根据平台和负荷自动推荐负责人(v8.3.337+ 双维匹配)
|
|
4235
|
+
*
|
|
4236
|
+
* 三级匹配(从严格到宽松,同级内取负荷最低者):
|
|
4237
|
+
* 1. 岗位+方向双命中(技术栈与业务端都对口)
|
|
4238
|
+
* 2. 仅方向命中(沿用 v8.3.319 语义)
|
|
4239
|
+
* 3. 仅岗位命中(方向未声明但技术栈对口)
|
|
4240
|
+
* 均无命中 → 未分配。已剔除「不在项目」成员(loadStaffing 过滤)。
|
|
4167
4241
|
*/
|
|
4168
4242
|
function autoAssign(section, platforms, staffing) {
|
|
4169
4243
|
const targetPlatform = section.platform || '';
|
|
4170
4244
|
if (!targetPlatform || !staffing.length)
|
|
4171
4245
|
return '未分配';
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4246
|
+
const needRoles = platformToRoles(targetPlatform);
|
|
4247
|
+
const pickLowest = (candidates) => {
|
|
4248
|
+
let best = null;
|
|
4249
|
+
let bestLoad = Infinity;
|
|
4250
|
+
for (const m of candidates) {
|
|
4251
|
+
if (m.capacity <= 0)
|
|
4252
|
+
continue; // v8.3.319: 投入比例 0% = 本迭代不参与分配(如休假)
|
|
4253
|
+
if (m.capacity < bestLoad) {
|
|
4254
|
+
best = m;
|
|
4255
|
+
bestLoad = m.capacity;
|
|
4256
|
+
}
|
|
4257
|
+
}
|
|
4258
|
+
return best;
|
|
4259
|
+
};
|
|
4260
|
+
const directionHit = (m) => m.platforms.includes(unit_staffing_1.WILDCARD) || // v8.3.339+: 通配方向恒命中(全栈成员兜底)
|
|
4261
|
+
m.platforms.some((p) => targetPlatform.includes(p) || p.includes(targetPlatform));
|
|
4262
|
+
const roleHit = (m) => memberRoleMatches(m.roles, needRoles);
|
|
4263
|
+
// 1. 岗位+方向双命中
|
|
4264
|
+
const dual = pickLowest(staffing.filter((m) => directionHit(m) && roleHit(m)));
|
|
4265
|
+
if (dual)
|
|
4266
|
+
return dual.name;
|
|
4267
|
+
// 2. 仅方向命中
|
|
4268
|
+
const dirOnly = pickLowest(staffing.filter(directionHit));
|
|
4269
|
+
if (dirOnly)
|
|
4270
|
+
return dirOnly.name;
|
|
4271
|
+
// 3. 仅岗位命中
|
|
4272
|
+
const roleOnly = pickLowest(staffing.filter(roleHit));
|
|
4273
|
+
return roleOnly ? roleOnly.name : '未分配';
|
|
4185
4274
|
}
|
|
4186
4275
|
/**
|
|
4187
4276
|
* 分析章节复杂度,决定优先级和工时(简化版)
|
|
@@ -4249,24 +4338,27 @@ async function detectExistingTasks(iterDir) {
|
|
|
4249
4338
|
// 优先从 030-tasks/ 扫描
|
|
4250
4339
|
const scanDir = (0, path_1.join)(iterDir, '030-tasks');
|
|
4251
4340
|
const targetDir = (await (0, fs_extra_1.pathExists)(scanDir)) ? scanDir : iterDir;
|
|
4252
|
-
|
|
4341
|
+
// v8.3.337+: 新布局模块目录名=功能单元名(无 Task- 前缀),位于类型子目录直接层
|
|
4342
|
+
// (030-tasks/{type}/{模块})。depth ≤ 1 时按功能单元名识别为模块并停止深入,
|
|
4343
|
+
// 避免误把端目录/子任务目录当任务收集。旧布局 030-tasks/Task-* 仍按前缀识别。
|
|
4344
|
+
const scanRecursive = async (dir, depth) => {
|
|
4253
4345
|
try {
|
|
4254
4346
|
const entries = await (0, fs_extra_1.readdir)(dir, { withFileTypes: true });
|
|
4255
4347
|
for (const e of entries) {
|
|
4256
4348
|
if (e.isDirectory()) {
|
|
4257
|
-
if (e.name.startsWith('Task-')) {
|
|
4349
|
+
if (e.name.startsWith('Task-') || (depth <= 1 && (0, task_paths_1.isTaskModuleDirName)(e.name))) {
|
|
4258
4350
|
tasks.push(e.name);
|
|
4259
4351
|
}
|
|
4260
4352
|
else if (!e.name.startsWith('.')) {
|
|
4261
4353
|
// 递归扫描类型子目录(feature/bugfix/refactor/research)
|
|
4262
|
-
await scanRecursive((0, path_1.join)(dir, e.name));
|
|
4354
|
+
await scanRecursive((0, path_1.join)(dir, e.name), depth + 1);
|
|
4263
4355
|
}
|
|
4264
4356
|
}
|
|
4265
4357
|
}
|
|
4266
4358
|
}
|
|
4267
4359
|
catch { }
|
|
4268
4360
|
};
|
|
4269
|
-
await scanRecursive(targetDir);
|
|
4361
|
+
await scanRecursive(targetDir, 0);
|
|
4270
4362
|
return tasks;
|
|
4271
4363
|
}
|
|
4272
4364
|
/**
|
|
@@ -4294,7 +4386,8 @@ async function pruneTasksByModules(iterDir, modules) {
|
|
|
4294
4386
|
if (!e.isDirectory())
|
|
4295
4387
|
continue;
|
|
4296
4388
|
const full = (0, path_1.join)(dir, e.name);
|
|
4297
|
-
|
|
4389
|
+
// v8.3.337+: 新布局模块目录=功能单元名(无 Task- 前缀),同样按 .meta/feature 匹配
|
|
4390
|
+
if (e.name.startsWith('Task-') || (0, task_paths_1.isTaskModuleDirName)(e.name)) {
|
|
4298
4391
|
let feature = '';
|
|
4299
4392
|
try {
|
|
4300
4393
|
feature = (await (0, fs_extra_1.readFile)((0, path_1.join)(full, '.meta', 'feature'), 'utf-8')).trim();
|
|
@@ -5054,7 +5147,12 @@ async function tryModuleDrivenSplit(iteration, iterationDir, options) {
|
|
|
5054
5147
|
// 逐模块创建任务目录(按模块各自的涉及端)
|
|
5055
5148
|
const createdSections = [];
|
|
5056
5149
|
for (const mod of modules) {
|
|
5057
|
-
|
|
5150
|
+
// v8.3.337+: 模块目录名优先对齐功能单元目录名(mod.name 即功能单元名)
|
|
5151
|
+
let taskId;
|
|
5152
|
+
if (mod.name && /^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(mod.name))
|
|
5153
|
+
taskId = mod.name;
|
|
5154
|
+
else
|
|
5155
|
+
taskId = (await (0, global_counters_1.nextTaskId)(mod.name, mod.slug)).id;
|
|
5058
5156
|
const modPlatforms = mod.platforms.length > 0 ? mod.platforms : [...allPlatforms];
|
|
5059
5157
|
// v8.3.249+: section.content 从 sourceFile(SOURCE.md 等)读取——此前硬编码空串,
|
|
5060
5158
|
// 导致 REQ.md 四级回退全部落空(aiReq/analyzeReq/短 section.content 均不满足),
|