@mcoda/core 0.1.16 → 0.1.18
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/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
- package/dist/services/backlog/TaskOrderingService.js +26 -2
- package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
- package/dist/services/execution/WorkOnTasksService.js +167 -5
- package/dist/services/planning/CreateTasksService.d.ts +18 -0
- package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
- package/dist/services/planning/CreateTasksService.js +878 -8
- package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
- package/dist/services/planning/RefineTasksService.js +17 -4
- package/dist/services/shared/ProjectGuidance.js +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaskOrderingService.d.ts","sourceRoot":"","sources":["../../../src/services/backlog/TaskOrderingService.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAG1E,OAAO,EAAgB,SAAS,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"TaskOrderingService.d.ts","sourceRoot":"","sources":["../../../src/services/backlog/TaskOrderingService.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ import { classifyTask } from "./TaskOrderingHeuristics.js";
|
|
|
9
9
|
const DEFAULT_STATUSES = ["not_started", "in_progress", "changes_requested", READY_TO_CODE_REVIEW, "ready_to_qa"];
|
|
10
10
|
const DONE_STATUSES = new Set(["completed", "cancelled"]);
|
|
11
11
|
const DEFAULT_STAGE_ORDER = ["foundation", "backend", "frontend", "other"];
|
|
12
|
+
const PLANNING_DOC_HINT_PATTERN = /(sds|pdr|rfp|requirements|architecture|openapi|swagger|design)/i;
|
|
12
13
|
const STATUS_RANK = {
|
|
13
14
|
in_progress: 0,
|
|
14
15
|
changes_requested: 0,
|
|
@@ -230,10 +231,21 @@ export class TaskOrderingService {
|
|
|
230
231
|
}
|
|
231
232
|
async buildDocContext(projectKey, warnings) {
|
|
232
233
|
try {
|
|
233
|
-
|
|
234
|
+
let docs = await this.docdex.search({ docType: "SDS", projectKey });
|
|
235
|
+
if (!docs.length) {
|
|
236
|
+
docs = await this.docdex.search({
|
|
237
|
+
projectKey,
|
|
238
|
+
profile: "workspace-code",
|
|
239
|
+
query: "sds requirements architecture openapi",
|
|
240
|
+
});
|
|
241
|
+
}
|
|
234
242
|
if (!docs.length)
|
|
235
243
|
return undefined;
|
|
236
|
-
const doc = docs
|
|
244
|
+
const doc = docs.find((entry) => {
|
|
245
|
+
const type = (entry.docType ?? "").toLowerCase();
|
|
246
|
+
const label = `${entry.path ?? ""} ${entry.title ?? ""}`.toLowerCase();
|
|
247
|
+
return type.includes("sds") || type.includes("pdr") || type.includes("rfp") || PLANNING_DOC_HINT_PATTERN.test(label);
|
|
248
|
+
}) ?? docs[0];
|
|
237
249
|
const segments = (doc.segments ?? []).slice(0, 3);
|
|
238
250
|
const body = segments.length > 0
|
|
239
251
|
? segments
|
|
@@ -323,9 +335,11 @@ export class TaskOrderingService {
|
|
|
323
335
|
t.assignee_human,
|
|
324
336
|
t.epic_id,
|
|
325
337
|
e.key as epic_key,
|
|
338
|
+
e.priority as epic_priority,
|
|
326
339
|
t.user_story_id as story_id,
|
|
327
340
|
us.key as story_key,
|
|
328
341
|
us.title as story_title,
|
|
342
|
+
us.priority as story_priority,
|
|
329
343
|
t.created_at,
|
|
330
344
|
t.updated_at,
|
|
331
345
|
t.metadata_json
|
|
@@ -339,6 +353,8 @@ export class TaskOrderingService {
|
|
|
339
353
|
...row,
|
|
340
354
|
story_points: row.story_points ?? null,
|
|
341
355
|
priority: row.priority ?? null,
|
|
356
|
+
epic_priority: row.epic_priority ?? null,
|
|
357
|
+
story_priority: row.story_priority ?? null,
|
|
342
358
|
metadata: row.metadata_json ? JSON.parse(row.metadata_json) : null,
|
|
343
359
|
}));
|
|
344
360
|
}
|
|
@@ -604,6 +620,14 @@ export class TaskOrderingService {
|
|
|
604
620
|
}
|
|
605
621
|
}
|
|
606
622
|
compareTasks(a, b, impact, agentRank, stageOrderMap) {
|
|
623
|
+
const epicPriorityA = a.epic_priority ?? Number.MAX_SAFE_INTEGER;
|
|
624
|
+
const epicPriorityB = b.epic_priority ?? Number.MAX_SAFE_INTEGER;
|
|
625
|
+
if (epicPriorityA !== epicPriorityB)
|
|
626
|
+
return epicPriorityA - epicPriorityB;
|
|
627
|
+
const storyPriorityA = a.story_priority ?? Number.MAX_SAFE_INTEGER;
|
|
628
|
+
const storyPriorityB = b.story_priority ?? Number.MAX_SAFE_INTEGER;
|
|
629
|
+
if (storyPriorityA !== storyPriorityB)
|
|
630
|
+
return storyPriorityA - storyPriorityB;
|
|
607
631
|
const priorityA = a.priority ?? Number.MAX_SAFE_INTEGER;
|
|
608
632
|
const priorityB = b.priority ?? Number.MAX_SAFE_INTEGER;
|
|
609
633
|
if (priorityA !== priorityB)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkOnTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/WorkOnTasksService.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAgD,MAAM,eAAe,CAAC;AAC3F,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAuB,MAAM,WAAW,CAAC;AAEvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAiB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC1G,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAsFrE,MAAM,WAAW,kBAAmB,SAAQ,oBAAoB;IAC9D,SAAS,EAAE,mBAAmB,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,iBAAiB,CAAC;IAC7B,OAAO,EAAE,mBAAmB,EAAE,CAAC;IAC/B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA6wBD,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"WorkOnTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/WorkOnTasksService.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,7 +38,7 @@ const DEFAULT_CODE_WRITER_PROMPT = [
|
|
|
38
38
|
"Use docdex snippets to ground decisions (data model, offline/online expectations, constraints, acceptance criteria).",
|
|
39
39
|
"When a comment backlog is provided (code-review/qa-tasks), resolve those items first and do not mark a slug resolved unless you made real repo changes that address it.",
|
|
40
40
|
"Do not ignore the main task description or acceptance criteria; address them after resolving comment backlog items.",
|
|
41
|
-
"Re-use existing store/slices/adapters and
|
|
41
|
+
"Re-use existing store/slices/adapters and documented product patterns; avoid inventing new backends or ad-hoc actions. Prioritize product behavior changes first, then align tests.",
|
|
42
42
|
"Do not hardcode ports. Read PORT/HOST (or MCODA_QA_PORT/MCODA_QA_HOST) from env, and document base URLs with http://localhost:<PORT> placeholders when needed.",
|
|
43
43
|
"Do not create docs/qa/* reports unless the task explicitly requests one. Work-on-tasks should not generate QA reports.",
|
|
44
44
|
"If you encounter merge conflicts or conflict markers, stop and report; do not attempt to merge them.",
|
|
@@ -1330,6 +1330,125 @@ const findOutOfScopeActionPaths = (actions, workspaceRoot) => {
|
|
|
1330
1330
|
return Array.from(invalid);
|
|
1331
1331
|
};
|
|
1332
1332
|
const normalizePaths = (workspaceRoot, files) => files.map((f) => PathHelper.resolveRelativePath(workspaceRoot, f));
|
|
1333
|
+
const DOC_CONTEXT_QUERY_TOKEN_LIMIT = 24;
|
|
1334
|
+
const DOC_CONTEXT_QUERY_MAX_CHARS = 320;
|
|
1335
|
+
const DOC_CONTEXT_STOP_WORDS = new Set([
|
|
1336
|
+
"and",
|
|
1337
|
+
"the",
|
|
1338
|
+
"for",
|
|
1339
|
+
"with",
|
|
1340
|
+
"that",
|
|
1341
|
+
"this",
|
|
1342
|
+
"from",
|
|
1343
|
+
"into",
|
|
1344
|
+
"onto",
|
|
1345
|
+
"task",
|
|
1346
|
+
"story",
|
|
1347
|
+
"epic",
|
|
1348
|
+
"add",
|
|
1349
|
+
"update",
|
|
1350
|
+
"implement",
|
|
1351
|
+
"ensure",
|
|
1352
|
+
"support",
|
|
1353
|
+
"across",
|
|
1354
|
+
"should",
|
|
1355
|
+
"must",
|
|
1356
|
+
"able",
|
|
1357
|
+
"when",
|
|
1358
|
+
"then",
|
|
1359
|
+
"than",
|
|
1360
|
+
"using",
|
|
1361
|
+
"user",
|
|
1362
|
+
"users",
|
|
1363
|
+
"project",
|
|
1364
|
+
]);
|
|
1365
|
+
const TEST_CONTEXT_PATH_PATTERN = /(^|[\\/])(__tests__|tests?|specs?|fixtures?|mocks?)([\\/]|$)|\.(test|spec)\.[cm]?[jt]sx?$/i;
|
|
1366
|
+
const DOC_PATH_PATTERN = /(^|[\\/])docs?([\\/]|$)|\.(md|mdx|rst|adoc)$/i;
|
|
1367
|
+
const TEST_TASK_HINT_PATTERN = /\b(test|tests|qa|quality|e2e|unit|integration|spec|regression|coverage|benchmark|throughput|resilience|audit)\b/i;
|
|
1368
|
+
const DOC_TASK_HINT_PATTERN = /\b(doc|docs|documentation|readme|sds|rfp|openapi|changelog|guide)\b/i;
|
|
1369
|
+
const normalizeMatcherPath = (value) => value.replace(/\\/g, "/").replace(/^\.\/+/, "").toLowerCase();
|
|
1370
|
+
const isTestLikePath = (value) => {
|
|
1371
|
+
if (!value)
|
|
1372
|
+
return false;
|
|
1373
|
+
return TEST_CONTEXT_PATH_PATTERN.test(normalizeMatcherPath(value));
|
|
1374
|
+
};
|
|
1375
|
+
const isDocumentationPath = (value) => {
|
|
1376
|
+
if (!value)
|
|
1377
|
+
return false;
|
|
1378
|
+
return DOC_PATH_PATTERN.test(normalizeMatcherPath(value));
|
|
1379
|
+
};
|
|
1380
|
+
const buildTaskTextBlob = (task) => [
|
|
1381
|
+
task.type,
|
|
1382
|
+
task.title,
|
|
1383
|
+
task.description,
|
|
1384
|
+
task.epicTitle,
|
|
1385
|
+
task.storyTitle,
|
|
1386
|
+
task.storyDescription,
|
|
1387
|
+
...(task.acceptanceCriteria ?? []),
|
|
1388
|
+
]
|
|
1389
|
+
.filter((value) => typeof value === "string" && value.trim().length > 0)
|
|
1390
|
+
.join(" ");
|
|
1391
|
+
const isTestFocusedTask = (task) => TEST_TASK_HINT_PATTERN.test(buildTaskTextBlob(task)) ||
|
|
1392
|
+
(task.type ?? "").toLowerCase().includes("test") ||
|
|
1393
|
+
(task.type ?? "").toLowerCase().includes("qa");
|
|
1394
|
+
const isDocumentationFocusedTask = (task) => DOC_TASK_HINT_PATTERN.test(buildTaskTextBlob(task));
|
|
1395
|
+
const normalizeBoolean = (value) => value === true || value === "true";
|
|
1396
|
+
const allowsTestsOnlyCompletion = (task, metadata, allowedFiles) => {
|
|
1397
|
+
if (normalizeBoolean(metadata.allow_doc_edits) || normalizeBoolean(metadata.allowDocEdits)) {
|
|
1398
|
+
return true;
|
|
1399
|
+
}
|
|
1400
|
+
if (normalizeBoolean(metadata.allow_large_doc_edits) || normalizeBoolean(metadata.allowLargeDocEdits)) {
|
|
1401
|
+
return true;
|
|
1402
|
+
}
|
|
1403
|
+
if (normalizeBoolean(metadata.allow_tests_only_completion) || normalizeBoolean(metadata.allowTestOnlyCompletion)) {
|
|
1404
|
+
return true;
|
|
1405
|
+
}
|
|
1406
|
+
if (isTestFocusedTask(task) || isDocumentationFocusedTask(task)) {
|
|
1407
|
+
return true;
|
|
1408
|
+
}
|
|
1409
|
+
if (allowedFiles.length > 0 && allowedFiles.every((file) => isTestLikePath(file) || isDocumentationPath(file))) {
|
|
1410
|
+
return true;
|
|
1411
|
+
}
|
|
1412
|
+
return false;
|
|
1413
|
+
};
|
|
1414
|
+
const hasProductTouchedFiles = (touchedFiles) => touchedFiles.some((file) => !isTestLikePath(file) && !isDocumentationPath(file));
|
|
1415
|
+
const buildDocContextQuery = (task, allowedFiles) => {
|
|
1416
|
+
const seeds = [
|
|
1417
|
+
task.key,
|
|
1418
|
+
task.title,
|
|
1419
|
+
task.description,
|
|
1420
|
+
task.epicTitle,
|
|
1421
|
+
task.storyTitle,
|
|
1422
|
+
task.storyDescription,
|
|
1423
|
+
...(task.acceptanceCriteria ?? []),
|
|
1424
|
+
...allowedFiles.map((file) => path.basename(file)),
|
|
1425
|
+
];
|
|
1426
|
+
const tokens = [];
|
|
1427
|
+
const seen = new Set();
|
|
1428
|
+
for (const seed of seeds) {
|
|
1429
|
+
if (!seed)
|
|
1430
|
+
continue;
|
|
1431
|
+
const rawTokens = seed.toLowerCase().split(/[^a-z0-9]+/g);
|
|
1432
|
+
for (const token of rawTokens) {
|
|
1433
|
+
if (token.length < 3)
|
|
1434
|
+
continue;
|
|
1435
|
+
if (DOC_CONTEXT_STOP_WORDS.has(token))
|
|
1436
|
+
continue;
|
|
1437
|
+
if (seen.has(token))
|
|
1438
|
+
continue;
|
|
1439
|
+
seen.add(token);
|
|
1440
|
+
tokens.push(token);
|
|
1441
|
+
if (tokens.length >= DOC_CONTEXT_QUERY_TOKEN_LIMIT)
|
|
1442
|
+
break;
|
|
1443
|
+
}
|
|
1444
|
+
if (tokens.length >= DOC_CONTEXT_QUERY_TOKEN_LIMIT)
|
|
1445
|
+
break;
|
|
1446
|
+
}
|
|
1447
|
+
if (!tokens.length)
|
|
1448
|
+
return undefined;
|
|
1449
|
+
const query = tokens.join(" ").slice(0, DOC_CONTEXT_QUERY_MAX_CHARS).trim();
|
|
1450
|
+
return query || undefined;
|
|
1451
|
+
};
|
|
1333
1452
|
const resolveLockTtlSeconds = (maxAgentSeconds) => {
|
|
1334
1453
|
if (!maxAgentSeconds || maxAgentSeconds <= 0)
|
|
1335
1454
|
return TASK_LOCK_TTL_SECONDS;
|
|
@@ -2141,11 +2260,13 @@ export class WorkOnTasksService {
|
|
|
2141
2260
|
await this.logTask(taskRunId, `${phase}:${status}`, phase, payload);
|
|
2142
2261
|
await this.checkpoint(jobId, `task:${taskKey}:${phase}:${status}`, payload);
|
|
2143
2262
|
}
|
|
2144
|
-
async gatherDocContext(projectKey, docLinks = []) {
|
|
2263
|
+
async gatherDocContext(task, projectKey, docLinks = [], allowedFiles = []) {
|
|
2145
2264
|
const warnings = [];
|
|
2146
2265
|
const parts = [];
|
|
2147
2266
|
let openApiIncluded = false;
|
|
2148
2267
|
let docdexUnavailable = false;
|
|
2268
|
+
const includeTestDocs = isTestFocusedTask(task);
|
|
2269
|
+
const docQuery = buildDocContextQuery(task, allowedFiles);
|
|
2149
2270
|
const shouldIncludeDocType = (docType) => {
|
|
2150
2271
|
if (docType.toUpperCase() !== "OPENAPI")
|
|
2151
2272
|
return true;
|
|
@@ -2165,8 +2286,12 @@ export class WorkOnTasksService {
|
|
|
2165
2286
|
}
|
|
2166
2287
|
}
|
|
2167
2288
|
try {
|
|
2168
|
-
|
|
2169
|
-
|
|
2289
|
+
let docs = await this.deps.docdex.search({ projectKey, profile: "workspace-code", query: docQuery });
|
|
2290
|
+
if (!docs.length && docQuery) {
|
|
2291
|
+
docs = await this.deps.docdex.search({ projectKey, profile: "workspace-code" });
|
|
2292
|
+
}
|
|
2293
|
+
const filteredDocs = docs.filter((doc) => !isDocContextExcluded(doc.path ?? doc.title ?? doc.id, false) &&
|
|
2294
|
+
(includeTestDocs || !isTestLikePath(doc.path ?? doc.title ?? doc.id)));
|
|
2170
2295
|
const resolveDocType = (doc) => {
|
|
2171
2296
|
const content = doc.segments?.[0]?.content ?? doc.content ?? "";
|
|
2172
2297
|
const normalized = normalizeDocType({
|
|
@@ -4308,7 +4433,7 @@ export class WorkOnTasksService {
|
|
|
4308
4433
|
docWarnings = ["Gateway handoff present; skipping docdex context gathering."];
|
|
4309
4434
|
}
|
|
4310
4435
|
else {
|
|
4311
|
-
const docContext = await this.gatherDocContext(request.projectKey, docLinks);
|
|
4436
|
+
const docContext = await this.gatherDocContext(task.task, request.projectKey, docLinks, allowedFiles);
|
|
4312
4437
|
docSummary = docContext.summary;
|
|
4313
4438
|
docWarnings = docContext.warnings;
|
|
4314
4439
|
docdexUnavailable = docContext.docdexUnavailable;
|
|
@@ -5672,6 +5797,43 @@ export class WorkOnTasksService {
|
|
|
5672
5797
|
await this.deps.jobService.updateJobStatus(job.id, "running", { processedItems: index + 1 });
|
|
5673
5798
|
continue taskLoop;
|
|
5674
5799
|
}
|
|
5800
|
+
const allowTestOnlyCompletion = allowsTestsOnlyCompletion(task.task, metadata, allowedFiles);
|
|
5801
|
+
if (!allowTestOnlyCompletion && !hasProductTouchedFiles(touched)) {
|
|
5802
|
+
const body = [
|
|
5803
|
+
"[work-on-tasks]",
|
|
5804
|
+
"Completion guard blocked finalization.",
|
|
5805
|
+
"Only test/documentation files were touched for a task that appears to require product implementation changes.",
|
|
5806
|
+
`Touched files: ${touched.join(", ")}`,
|
|
5807
|
+
"Update product code (or set metadata.allow_tests_only_completion=true for explicitly test-only tasks) and rerun.",
|
|
5808
|
+
].join("\n");
|
|
5809
|
+
await this.deps.workspaceRepo.createTaskComment({
|
|
5810
|
+
taskId: task.task.id,
|
|
5811
|
+
taskRunId: taskRun.id,
|
|
5812
|
+
jobId: job.id,
|
|
5813
|
+
sourceCommand: "work-on-tasks",
|
|
5814
|
+
authorType: "agent",
|
|
5815
|
+
authorAgentId: agent.id,
|
|
5816
|
+
category: "completion_guard",
|
|
5817
|
+
body,
|
|
5818
|
+
createdAt: new Date().toISOString(),
|
|
5819
|
+
metadata: { reason: "tests_only_changes", touchedFiles: touched, allowedFiles },
|
|
5820
|
+
});
|
|
5821
|
+
await this.logTask(taskRun.id, `Completion guard blocked task: non-product touched files only (${touched.join(", ")}).`, "execution");
|
|
5822
|
+
await this.updateTaskPhase(job.id, taskRun.id, task.task.key, "finalize", "error", {
|
|
5823
|
+
error: "tests_only_changes",
|
|
5824
|
+
touchedFiles: touched,
|
|
5825
|
+
});
|
|
5826
|
+
await this.stateService.markChangesRequested(task.task, { failed_reason: "tests_only_changes", touched_files: touched }, statusContext);
|
|
5827
|
+
await this.deps.workspaceRepo.updateTaskRun(taskRun.id, {
|
|
5828
|
+
status: "failed",
|
|
5829
|
+
finishedAt: new Date().toISOString(),
|
|
5830
|
+
});
|
|
5831
|
+
setFailureReason("tests_only_changes");
|
|
5832
|
+
results.push({ taskKey: task.task.key, status: "failed", notes: "tests_only_changes" });
|
|
5833
|
+
taskStatus = "failed";
|
|
5834
|
+
await this.deps.jobService.updateJobStatus(job.id, "running", { processedItems: index + 1 });
|
|
5835
|
+
continue taskLoop;
|
|
5836
|
+
}
|
|
5675
5837
|
}
|
|
5676
5838
|
if (runVcsPhase) {
|
|
5677
5839
|
const vcsOutcome = await runVcsPhase({ allowResultUpdate: true, reason: "primary" });
|
|
@@ -63,6 +63,24 @@ export declare class CreateTasksService {
|
|
|
63
63
|
private ensureRatingService;
|
|
64
64
|
private prepareDocs;
|
|
65
65
|
private resolveDefaultDocInputs;
|
|
66
|
+
private walkDocCandidates;
|
|
67
|
+
private scoreDocCandidate;
|
|
68
|
+
private findFuzzyDocInputs;
|
|
69
|
+
private normalizeStructurePathToken;
|
|
70
|
+
private extractStructureTargets;
|
|
71
|
+
private normalizeServiceName;
|
|
72
|
+
private deriveServiceFromPathToken;
|
|
73
|
+
private addServiceAlias;
|
|
74
|
+
private extractServiceMentionsFromText;
|
|
75
|
+
private resolveServiceMentionFromPhrase;
|
|
76
|
+
private collectDependencyStatements;
|
|
77
|
+
private sortServicesByDependency;
|
|
78
|
+
private buildServiceDependencyGraph;
|
|
79
|
+
private orderStoryTasksByDependencies;
|
|
80
|
+
private applyServiceDependencySequencing;
|
|
81
|
+
private shouldInjectStructureBootstrap;
|
|
82
|
+
private injectStructureBootstrapPlan;
|
|
83
|
+
private enforceStoryScopedDependencies;
|
|
66
84
|
private buildQaPreflight;
|
|
67
85
|
private buildQaOverrides;
|
|
68
86
|
private buildDocContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/planning/CreateTasksService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAEL,OAAO,EACP,gBAAgB,EAEhB,QAAQ,EAER,iBAAiB,EAEjB,OAAO,EACP,mBAAmB,EACpB,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,YAAY,EAAkB,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAQxE,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,YAAY,EAAE,iBAAiB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"CreateTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/planning/CreateTasksService.ts"],"names":[],"mappings":"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"}
|