@guanlin4924/devflow-pi 0.1.16 → 0.1.17
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/package.json +1 -1
- package/plugins/devflow-core/extensions/devflow-core.ts +247 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +3 -2
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_assessment.rb +458 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_brief.rb +256 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_constraints.rb +155 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/architecture_feasibility.rb +176 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/control_io.rb +46 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +1 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +1 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +187 -12
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/runtime_context_collector.rb +210 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/stale_check.rb +56 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/static_runtime_context_collector.rb +518 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +83 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/workload_constraint.rb +57 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +54 -2
- package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +3 -2
- package/plugins/devflow-core/skills/workflow-project-context/SKILL.md +17 -1
- package/plugins/devflow-design/skills/workflow-architecture-feasibility/SKILL.md +37 -0
- package/plugins/devflow-design/skills/workflow-architecture-feasibility/agents/openai.yaml +4 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/SKILL.md +7 -2
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/SKILL.md +6 -1
package/package.json
CHANGED
|
@@ -1310,7 +1310,7 @@ export default function devflowCore(pi: ExtensionAPI) {
|
|
|
1310
1310
|
read: z.boolean().optional(),
|
|
1311
1311
|
delta: z.object({
|
|
1312
1312
|
op: z.enum(["add", "link", "update"]),
|
|
1313
|
-
kind: z.enum(["source", "code", "term", "object", "behavior", "requirement", "rule", "boundary", "slice", "risk", "decision", "acceptance", "api"]).optional(),
|
|
1313
|
+
kind: z.enum(["source", "code", "term", "object", "behavior", "requirement", "rule", "boundary", "slice", "risk", "decision", "acceptance", "api", "workload_shape", "workload_constraint"]).optional(),
|
|
1314
1314
|
id: z.string().min(1).optional(),
|
|
1315
1315
|
data: z.record(z.string(), z.unknown()).optional(),
|
|
1316
1316
|
from: z.string().min(1).optional(),
|
|
@@ -1340,6 +1340,36 @@ export default function devflowCore(pi: ExtensionAPI) {
|
|
|
1340
1340
|
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "confirm requires expectedRevision, nodeId and evidence" });
|
|
1341
1341
|
}
|
|
1342
1342
|
args.push("--write", "--expected-revision", String(params.expectedRevision), "--node-id", params.nodeId, "--evidence-json", JSON.stringify(params.evidence));
|
|
1343
|
+
const inspected = parseJsonResult(
|
|
1344
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/requirement_graph.rb", ["inspect", "--feature", params.feature, "--json"]),
|
|
1345
|
+
);
|
|
1346
|
+
const node = Array.isArray(inspected?.graph?.nodes)
|
|
1347
|
+
? inspected.graph.nodes.find((candidate: unknown) => typeof candidate === "object" && candidate !== null && (candidate as { id?: unknown }).id === params.nodeId) as { kind?: unknown; data?: unknown } | undefined
|
|
1348
|
+
: undefined;
|
|
1349
|
+
const architectureDecision = node?.kind === "decision" && typeof node?.data === "object" && node.data !== null && (node.data as { decision_type?: unknown }).decision_type === "architecture_option_comparison";
|
|
1350
|
+
const architectureRisk = node?.kind === "risk" && typeof node?.data === "object" && node.data !== null && (node.data as { risk_type?: unknown }).risk_type === "architecture_option_risk";
|
|
1351
|
+
if (node?.kind === "workload_shape" || node?.kind === "workload_constraint" || architectureDecision || architectureRisk) {
|
|
1352
|
+
const preview = JSON.stringify(node.data ?? {}, null, 2);
|
|
1353
|
+
const decisionDialog = architectureDecision;
|
|
1354
|
+
const riskDialog = architectureRisk;
|
|
1355
|
+
const confirmed = await ctx.ui.confirm(
|
|
1356
|
+
decisionDialog ? "确认架构方案取舍" : riskDialog ? "确认架构风险处理" : "确认工作负载事实或缺口",
|
|
1357
|
+
[
|
|
1358
|
+
`Feature:${params.feature}`,
|
|
1359
|
+
`节点:${params.nodeId}`,
|
|
1360
|
+
`类型:${decisionDialog ? "架构方案比较" : riskDialog ? "架构风险处理" : node.kind === "workload_shape" ? "工作负载形态" : "工作负载约束"}`,
|
|
1361
|
+
decisionDialog
|
|
1362
|
+
? "确认的含义是:你已核对候选方案、证据与取舍,并接受其中 recommendation_option_id 作为本次架构选择。"
|
|
1363
|
+
: riskDialog
|
|
1364
|
+
? "确认的含义是:你已核对失败模式、影响、处理方式、负责人和复核条件;它不代表生产风险从此消失。"
|
|
1365
|
+
: "确认的含义仅是:该事实或缺口、来源与责任归属已被你核对;它不代表容量已经满足,也不会替你选择实现方案。",
|
|
1366
|
+
"待确认内容:",
|
|
1367
|
+
preview.length > 8_000 ? `${preview.slice(0, 8_000)}\n…(内容过长,已截断)` : preview,
|
|
1368
|
+
].join("\n\n"),
|
|
1369
|
+
);
|
|
1370
|
+
if (!confirmed) return renderResult({ ok: false, exitCode: 1, stdout: "", stderr: "User declined workload confirmation; node remains candidate." });
|
|
1371
|
+
args.push("--confirmed-interactively");
|
|
1372
|
+
}
|
|
1343
1373
|
}
|
|
1344
1374
|
return renderResult(
|
|
1345
1375
|
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/requirement_graph.rb", args),
|
|
@@ -1348,6 +1378,222 @@ export default function devflowCore(pi: ExtensionAPI) {
|
|
|
1348
1378
|
},
|
|
1349
1379
|
});
|
|
1350
1380
|
|
|
1381
|
+
pi.registerTool({
|
|
1382
|
+
name: "devflow_runtime_context",
|
|
1383
|
+
label: "Devflow Runtime Context",
|
|
1384
|
+
description: "Collect or inspect the P0 repository-declared dependency snapshot and its coverage.",
|
|
1385
|
+
parameters: z.object({
|
|
1386
|
+
action: z.enum(["collect", "inspect"]),
|
|
1387
|
+
}),
|
|
1388
|
+
approval: (args) => args.action === "collect" ? "write" : "read",
|
|
1389
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1390
|
+
return renderResult(
|
|
1391
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/runtime_context_collector.rb", [params.action, "--json"]),
|
|
1392
|
+
{ action: params.action },
|
|
1393
|
+
);
|
|
1394
|
+
},
|
|
1395
|
+
});
|
|
1396
|
+
|
|
1397
|
+
pi.registerTool({
|
|
1398
|
+
name: "devflow_static_runtime_context",
|
|
1399
|
+
label: "Devflow Static Runtime Context",
|
|
1400
|
+
description: "Collect or inspect the P1 static evidence snapshot. It records only repository declarations and references, never production health or capacity.",
|
|
1401
|
+
parameters: z.object({
|
|
1402
|
+
action: z.enum(["collect", "inspect"]),
|
|
1403
|
+
}),
|
|
1404
|
+
approval: (args) => args.action === "collect" ? "write" : "read",
|
|
1405
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1406
|
+
return renderResult(
|
|
1407
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/static_runtime_context_collector.rb", [params.action, "--json"]),
|
|
1408
|
+
{ action: params.action },
|
|
1409
|
+
);
|
|
1410
|
+
},
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
pi.registerTool({
|
|
1414
|
+
name: "devflow_architecture_assessment",
|
|
1415
|
+
label: "Devflow Architecture Assessment",
|
|
1416
|
+
description: "Confirm an immutable delta set through an explicit user dialog, then assess only that Core-owned manifest against a pinned runtime-context snapshot.",
|
|
1417
|
+
parameters: z.object({
|
|
1418
|
+
action: z.enum(["inspect", "assess", "write-manifest"]),
|
|
1419
|
+
feature: z.string().min(1),
|
|
1420
|
+
baseSnapshotRevision: z.number().int().min(0).optional(),
|
|
1421
|
+
deltaSetId: z.string().min(1).optional(),
|
|
1422
|
+
deltaJson: z.array(z.record(z.string(), z.unknown())).optional(),
|
|
1423
|
+
sourceBundleRevision: z.string().min(1).optional(),
|
|
1424
|
+
expectedAssessmentRevision: z.number().int().min(0).optional(),
|
|
1425
|
+
write: z.boolean().optional(),
|
|
1426
|
+
}),
|
|
1427
|
+
approval: (args) => args.action === "write-manifest" || args.write ? "write" : "read",
|
|
1428
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1429
|
+
const args = [params.action, "--feature", params.feature, "--json"];
|
|
1430
|
+
if (params.action === "inspect") {
|
|
1431
|
+
if (params.deltaSetId) args.push("--delta-set-id", params.deltaSetId);
|
|
1432
|
+
return renderResult(
|
|
1433
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_assessment.rb", args),
|
|
1434
|
+
{ action: params.action, feature: params.feature },
|
|
1435
|
+
);
|
|
1436
|
+
}
|
|
1437
|
+
if (!params.deltaSetId) {
|
|
1438
|
+
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "deltaSetId is required" });
|
|
1439
|
+
}
|
|
1440
|
+
args.push("--delta-set-id", params.deltaSetId);
|
|
1441
|
+
if (params.action === "assess") {
|
|
1442
|
+
if (params.baseSnapshotRevision === undefined) {
|
|
1443
|
+
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "assess requires baseSnapshotRevision and deltaSetId; deltas and manifest are Core-owned" });
|
|
1444
|
+
}
|
|
1445
|
+
args.push("--base-snapshot-revision", String(params.baseSnapshotRevision));
|
|
1446
|
+
if (params.write) {
|
|
1447
|
+
const inspected = parseJsonResult(await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_assessment.rb", ["inspect", "--feature", params.feature, "--delta-set-id", params.deltaSetId, "--json"]));
|
|
1448
|
+
const currentRevision = typeof inspected?.current_assessment_revision === "number" ? inspected.current_assessment_revision : undefined;
|
|
1449
|
+
if (currentRevision === undefined) {
|
|
1450
|
+
return renderResult({ ok: false, exitCode: 1, stdout: "", stderr: "Unable to read the current assessment revision for CAS." });
|
|
1451
|
+
}
|
|
1452
|
+
args.push("--write", "--expected-assessment-revision", String(currentRevision));
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
if (params.action === "write-manifest") {
|
|
1456
|
+
if (!params.sourceBundleRevision || !params.deltaJson?.length) {
|
|
1457
|
+
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "write-manifest requires deltaSetId, sourceBundleRevision and a non-empty deltaJson" });
|
|
1458
|
+
}
|
|
1459
|
+
const preview = params.deltaJson.map((rawDelta, index) => {
|
|
1460
|
+
const delta = rawDelta as Record<string, unknown>;
|
|
1461
|
+
const source = delta.source && typeof delta.source === "object" ? delta.source as Record<string, unknown> : {};
|
|
1462
|
+
return [
|
|
1463
|
+
`${index + 1}. ID:${String(delta.id ?? "(缺失)")}`,
|
|
1464
|
+
`依赖:${String(delta.subject ?? "(缺失)")}`,
|
|
1465
|
+
`来源:${String(source.locator ?? "(缺失)")}`,
|
|
1466
|
+
`来源 revision:${String(source.repository_revision ?? "(缺失)")}`,
|
|
1467
|
+
`内容哈希:${String(source.input_hash ?? "(缺失)")}`,
|
|
1468
|
+
].join("\n");
|
|
1469
|
+
}).join("\n\n");
|
|
1470
|
+
const confirmed = await ctx.ui.confirm(
|
|
1471
|
+
"确认架构评估 Delta 集合",
|
|
1472
|
+
[
|
|
1473
|
+
`Feature:${params.feature}`,
|
|
1474
|
+
`Delta 集合:${params.deltaSetId}`,
|
|
1475
|
+
`需求/方案 revision:${params.sourceBundleRevision}`,
|
|
1476
|
+
"确认后 Core 会创建不可覆盖的 manifest;后续评估只能读取这一份确认内容。",
|
|
1477
|
+
"请核对以下依赖、来源与哈希:",
|
|
1478
|
+
preview,
|
|
1479
|
+
].join("\n\n"),
|
|
1480
|
+
);
|
|
1481
|
+
if (!confirmed) return renderResult({ ok: false, exitCode: 1, stdout: "", stderr: "User declined delta-set confirmation; no manifest was written." });
|
|
1482
|
+
args.push("--source-bundle-revision", params.sourceBundleRevision, "--delta-json", JSON.stringify(params.deltaJson), "--confirmed-interactively", "--write");
|
|
1483
|
+
}
|
|
1484
|
+
return renderResult(
|
|
1485
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_assessment.rb", args),
|
|
1486
|
+
{ action: params.action, feature: params.feature },
|
|
1487
|
+
);
|
|
1488
|
+
},
|
|
1489
|
+
});
|
|
1490
|
+
|
|
1491
|
+
pi.registerTool({
|
|
1492
|
+
name: "devflow_workload_constraint",
|
|
1493
|
+
label: "Devflow Workload Constraint",
|
|
1494
|
+
description: "Validate a workload constraint (NFR) against its source-status schema.",
|
|
1495
|
+
parameters: z.object({
|
|
1496
|
+
constraintJson: z.record(z.string(), z.unknown()),
|
|
1497
|
+
}),
|
|
1498
|
+
approval: "read",
|
|
1499
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1500
|
+
return renderResult(
|
|
1501
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/workload_constraint.rb", ["validate", "--constraint-json", JSON.stringify(params.constraintJson), "--json"]),
|
|
1502
|
+
{},
|
|
1503
|
+
);
|
|
1504
|
+
},
|
|
1505
|
+
});
|
|
1506
|
+
|
|
1507
|
+
pi.registerTool({
|
|
1508
|
+
name: "devflow_architecture_constraint",
|
|
1509
|
+
label: "Devflow Architecture Constraint",
|
|
1510
|
+
description: "Validate candidate workload shape or workload constraint inputs without assigning confirmation, decisions, or gate status.",
|
|
1511
|
+
parameters: z.object({
|
|
1512
|
+
action: z.enum(["validate-shape", "validate-constraint"]),
|
|
1513
|
+
shapeJson: z.record(z.string(), z.unknown()).optional(),
|
|
1514
|
+
constraintJson: z.record(z.string(), z.unknown()).optional(),
|
|
1515
|
+
}),
|
|
1516
|
+
approval: "read",
|
|
1517
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1518
|
+
if (params.action === "validate-shape" && !params.shapeJson) {
|
|
1519
|
+
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "validate-shape requires shapeJson" });
|
|
1520
|
+
}
|
|
1521
|
+
if (params.action === "validate-constraint" && !params.constraintJson) {
|
|
1522
|
+
return renderResult({ ok: false, exitCode: 2, stdout: "", stderr: "validate-constraint requires constraintJson" });
|
|
1523
|
+
}
|
|
1524
|
+
const args = [params.action, "--json"];
|
|
1525
|
+
if (params.shapeJson) args.push("--shape-json", JSON.stringify(params.shapeJson));
|
|
1526
|
+
if (params.constraintJson) args.push("--constraint-json", JSON.stringify(params.constraintJson));
|
|
1527
|
+
return renderResult(
|
|
1528
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_constraints.rb", args),
|
|
1529
|
+
{ action: params.action },
|
|
1530
|
+
);
|
|
1531
|
+
},
|
|
1532
|
+
});
|
|
1533
|
+
|
|
1534
|
+
pi.registerTool({
|
|
1535
|
+
name: "devflow_architecture_feasibility",
|
|
1536
|
+
label: "Devflow Architecture Feasibility",
|
|
1537
|
+
description: "Read confirmed workload facts and a pinned static-context snapshot to derive an advisory architecture assessment. It never selects an option or claims production capacity.",
|
|
1538
|
+
parameters: z.object({
|
|
1539
|
+
feature: z.string().min(1),
|
|
1540
|
+
}),
|
|
1541
|
+
approval: "read",
|
|
1542
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1543
|
+
return renderResult(
|
|
1544
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_feasibility.rb", ["assess", "--feature", params.feature, "--json"]),
|
|
1545
|
+
{ feature: params.feature },
|
|
1546
|
+
);
|
|
1547
|
+
},
|
|
1548
|
+
});
|
|
1549
|
+
|
|
1550
|
+
pi.registerTool({
|
|
1551
|
+
name: "devflow_architecture_brief",
|
|
1552
|
+
label: "Devflow Architecture Brief",
|
|
1553
|
+
description: "Inspect or regenerate the Core-derived architecture brief from the current graph and static-context snapshot. The brief is a view, never an agent-authored source of truth.",
|
|
1554
|
+
parameters: z.object({
|
|
1555
|
+
action: z.enum(["inspect", "render"]),
|
|
1556
|
+
feature: z.string().min(1),
|
|
1557
|
+
}),
|
|
1558
|
+
approval: (args) => args.action === "render" ? "write" : "read",
|
|
1559
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1560
|
+
if (params.action === "inspect") {
|
|
1561
|
+
return renderResult(
|
|
1562
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_brief.rb", ["inspect", "--feature", params.feature, "--json"]),
|
|
1563
|
+
{ action: params.action, feature: params.feature },
|
|
1564
|
+
);
|
|
1565
|
+
}
|
|
1566
|
+
const inspected = parseJsonResult(
|
|
1567
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_brief.rb", ["inspect", "--feature", params.feature, "--json"]),
|
|
1568
|
+
);
|
|
1569
|
+
const currentRevision = typeof inspected?.brief_revision === "number" ? inspected.brief_revision : undefined;
|
|
1570
|
+
if (currentRevision === undefined) {
|
|
1571
|
+
return renderResult({ ok: false, exitCode: 1, stdout: "", stderr: "Unable to read the current architecture brief revision for CAS." });
|
|
1572
|
+
}
|
|
1573
|
+
return renderResult(
|
|
1574
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/architecture_brief.rb", ["render", "--feature", params.feature, "--write", "--expected-brief-revision", String(currentRevision), "--json"]),
|
|
1575
|
+
{ action: params.action, feature: params.feature },
|
|
1576
|
+
);
|
|
1577
|
+
},
|
|
1578
|
+
});
|
|
1579
|
+
|
|
1580
|
+
pi.registerTool({
|
|
1581
|
+
name: "devflow_stale_check",
|
|
1582
|
+
label: "Devflow Stale Check",
|
|
1583
|
+
description: "Check field-level staleness of consumed evidence against the current snapshot.",
|
|
1584
|
+
parameters: z.object({
|
|
1585
|
+
consumedRevision: z.number().int().min(0),
|
|
1586
|
+
evidencePaths: z.array(z.string().min(1)),
|
|
1587
|
+
}),
|
|
1588
|
+
approval: "read",
|
|
1589
|
+
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
1590
|
+
return renderResult(
|
|
1591
|
+
await runRuby(ctx.cwd, "workflow-orchestrator/scripts/stale_check.rb", ["check", "--consumed-revision", String(params.consumedRevision), "--evidence-paths", JSON.stringify(params.evidencePaths), "--json"]),
|
|
1592
|
+
{},
|
|
1593
|
+
);
|
|
1594
|
+
},
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1351
1597
|
pi.registerTool({
|
|
1352
1598
|
name: "devflow_evidence",
|
|
1353
1599
|
label: "Devflow Evidence Pack",
|
|
@@ -117,6 +117,7 @@ After each step completes, verify the step's gate before advancing:
|
|
|
117
117
|
| requirement-feasibility-review | 可实现性审查.meta.json `status=ready_for_baseline`、`baseline_gate=pass`、`gap_count=0` 且无 critical finding | Reject advance to requirement-baseline |
|
|
118
118
|
| requirement-baseline | baseline.md review conclusion is "通过" AND baseline.meta.json `review_status` / `traceability_status` are `passed` AND blocking counters are all 0 | Reject advance to api-contract |
|
|
119
119
|
| api-contract | api-contract.meta.json `review_status` / `traceability_status` are `passed` AND `pending_contract_count` is 0 | Reject advance to dual tracks |
|
|
120
|
+
| architecture-feasibility | Core-derived `architecture-brief.md` / meta exist. If `assessment_level=full`, require `assessment_status=ready` and `comparison_status=confirmed`; a lightweight incomplete result may proceed only as an explicitly unresolved downstream input. | Reject advance to dual tracks for an incomplete full assessment |
|
|
120
121
|
| ui-spec | UI-SPEC.md review conclusion is "通过" | Reject advance to feature-breakdown |
|
|
121
122
|
| feature-breakdown | 功能点梳理.md review conclusion is "通过" | Reject advance to tech-specs |
|
|
122
123
|
| api-call-guide | api-call-guide.meta.json `frontend_consumable` and `mock_ready` are true, pending_items is empty | Reject merge gate |
|
|
@@ -161,8 +162,8 @@ When the inspector returns `route_failure_branch`:
|
|
|
161
162
|
When the inspector returns `run_parallel_window`:
|
|
162
163
|
|
|
163
164
|
0. **Track filtering**(新增):读取 STATE.md 的 `active_track` 字段
|
|
164
|
-
- 如果 `active_track == "A"`:只路由完整需求主链及 Track A 步骤(requirement-triage、requirement-wayfinder、domain-modeling、requirement-feasibility-review、requirement-baseline、api-contract、backend-tech-spec、api-call-guide),完成后阻断在轨道边界
|
|
165
|
-
- 如果 `active_track == "B"`:新需求必须完成完整需求主链;前端设计步骤仍依赖 api-contract。允许步骤为 requirement-triage、requirement-wayfinder、domain-modeling、requirement-feasibility-review、requirement-baseline、api-contract、ui-spec、feature-breakdown、frontend-tech-spec、api-supplement,完成后阻断在轨道边界
|
|
165
|
+
- 如果 `active_track == "A"`:只路由完整需求主链及 Track A 步骤(requirement-triage、requirement-wayfinder、domain-modeling、requirement-feasibility-review、requirement-baseline、api-contract、architecture-feasibility、backend-tech-spec、api-call-guide),完成后阻断在轨道边界
|
|
166
|
+
- 如果 `active_track == "B"`:新需求必须完成完整需求主链;前端设计步骤仍依赖 api-contract 和 architecture-feasibility。允许步骤为 requirement-triage、requirement-wayfinder、domain-modeling、requirement-feasibility-review、requirement-baseline、api-contract、architecture-feasibility、ui-spec、feature-breakdown、frontend-tech-spec、api-supplement,完成后阻断在轨道边界
|
|
166
167
|
- 如果未设置或无效:保留全部 branch_steps(双轨道)
|
|
167
168
|
- 过滤后如果只剩一个步骤,退化为串行执行(不启动并行窗口)
|
|
168
169
|
|