@mcoda/core 0.1.19 → 0.1.20

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.
Files changed (55) hide show
  1. package/dist/api/QaTasksApi.d.ts.map +1 -1
  2. package/dist/api/QaTasksApi.js +3 -0
  3. package/dist/prompts/PdrPrompts.d.ts.map +1 -1
  4. package/dist/prompts/PdrPrompts.js +22 -8
  5. package/dist/prompts/SdsPrompts.d.ts.map +1 -1
  6. package/dist/prompts/SdsPrompts.js +53 -34
  7. package/dist/services/backlog/BacklogService.d.ts.map +1 -1
  8. package/dist/services/backlog/BacklogService.js +3 -0
  9. package/dist/services/backlog/TaskOrderingService.d.ts +9 -0
  10. package/dist/services/backlog/TaskOrderingService.d.ts.map +1 -1
  11. package/dist/services/backlog/TaskOrderingService.js +251 -35
  12. package/dist/services/docs/DocsService.d.ts.map +1 -1
  13. package/dist/services/docs/DocsService.js +487 -71
  14. package/dist/services/docs/review/gates/PdrFolderTreeGate.d.ts +7 -0
  15. package/dist/services/docs/review/gates/PdrFolderTreeGate.d.ts.map +1 -0
  16. package/dist/services/docs/review/gates/PdrFolderTreeGate.js +151 -0
  17. package/dist/services/docs/review/gates/PdrNoUnresolvedItemsGate.d.ts +7 -0
  18. package/dist/services/docs/review/gates/PdrNoUnresolvedItemsGate.d.ts.map +1 -0
  19. package/dist/services/docs/review/gates/PdrNoUnresolvedItemsGate.js +109 -0
  20. package/dist/services/docs/review/gates/PdrTechStackRationaleGate.d.ts +7 -0
  21. package/dist/services/docs/review/gates/PdrTechStackRationaleGate.d.ts.map +1 -0
  22. package/dist/services/docs/review/gates/PdrTechStackRationaleGate.js +128 -0
  23. package/dist/services/docs/review/gates/SdsFolderTreeGate.d.ts +7 -0
  24. package/dist/services/docs/review/gates/SdsFolderTreeGate.d.ts.map +1 -0
  25. package/dist/services/docs/review/gates/SdsFolderTreeGate.js +153 -0
  26. package/dist/services/docs/review/gates/SdsNoUnresolvedItemsGate.d.ts +7 -0
  27. package/dist/services/docs/review/gates/SdsNoUnresolvedItemsGate.d.ts.map +1 -0
  28. package/dist/services/docs/review/gates/SdsNoUnresolvedItemsGate.js +109 -0
  29. package/dist/services/docs/review/gates/SdsTechStackRationaleGate.d.ts +7 -0
  30. package/dist/services/docs/review/gates/SdsTechStackRationaleGate.d.ts.map +1 -0
  31. package/dist/services/docs/review/gates/SdsTechStackRationaleGate.js +128 -0
  32. package/dist/services/execution/QaTasksService.d.ts +6 -0
  33. package/dist/services/execution/QaTasksService.d.ts.map +1 -1
  34. package/dist/services/execution/QaTasksService.js +278 -95
  35. package/dist/services/execution/TaskSelectionService.d.ts +3 -0
  36. package/dist/services/execution/TaskSelectionService.d.ts.map +1 -1
  37. package/dist/services/execution/TaskSelectionService.js +33 -0
  38. package/dist/services/execution/WorkOnTasksService.d.ts +4 -0
  39. package/dist/services/execution/WorkOnTasksService.d.ts.map +1 -1
  40. package/dist/services/execution/WorkOnTasksService.js +141 -19
  41. package/dist/services/openapi/OpenApiService.d.ts.map +1 -1
  42. package/dist/services/openapi/OpenApiService.js +43 -4
  43. package/dist/services/planning/CreateTasksService.d.ts +10 -0
  44. package/dist/services/planning/CreateTasksService.d.ts.map +1 -1
  45. package/dist/services/planning/CreateTasksService.js +480 -44
  46. package/dist/services/planning/RefineTasksService.d.ts +1 -0
  47. package/dist/services/planning/RefineTasksService.d.ts.map +1 -1
  48. package/dist/services/planning/RefineTasksService.js +88 -2
  49. package/dist/services/review/CodeReviewService.d.ts +6 -0
  50. package/dist/services/review/CodeReviewService.d.ts.map +1 -1
  51. package/dist/services/review/CodeReviewService.js +260 -41
  52. package/dist/services/shared/ProjectGuidance.d.ts +18 -2
  53. package/dist/services/shared/ProjectGuidance.d.ts.map +1 -1
  54. package/dist/services/shared/ProjectGuidance.js +535 -34
  55. package/package.json +6 -6
@@ -3,6 +3,7 @@ import { AgentService } from "@mcoda/agents";
3
3
  import { DocdexClient } from "@mcoda/integrations";
4
4
  import { GlobalRepository, WorkspaceRepository, Connection } from "@mcoda/db";
5
5
  import { PathHelper, READY_TO_CODE_REVIEW, normalizeReviewStatuses } from "@mcoda/shared";
6
+ import YAML from "yaml";
6
7
  import { JobService } from "../jobs/JobService.js";
7
8
  import { RoutingService } from "../agents/RoutingService.js";
8
9
  import { classifyTask } from "./TaskOrderingHeuristics.js";
@@ -10,6 +11,8 @@ const DEFAULT_STATUSES = ["not_started", "in_progress", "changes_requested", REA
10
11
  const DONE_STATUSES = new Set(["completed", "cancelled"]);
11
12
  const DEFAULT_STAGE_ORDER = ["foundation", "backend", "frontend", "other"];
12
13
  const PLANNING_DOC_HINT_PATTERN = /(sds|pdr|rfp|requirements|architecture|openapi|swagger|design)/i;
14
+ const OPENAPI_METHODS = new Set(["get", "post", "put", "patch", "delete", "options", "head", "trace"]);
15
+ const OPENAPI_HINTS_LIMIT = 20;
13
16
  const STATUS_RANK = {
14
17
  in_progress: 0,
15
18
  changes_requested: 0,
@@ -31,6 +34,28 @@ const normalizeStatuses = (statuses) => {
31
34
  return normalizeReviewStatuses(normalized);
32
35
  };
33
36
  const estimateTokens = (text) => Math.max(1, Math.ceil((text ?? "").length / 4));
37
+ const isPlainObject = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
38
+ const parseStructuredDoc = (raw) => {
39
+ if (!raw || raw.trim().length === 0)
40
+ return undefined;
41
+ try {
42
+ const parsed = YAML.parse(raw);
43
+ if (isPlainObject(parsed))
44
+ return parsed;
45
+ }
46
+ catch {
47
+ // continue
48
+ }
49
+ try {
50
+ const parsed = JSON.parse(raw);
51
+ if (isPlainObject(parsed))
52
+ return parsed;
53
+ }
54
+ catch {
55
+ // ignore invalid parse
56
+ }
57
+ return undefined;
58
+ };
34
59
  const SDS_DEPENDENCY_GUIDE = [
35
60
  "SDS hints for dependency-aware ordering:",
36
61
  "- Enforce topological ordering: never place a task before any of its dependencies.",
@@ -202,6 +227,77 @@ export class TaskOrderingService {
202
227
  this.docdex = docdex;
203
228
  this.recordTelemetry = recordTelemetry;
204
229
  }
230
+ classifyDocContextKind(doc) {
231
+ const type = (doc.docType ?? "").toLowerCase();
232
+ const label = `${doc.path ?? ""} ${doc.title ?? ""}`.toLowerCase();
233
+ if (type.includes("sds") || /\bsds\b/.test(label))
234
+ return "sds";
235
+ if (type.includes("openapi") || type.includes("swagger") || /(openapi|swagger)/.test(label))
236
+ return "openapi";
237
+ return "fallback";
238
+ }
239
+ buildOpenApiHintSummary(docs) {
240
+ const lines = [];
241
+ const countEntries = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string").length : 0;
242
+ for (const doc of docs) {
243
+ if (this.classifyDocContextKind(doc) !== "openapi")
244
+ continue;
245
+ const rawContent = doc.content && doc.content.trim().length > 0 ? doc.content : (doc.segments ?? []).map((segment) => segment.content).join("\n\n");
246
+ const parsed = parseStructuredDoc(rawContent);
247
+ if (!parsed)
248
+ continue;
249
+ const paths = parsed.paths;
250
+ if (!isPlainObject(paths))
251
+ continue;
252
+ for (const [apiPath, pathItem] of Object.entries(paths)) {
253
+ if (!isPlainObject(pathItem))
254
+ continue;
255
+ for (const [method, operation] of Object.entries(pathItem)) {
256
+ const normalizedMethod = method.toLowerCase();
257
+ if (!OPENAPI_METHODS.has(normalizedMethod))
258
+ continue;
259
+ if (!isPlainObject(operation))
260
+ continue;
261
+ const hints = operation["x-mcoda-task-hints"];
262
+ if (!isPlainObject(hints))
263
+ continue;
264
+ const service = typeof hints.service === "string" ? hints.service : "-";
265
+ const capability = typeof hints.capability === "string" ? hints.capability : "-";
266
+ const stage = typeof hints.stage === "string" ? hints.stage : "-";
267
+ const complexity = typeof hints.complexity === "number" && Number.isFinite(hints.complexity) ? hints.complexity.toFixed(1) : "-";
268
+ const dependsOn = Array.isArray(hints.depends_on_operations)
269
+ ? hints.depends_on_operations.filter((entry) => typeof entry === "string").length
270
+ : 0;
271
+ const tests = isPlainObject(hints.test_requirements) ? hints.test_requirements : undefined;
272
+ const unitCount = countEntries(tests?.unit);
273
+ const componentCount = countEntries(tests?.component);
274
+ const integrationCount = countEntries(tests?.integration);
275
+ const apiCount = countEntries(tests?.api);
276
+ lines.push(`- ${normalizedMethod.toUpperCase()} ${apiPath} :: service=${service}; capability=${capability}; stage=${stage}; complexity=${complexity}; deps=${dependsOn}; tests(u/c/i/a)=${unitCount}/${componentCount}/${integrationCount}/${apiCount}`);
277
+ if (lines.length >= OPENAPI_HINTS_LIMIT) {
278
+ return lines.join("\n");
279
+ }
280
+ }
281
+ }
282
+ }
283
+ return lines.join("\n");
284
+ }
285
+ enforcePlanningContextPolicy(policy, context) {
286
+ if (policy === "best_effort")
287
+ return;
288
+ if (policy === "require_any") {
289
+ if (!context) {
290
+ throw new Error("Planning context is required but no planning documents were resolved (policy=require_any).");
291
+ }
292
+ return;
293
+ }
294
+ if (!context) {
295
+ throw new Error("Planning context is required from SDS/OpenAPI sources, but none were resolved (policy=require_sds_or_openapi).");
296
+ }
297
+ if (context.kind !== "sds" && context.kind !== "openapi") {
298
+ throw new Error(`Planning context policy require_sds_or_openapi rejected source '${context.source}' (kind=${context.kind}).`);
299
+ }
300
+ }
205
301
  static async create(workspace, options = {}) {
206
302
  const dbPath = PathHelper.getWorkspaceDbPath(workspace.workspaceRoot);
207
303
  try {
@@ -232,11 +328,14 @@ export class TaskOrderingService {
232
328
  async buildDocContext(projectKey, warnings) {
233
329
  try {
234
330
  let docs = await this.docdex.search({ docType: "SDS", projectKey });
331
+ if (!docs.length) {
332
+ docs = await this.docdex.search({ docType: "OPENAPI", projectKey });
333
+ }
235
334
  if (!docs.length) {
236
335
  docs = await this.docdex.search({
237
336
  projectKey,
238
337
  profile: "workspace-code",
239
- query: "sds requirements architecture openapi",
338
+ query: "sds requirements architecture openapi swagger",
240
339
  });
241
340
  }
242
341
  if (!docs.length)
@@ -246,6 +345,7 @@ export class TaskOrderingService {
246
345
  const label = `${entry.path ?? ""} ${entry.title ?? ""}`.toLowerCase();
247
346
  return type.includes("sds") || type.includes("pdr") || type.includes("rfp") || PLANNING_DOC_HINT_PATTERN.test(label);
248
347
  }) ?? docs[0];
348
+ const kind = this.classifyDocContextKind(doc);
249
349
  const segments = (doc.segments ?? []).slice(0, 3);
250
350
  const body = segments.length > 0
251
351
  ? segments
@@ -256,9 +356,15 @@ export class TaskOrderingService {
256
356
  })
257
357
  .join("\n\n")
258
358
  : doc.content ?? "";
359
+ const openApiHints = this.buildOpenApiHintSummary([doc]);
360
+ const contextBlocks = ["[Planning context]", doc.title ?? doc.path ?? doc.id, body];
361
+ if (openApiHints) {
362
+ contextBlocks.push(`[OPENAPI_HINTS]\n${openApiHints}`);
363
+ }
259
364
  return {
260
- content: ["[SDS context]", doc.title ?? doc.path ?? doc.id, body].filter(Boolean).join("\n\n"),
365
+ content: contextBlocks.filter(Boolean).join("\n\n"),
261
366
  source: doc.id ?? doc.path ?? "sds",
367
+ kind,
262
368
  };
263
369
  }
264
370
  catch (error) {
@@ -437,6 +543,67 @@ export class TaskOrderingService {
437
543
  const inferred = classifyTask({ title: task.title, description: task.description, type: task.type ?? undefined });
438
544
  return { stage: inferred.stage, foundation: inferred.foundation };
439
545
  }
546
+ complexityBand(score) {
547
+ if (score < 12)
548
+ return "low";
549
+ if (score < 24)
550
+ return "medium";
551
+ if (score < 40)
552
+ return "high";
553
+ return "very_high";
554
+ }
555
+ buildOrderingMetadata(tasks, impact, missingContext, docContext) {
556
+ const metadataByTask = new Map();
557
+ const complexityByTask = new Map();
558
+ for (const task of tasks) {
559
+ const classification = this.resolveClassification(task);
560
+ const inferred = classifyTask({ title: task.title, description: task.description, type: task.type ?? undefined });
561
+ const impactEntry = impact.get(task.id) ?? { direct: 0, total: 0 };
562
+ const dependencyCount = task.dependencies.length;
563
+ const missingContextOpen = missingContext.has(task.id);
564
+ const textLength = `${task.title ?? ""} ${task.description ?? ""}`.trim().length;
565
+ const textWeight = Math.min(6, Math.ceil(textLength / 200));
566
+ const stageWeight = classification.stage === "backend" ? 2 : classification.stage === "frontend" ? 1.5 : classification.stage === "foundation" ? 1.2 : 1;
567
+ let complexityScore = (task.story_points ?? 0) * 5 +
568
+ impactEntry.total * 3 +
569
+ dependencyCount * 2 +
570
+ textWeight * stageWeight +
571
+ (classification.foundation ? 2 : 0) +
572
+ (missingContextOpen ? 4 : 0);
573
+ complexityScore = Number(Math.max(1, complexityScore).toFixed(2));
574
+ complexityByTask.set(task.id, complexityScore);
575
+ const existingMetadata = task.metadata ?? {};
576
+ const existingOrdering = existingMetadata && typeof existingMetadata.ordering === "object" && !Array.isArray(existingMetadata.ordering)
577
+ ? existingMetadata.ordering
578
+ : {};
579
+ const reasons = [...inferred.reasons];
580
+ if (typeof existingMetadata.stage === "string") {
581
+ reasons.unshift(`metadata:stage:${String(existingMetadata.stage).toLowerCase()}`);
582
+ }
583
+ if (typeof existingMetadata.foundation === "boolean") {
584
+ reasons.unshift(`metadata:foundation:${existingMetadata.foundation ? "true" : "false"}`);
585
+ }
586
+ const mergedMetadata = {
587
+ ...existingMetadata,
588
+ stage: classification.stage,
589
+ foundation: classification.foundation,
590
+ ordering: {
591
+ ...existingOrdering,
592
+ stage: classification.stage,
593
+ foundation: classification.foundation,
594
+ dependencyImpact: impactEntry,
595
+ dependencyCount,
596
+ complexityScore,
597
+ complexityBand: this.complexityBand(complexityScore),
598
+ missingContextOpen,
599
+ classificationReasons: reasons,
600
+ docContextSource: docContext?.source,
601
+ },
602
+ };
603
+ metadataByTask.set(task.id, mergedMetadata);
604
+ }
605
+ return { metadataByTask, complexityByTask };
606
+ }
440
607
  buildDependencyGraph(tasks, deps) {
441
608
  const taskIds = new Set(tasks.map((task) => task.id));
442
609
  const graph = new Map();
@@ -478,7 +645,7 @@ export class TaskOrderingService {
478
645
  }
479
646
  return false;
480
647
  }
481
- async injectFoundationDependencies(tasks, deps, warnings) {
648
+ async injectFoundationDependencies(tasks, deps, warnings, persist) {
482
649
  const classification = new Map();
483
650
  for (const task of tasks) {
484
651
  classification.set(task.id, this.resolveClassification(task));
@@ -528,7 +695,9 @@ export class TaskOrderingService {
528
695
  }
529
696
  return;
530
697
  }
531
- await this.repo.insertTaskDependencies(inserts, true);
698
+ if (persist) {
699
+ await this.repo.insertTaskDependencies(inserts, true);
700
+ }
532
701
  for (const insert of inserts) {
533
702
  const depList = deps.get(insert.taskId) ?? [];
534
703
  const dependsOn = taskById.get(insert.dependsOnTaskId);
@@ -540,7 +709,12 @@ export class TaskOrderingService {
540
709
  });
541
710
  deps.set(insert.taskId, depList);
542
711
  }
543
- warnings.push(`Injected ${inserts.length} inferred foundation deps.`);
712
+ if (persist) {
713
+ warnings.push(`Injected ${inserts.length} inferred foundation deps.`);
714
+ }
715
+ else {
716
+ warnings.push(`Dry run: inferred ${inserts.length} foundation deps (not persisted).`);
717
+ }
544
718
  if (skippedCycles > 0) {
545
719
  warnings.push(`Skipped ${skippedCycles} inferred foundation deps due to cycles.`);
546
720
  if (skippedEdges.length > 0) {
@@ -548,7 +722,7 @@ export class TaskOrderingService {
548
722
  }
549
723
  }
550
724
  }
551
- async applyInferredDependencies(tasks, deps, inferred, warnings) {
725
+ async applyInferredDependencies(tasks, deps, inferred, warnings, persist) {
552
726
  if (inferred.length === 0)
553
727
  return;
554
728
  const taskByKey = new Map(tasks.map((task) => [task.key, task]));
@@ -598,7 +772,9 @@ export class TaskOrderingService {
598
772
  }
599
773
  return;
600
774
  }
601
- await this.repo.insertTaskDependencies(inserts, true);
775
+ if (persist) {
776
+ await this.repo.insertTaskDependencies(inserts, true);
777
+ }
602
778
  const taskById = new Map(tasks.map((task) => [task.id, task]));
603
779
  for (const insert of inserts) {
604
780
  const depList = deps.get(insert.taskId) ?? [];
@@ -611,7 +787,12 @@ export class TaskOrderingService {
611
787
  });
612
788
  deps.set(insert.taskId, depList);
613
789
  }
614
- warnings.push(`Applied ${inserts.length} inferred agent deps.`);
790
+ if (persist) {
791
+ warnings.push(`Applied ${inserts.length} inferred agent deps.`);
792
+ }
793
+ else {
794
+ warnings.push(`Dry run: inferred ${inserts.length} agent deps (not persisted).`);
795
+ }
615
796
  if (skippedCycles > 0) {
616
797
  warnings.push(`Skipped ${skippedCycles} inferred agent deps due to cycles.`);
617
798
  if (skippedEdges.length > 0) {
@@ -619,7 +800,7 @@ export class TaskOrderingService {
619
800
  }
620
801
  }
621
802
  }
622
- compareTasks(a, b, impact, agentRank, stageOrderMap) {
803
+ compareTasks(a, b, impact, complexityByTask, missingContext, agentRank, stageOrderMap) {
623
804
  const epicPriorityA = a.epic_priority ?? Number.MAX_SAFE_INTEGER;
624
805
  const epicPriorityB = b.epic_priority ?? Number.MAX_SAFE_INTEGER;
625
806
  if (epicPriorityA !== epicPriorityB)
@@ -628,14 +809,29 @@ export class TaskOrderingService {
628
809
  const storyPriorityB = b.story_priority ?? Number.MAX_SAFE_INTEGER;
629
810
  if (storyPriorityA !== storyPriorityB)
630
811
  return storyPriorityA - storyPriorityB;
631
- const priorityA = a.priority ?? Number.MAX_SAFE_INTEGER;
632
- const priorityB = b.priority ?? Number.MAX_SAFE_INTEGER;
633
- if (priorityA !== priorityB)
634
- return priorityA - priorityB;
812
+ const missingA = missingContext.has(a.id);
813
+ const missingB = missingContext.has(b.id);
814
+ if (missingA !== missingB)
815
+ return missingA ? 1 : -1;
816
+ const classA = this.resolveClassification(a);
817
+ const classB = this.resolveClassification(b);
818
+ if (classA.foundation !== classB.foundation) {
819
+ return classA.foundation ? -1 : 1;
820
+ }
821
+ if (stageOrderMap) {
822
+ const stageA = stageOrderMap.get(classA.stage) ?? stageOrderMap.get("other") ?? Number.MAX_SAFE_INTEGER;
823
+ const stageB = stageOrderMap.get(classB.stage) ?? stageOrderMap.get("other") ?? Number.MAX_SAFE_INTEGER;
824
+ if (stageA !== stageB)
825
+ return stageA - stageB;
826
+ }
635
827
  const impactA = impact.get(a.id)?.total ?? 0;
636
828
  const impactB = impact.get(b.id)?.total ?? 0;
637
829
  if (impactA !== impactB)
638
830
  return impactB - impactA;
831
+ const complexityA = complexityByTask.get(a.id) ?? 0;
832
+ const complexityB = complexityByTask.get(b.id) ?? 0;
833
+ if (complexityA !== complexityB)
834
+ return complexityB - complexityA;
639
835
  const rankA = agentRank?.get(a.id);
640
836
  const rankB = agentRank?.get(b.id);
641
837
  if (rankA !== undefined || rankB !== undefined) {
@@ -646,17 +842,10 @@ export class TaskOrderingService {
646
842
  if (rankA !== rankB)
647
843
  return rankA - rankB;
648
844
  }
649
- const classA = this.resolveClassification(a);
650
- const classB = this.resolveClassification(b);
651
- if (classA.foundation !== classB.foundation) {
652
- return classA.foundation ? -1 : 1;
653
- }
654
- if (stageOrderMap) {
655
- const stageA = stageOrderMap.get(classA.stage) ?? stageOrderMap.get("other") ?? Number.MAX_SAFE_INTEGER;
656
- const stageB = stageOrderMap.get(classB.stage) ?? stageOrderMap.get("other") ?? Number.MAX_SAFE_INTEGER;
657
- if (stageA !== stageB)
658
- return stageA - stageB;
659
- }
845
+ const priorityA = a.priority ?? Number.MAX_SAFE_INTEGER;
846
+ const priorityB = b.priority ?? Number.MAX_SAFE_INTEGER;
847
+ if (priorityA !== priorityB)
848
+ return priorityA - priorityB;
660
849
  const spA = a.story_points ?? Number.POSITIVE_INFINITY;
661
850
  const spB = b.story_points ?? Number.POSITIVE_INFINITY;
662
851
  if (spA !== spB)
@@ -671,7 +860,7 @@ export class TaskOrderingService {
671
860
  return statusA - statusB;
672
861
  return a.key.localeCompare(b.key);
673
862
  }
674
- topologicalSort(tasks, edges, impact, agentRank, stageOrderMap) {
863
+ topologicalSort(tasks, edges, impact, complexityByTask, missingContext, agentRank, stageOrderMap) {
675
864
  const indegree = new Map();
676
865
  const taskMap = new Map(tasks.map((t) => [t.id, t]));
677
866
  for (const task of tasks) {
@@ -685,7 +874,7 @@ export class TaskOrderingService {
685
874
  }
686
875
  }
687
876
  const queue = tasks.filter((t) => (indegree.get(t.id) ?? 0) === 0);
688
- const sortQueue = () => queue.sort((a, b) => this.compareTasks(a, b, impact, agentRank, stageOrderMap));
877
+ const sortQueue = () => queue.sort((a, b) => this.compareTasks(a, b, impact, complexityByTask, missingContext, agentRank, stageOrderMap));
689
878
  sortQueue();
690
879
  const ordered = [];
691
880
  const visited = new Set();
@@ -713,7 +902,7 @@ export class TaskOrderingService {
713
902
  }
714
903
  }
715
904
  const remaining = tasks.filter((t) => !visited.has(t.id));
716
- remaining.sort((a, b) => this.compareTasks(a, b, impact, agentRank, stageOrderMap));
905
+ remaining.sort((a, b) => this.compareTasks(a, b, impact, complexityByTask, missingContext, agentRank, stageOrderMap));
717
906
  ordered.push(...remaining);
718
907
  }
719
908
  return { ordered, cycle, cycleMembers };
@@ -854,11 +1043,15 @@ export class TaskOrderingService {
854
1043
  const taskKeys = new Set(tasks.map((task) => task.key));
855
1044
  return parseDependencyInferenceOutput(output, taskKeys, context.warnings);
856
1045
  }
857
- async persistPriorities(ordered, epicMap, storyMap) {
1046
+ async persistPriorities(ordered, epicMap, storyMap, metadataByTask) {
858
1047
  await this.repo.withTransaction(async () => {
859
1048
  for (let i = 0; i < ordered.length; i += 1) {
860
1049
  const task = ordered[i];
861
- await this.repo.updateTask(task.id, { priority: i + 1 });
1050
+ const nextMetadata = metadataByTask?.get(task.id);
1051
+ await this.repo.updateTask(task.id, {
1052
+ priority: i + 1,
1053
+ metadata: nextMetadata !== undefined ? nextMetadata : undefined,
1054
+ });
862
1055
  }
863
1056
  const epicEntries = Array.from(epicMap.entries()).map(([epicId, tasks]) => ({
864
1057
  epicId,
@@ -943,10 +1136,13 @@ export class TaskOrderingService {
943
1136
  if (request.storyKey && !story) {
944
1137
  throw new Error(`Unknown user story key: ${request.storyKey} for project ${request.projectKey}`);
945
1138
  }
1139
+ const applyChanges = request.apply !== false;
1140
+ const enrichMetadata = request.enrichMetadata !== false;
1141
+ const planningContextPolicy = request.planningContextPolicy ?? "best_effort";
946
1142
  const tasks = await this.fetchTasks(project.id, epic?.id, statuses, story?.id, request.assignee);
947
1143
  const deps = await this.fetchDependencies(tasks.map((t) => t.id));
948
1144
  if (request.injectFoundationDeps !== false) {
949
- await this.injectFoundationDependencies(tasks, deps, warnings);
1145
+ await this.injectFoundationDependencies(tasks, deps, warnings, applyChanges);
950
1146
  }
951
1147
  let { nodes, dependents, missingRefs } = this.buildNodes(tasks, deps);
952
1148
  const enableAgentRanking = Boolean(request.agentName);
@@ -954,8 +1150,9 @@ export class TaskOrderingService {
954
1150
  const useAgent = enableAgentRanking || enableInference;
955
1151
  const agentStream = request.agentStream !== false;
956
1152
  let docContext;
957
- if (useAgent) {
1153
+ if (useAgent || enrichMetadata) {
958
1154
  docContext = await this.buildDocContext(project.key, warnings);
1155
+ this.enforcePlanningContextPolicy(planningContextPolicy, docContext);
959
1156
  if (docContext && commandRun && this.recordTelemetry) {
960
1157
  const contextTokens = estimateTokens(docContext.content);
961
1158
  await this.jobService.recordTokenUsage({
@@ -991,7 +1188,7 @@ export class TaskOrderingService {
991
1188
  stream: agentStream,
992
1189
  warnings,
993
1190
  });
994
- await this.applyInferredDependencies(tasks, deps, inferred, warnings);
1191
+ await this.applyInferredDependencies(tasks, deps, inferred, warnings, applyChanges);
995
1192
  ({ nodes, dependents, missingRefs } = this.buildNodes(tasks, deps));
996
1193
  }
997
1194
  catch (error) {
@@ -1008,6 +1205,9 @@ export class TaskOrderingService {
1008
1205
  if (missingContext.size > 0) {
1009
1206
  warnings.push(`Tasks with open missing_context comments: ${Array.from(missingContext).length}`);
1010
1207
  }
1208
+ if (enrichMetadata && !docContext) {
1209
+ warnings.push("Planning context unavailable: ordering metadata enrichment used task/dependency heuristics only.");
1210
+ }
1011
1211
  const stageOrder = (request.stageOrder && request.stageOrder.length > 0
1012
1212
  ? request.stageOrder
1013
1213
  : DEFAULT_STAGE_ORDER);
@@ -1021,7 +1221,10 @@ export class TaskOrderingService {
1021
1221
  DEFAULT_STAGE_ORDER.forEach((stage, idx) => stageOrderMap.set(stage, idx));
1022
1222
  }
1023
1223
  const impact = this.dependencyImpactMap(dependents);
1024
- const { ordered: initialOrder, cycle, cycleMembers } = this.topologicalSort(nodes, dependents, impact, undefined, stageOrderMap);
1224
+ const { metadataByTask, complexityByTask } = enrichMetadata
1225
+ ? this.buildOrderingMetadata(nodes, impact, missingContext, docContext)
1226
+ : { metadataByTask: new Map(), complexityByTask: new Map() };
1227
+ const { ordered: initialOrder, cycle, cycleMembers } = this.topologicalSort(nodes, dependents, impact, complexityByTask, missingContext, undefined, stageOrderMap);
1025
1228
  if (cycle) {
1026
1229
  warnings.push("Dependency cycle detected; ordering may be partial.");
1027
1230
  }
@@ -1102,12 +1305,20 @@ export class TaskOrderingService {
1102
1305
  else if (enableAgentRanking && !resolvedAgent) {
1103
1306
  warnings.push("Agent refinement skipped: no agent resolved.");
1104
1307
  }
1105
- const { ordered, cycle: cycleAfterAgent, cycleMembers: agentCycleMembers } = this.topologicalSort(nodes, dependents, impact, agentRank, stageOrderMap);
1308
+ const { ordered, cycle: cycleAfterAgent, cycleMembers: agentCycleMembers } = this.topologicalSort(nodes, dependents, impact, complexityByTask, missingContext, agentRank, stageOrderMap);
1106
1309
  const finalCycleMembers = new Set([...cycleMembers, ...agentCycleMembers]);
1107
1310
  if (cycleAfterAgent && !cycle) {
1108
1311
  warnings.push("Agent-influenced ordering encountered a cycle; used partial order.");
1109
1312
  }
1110
1313
  const prioritized = ordered;
1314
+ if (enrichMetadata) {
1315
+ for (const task of prioritized) {
1316
+ const metadata = metadataByTask.get(task.id);
1317
+ if (metadata) {
1318
+ task.metadata = metadata;
1319
+ }
1320
+ }
1321
+ }
1111
1322
  const epicMap = new Map();
1112
1323
  const storyMap = new Map();
1113
1324
  prioritized.forEach((task, idx) => {
@@ -1119,7 +1330,12 @@ export class TaskOrderingService {
1119
1330
  storyTasks.push(task);
1120
1331
  storyMap.set(task.story_id, storyTasks);
1121
1332
  });
1122
- await this.persistPriorities(prioritized, epicMap, storyMap);
1333
+ if (applyChanges) {
1334
+ await this.persistPriorities(prioritized, epicMap, storyMap, enrichMetadata ? metadataByTask : undefined);
1335
+ }
1336
+ else {
1337
+ warnings.push("Dry run: priorities and dependency inferences were not persisted.");
1338
+ }
1123
1339
  const mapped = this.mapResult(prioritized, impact, finalCycleMembers);
1124
1340
  if (job) {
1125
1341
  await this.jobService.updateJobStatus(job.id, "completed", {
@@ -1 +1 @@
1
- {"version":3,"file":"DocsService.d.ts","sourceRoot":"","sources":["../../../src/services/docs/DocsService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DocsService.d.ts","sourceRoot":"","sources":["../../../src/services/docs/DocsService.ts"],"names":[],"mappings":"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"}