@mcoda/core 0.1.28 → 0.1.29

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.
@@ -93,6 +93,11 @@ export declare class TaskOrderingService {
93
93
  private buildOrderingMetadata;
94
94
  private buildDependencyGraph;
95
95
  private hasDependencyPath;
96
+ private buildDependentsFromGraph;
97
+ private findCyclicComponents;
98
+ private chooseCycleBreakCandidate;
99
+ private removeDependencyEdge;
100
+ private resolveDependencyCycles;
96
101
  private injectFoundationDependencies;
97
102
  private applyInferredDependencies;
98
103
  private compareTasks;
@@ -1 +1 @@
1
- {"version":3,"file":"TaskOrderingService.d.ts","sourceRoot":"","sources":["../../../src/services/backlog/TaskOrderingService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TaskOrderingService.d.ts","sourceRoot":"","sources":["../../../src/services/backlog/TaskOrderingService.ts"],"names":[],"mappings":"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"}
@@ -646,6 +646,166 @@ export class TaskOrderingService {
646
646
  }
647
647
  return false;
648
648
  }
649
+ buildDependentsFromGraph(graph) {
650
+ const dependents = new Map();
651
+ for (const [taskId, dependencies] of graph.entries()) {
652
+ for (const dependencyId of dependencies) {
653
+ const list = dependents.get(dependencyId) ?? [];
654
+ list.push(taskId);
655
+ dependents.set(dependencyId, list);
656
+ }
657
+ }
658
+ return dependents;
659
+ }
660
+ findCyclicComponents(graph) {
661
+ const nodes = new Set();
662
+ for (const [taskId, dependencies] of graph.entries()) {
663
+ nodes.add(taskId);
664
+ for (const dependencyId of dependencies)
665
+ nodes.add(dependencyId);
666
+ }
667
+ const indexByNode = new Map();
668
+ const lowLinkByNode = new Map();
669
+ const stack = [];
670
+ const onStack = new Set();
671
+ const components = [];
672
+ let index = 0;
673
+ const visit = (nodeId) => {
674
+ indexByNode.set(nodeId, index);
675
+ lowLinkByNode.set(nodeId, index);
676
+ index += 1;
677
+ stack.push(nodeId);
678
+ onStack.add(nodeId);
679
+ const neighbors = graph.get(nodeId) ?? new Set();
680
+ for (const neighbor of neighbors) {
681
+ if (!indexByNode.has(neighbor)) {
682
+ visit(neighbor);
683
+ const nextLow = Math.min(lowLinkByNode.get(nodeId) ?? Number.MAX_SAFE_INTEGER, lowLinkByNode.get(neighbor) ?? Number.MAX_SAFE_INTEGER);
684
+ lowLinkByNode.set(nodeId, nextLow);
685
+ continue;
686
+ }
687
+ if (!onStack.has(neighbor))
688
+ continue;
689
+ const nextLow = Math.min(lowLinkByNode.get(nodeId) ?? Number.MAX_SAFE_INTEGER, indexByNode.get(neighbor) ?? Number.MAX_SAFE_INTEGER);
690
+ lowLinkByNode.set(nodeId, nextLow);
691
+ }
692
+ if ((lowLinkByNode.get(nodeId) ?? -1) !== (indexByNode.get(nodeId) ?? -2))
693
+ return;
694
+ const component = [];
695
+ while (stack.length > 0) {
696
+ const popped = stack.pop();
697
+ onStack.delete(popped);
698
+ component.push(popped);
699
+ if (popped === nodeId)
700
+ break;
701
+ }
702
+ if (component.length > 1) {
703
+ components.push(component);
704
+ return;
705
+ }
706
+ const only = component[0];
707
+ if (only && graph.get(only)?.has(only)) {
708
+ components.push(component);
709
+ }
710
+ };
711
+ for (const nodeId of nodes) {
712
+ if (!indexByNode.has(nodeId))
713
+ visit(nodeId);
714
+ }
715
+ return components;
716
+ }
717
+ chooseCycleBreakCandidate(component, dependencyGraph, impact) {
718
+ const members = new Set(component);
719
+ const candidates = [];
720
+ for (const taskId of component) {
721
+ const dependencies = dependencyGraph.get(taskId);
722
+ if (!dependencies || dependencies.size === 0)
723
+ continue;
724
+ const weight = impact.get(taskId)?.total ?? 0;
725
+ for (const dependencyId of dependencies) {
726
+ if (!members.has(dependencyId))
727
+ continue;
728
+ candidates.push({ taskId, dependsOnTaskId: dependencyId, weight });
729
+ }
730
+ }
731
+ if (candidates.length === 0)
732
+ return undefined;
733
+ const maxWeight = Math.max(...candidates.map((candidate) => candidate.weight));
734
+ const weighted = candidates.filter((candidate) => candidate.weight === maxWeight);
735
+ if (weighted.length === 1)
736
+ return weighted[0];
737
+ const randomIndex = Math.floor(Math.random() * weighted.length);
738
+ return weighted[randomIndex];
739
+ }
740
+ async removeDependencyEdge(deps, taskId, dependsOnTaskId, persist) {
741
+ const rows = deps.get(taskId) ?? [];
742
+ const rowIndex = rows.findIndex((row) => row.depends_on_task_id === dependsOnTaskId);
743
+ if (rowIndex < 0)
744
+ return false;
745
+ if (persist) {
746
+ await this.db.run(`DELETE FROM task_dependencies
747
+ WHERE id = (
748
+ SELECT id
749
+ FROM task_dependencies
750
+ WHERE task_id = ?
751
+ AND depends_on_task_id = ?
752
+ LIMIT 1
753
+ )`, taskId, dependsOnTaskId);
754
+ }
755
+ const nextRows = [...rows];
756
+ nextRows.splice(rowIndex, 1);
757
+ if (nextRows.length > 0) {
758
+ deps.set(taskId, nextRows);
759
+ }
760
+ else {
761
+ deps.delete(taskId);
762
+ }
763
+ return true;
764
+ }
765
+ async resolveDependencyCycles(tasks, deps, warnings, persist) {
766
+ const taskById = new Map(tasks.map((task) => [task.id, task]));
767
+ const maxIterations = Math.max(1, tasks.length * tasks.length);
768
+ let removedEdges = 0;
769
+ let unresolvedCycleMembers = new Set();
770
+ for (let iteration = 0; iteration < maxIterations; iteration += 1) {
771
+ const dependencyGraph = this.buildDependencyGraph(tasks, deps);
772
+ const cyclicComponents = this.findCyclicComponents(dependencyGraph);
773
+ if (cyclicComponents.length === 0) {
774
+ return { removedEdges, unresolvedCycleMembers: new Set() };
775
+ }
776
+ let removedThisIteration = false;
777
+ const dependents = this.buildDependentsFromGraph(dependencyGraph);
778
+ const impact = this.dependencyImpactMap(dependents);
779
+ for (const component of cyclicComponents) {
780
+ const candidate = this.chooseCycleBreakCandidate(component, dependencyGraph, impact);
781
+ if (!candidate)
782
+ continue;
783
+ const removed = await this.removeDependencyEdge(deps, candidate.taskId, candidate.dependsOnTaskId, persist);
784
+ if (!removed)
785
+ continue;
786
+ removedThisIteration = true;
787
+ removedEdges += 1;
788
+ const taskKey = taskById.get(candidate.taskId)?.key ?? candidate.taskId;
789
+ const dependencyKey = taskById.get(candidate.dependsOnTaskId)?.key ?? candidate.dependsOnTaskId;
790
+ warnings.push(persist
791
+ ? `Resolved dependency cycle: removed ${taskKey} -> ${dependencyKey}.`
792
+ : `Dry run: would remove cyclic dependency ${taskKey} -> ${dependencyKey}.`);
793
+ break;
794
+ }
795
+ if (removedThisIteration)
796
+ continue;
797
+ unresolvedCycleMembers = new Set(cyclicComponents.flat());
798
+ break;
799
+ }
800
+ if (unresolvedCycleMembers.size === 0) {
801
+ const dependencyGraph = this.buildDependencyGraph(tasks, deps);
802
+ const cyclicComponents = this.findCyclicComponents(dependencyGraph);
803
+ if (cyclicComponents.length > 0) {
804
+ unresolvedCycleMembers = new Set(cyclicComponents.flat());
805
+ }
806
+ }
807
+ return { removedEdges, unresolvedCycleMembers };
808
+ }
649
809
  async injectFoundationDependencies(tasks, deps, warnings, persist) {
650
810
  const relationType = "inferred_foundation";
651
811
  const classification = new Map();
@@ -1243,6 +1403,11 @@ export class TaskOrderingService {
1243
1403
  else if (enableInference && !resolvedAgent) {
1244
1404
  warnings.push("Dependency inference skipped: no agent resolved.");
1245
1405
  }
1406
+ const cycleResolution = await this.resolveDependencyCycles(tasks, deps, warnings, applyChanges);
1407
+ if (cycleResolution.removedEdges > 0) {
1408
+ warnings.push(`Cycle resolution removed ${cycleResolution.removedEdges} dependency edge(s).`);
1409
+ }
1410
+ ({ nodes, dependents, missingRefs } = this.buildNodes(tasks, deps));
1246
1411
  if (missingRefs.size > 0) {
1247
1412
  warnings.push(`Missing dependencies referenced: ${Array.from(missingRefs).join(", ")}`);
1248
1413
  }
@@ -1270,7 +1435,7 @@ export class TaskOrderingService {
1270
1435
  ? this.buildOrderingMetadata(nodes, impact, missingContext, docContext)
1271
1436
  : { metadataByTask: new Map(), complexityByTask: new Map() };
1272
1437
  const { ordered: initialOrder, cycle, cycleMembers } = this.topologicalSort(nodes, dependents, impact, complexityByTask, missingContext, undefined, stageOrderMap);
1273
- if (cycle) {
1438
+ if (cycle || cycleResolution.unresolvedCycleMembers.size > 0) {
1274
1439
  warnings.push("Dependency cycle detected; ordering may be partial.");
1275
1440
  }
1276
1441
  let agentRank;
@@ -1351,7 +1516,11 @@ export class TaskOrderingService {
1351
1516
  warnings.push("Agent refinement skipped: no agent resolved.");
1352
1517
  }
1353
1518
  const { ordered, cycle: cycleAfterAgent, cycleMembers: agentCycleMembers } = this.topologicalSort(nodes, dependents, impact, complexityByTask, missingContext, agentRank, stageOrderMap);
1354
- const finalCycleMembers = new Set([...cycleMembers, ...agentCycleMembers]);
1519
+ const finalCycleMembers = new Set([
1520
+ ...cycleMembers,
1521
+ ...agentCycleMembers,
1522
+ ...cycleResolution.unresolvedCycleMembers,
1523
+ ]);
1355
1524
  if (cycleAfterAgent && !cycle) {
1356
1525
  warnings.push("Agent-influenced ordering encountered a cycle; used partial order.");
1357
1526
  }
@@ -114,6 +114,7 @@ export declare class WorkOnTasksService {
114
114
  private applyChromiumForTests;
115
115
  private findMissingTestHarnessTasks;
116
116
  private runTests;
117
+ private selectMostDependedTask;
117
118
  workOnTasks(request: WorkOnTasksRequest): Promise<WorkOnTasksResult>;
118
119
  }
119
120
  //# sourceMappingURL=WorkOnTasksService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WorkOnTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/WorkOnTasksService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WorkOnTasksService.d.ts","sourceRoot":"","sources":["../../../src/services/execution/WorkOnTasksService.ts"],"names":[],"mappings":"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"}
@@ -3563,6 +3563,42 @@ export class WorkOnTasksService {
3563
3563
  }
3564
3564
  return { ok: true, results };
3565
3565
  }
3566
+ selectMostDependedTask(candidates) {
3567
+ if (candidates.length === 0)
3568
+ return undefined;
3569
+ const candidateIds = new Set(candidates.map((candidate) => candidate.task.id));
3570
+ const dependentCounts = new Map();
3571
+ for (const candidate of candidates) {
3572
+ dependentCounts.set(candidate.task.id, 0);
3573
+ }
3574
+ for (const candidate of candidates) {
3575
+ for (const dependencyId of candidate.dependencies.ids) {
3576
+ if (!candidateIds.has(dependencyId))
3577
+ continue;
3578
+ dependentCounts.set(dependencyId, (dependentCounts.get(dependencyId) ?? 0) + 1);
3579
+ }
3580
+ }
3581
+ const ranked = candidates
3582
+ .map((candidate, index) => ({
3583
+ candidate,
3584
+ index,
3585
+ dependentCount: dependentCounts.get(candidate.task.id) ?? 0,
3586
+ }))
3587
+ .sort((a, b) => {
3588
+ if (a.dependentCount !== b.dependentCount)
3589
+ return b.dependentCount - a.dependentCount;
3590
+ const priorityA = a.candidate.task.priority ?? Number.MAX_SAFE_INTEGER;
3591
+ const priorityB = b.candidate.task.priority ?? Number.MAX_SAFE_INTEGER;
3592
+ if (priorityA !== priorityB)
3593
+ return priorityA - priorityB;
3594
+ const createdA = Date.parse(a.candidate.task.createdAt) || 0;
3595
+ const createdB = Date.parse(b.candidate.task.createdAt) || 0;
3596
+ if (createdA !== createdB)
3597
+ return createdA - createdB;
3598
+ return a.index - b.index;
3599
+ });
3600
+ return ranked[0]?.candidate;
3601
+ }
3566
3602
  async workOnTasks(request) {
3567
3603
  await this.ensureMcoda();
3568
3604
  const commandName = "work-on-tasks";
@@ -3770,6 +3806,37 @@ export class WorkOnTasksService {
3770
3806
  limit: request.limit,
3771
3807
  parallel: request.parallel,
3772
3808
  });
3809
+ if (selection.ordered.length === 0 && !ignoreDependencies && !explicitTaskSelection) {
3810
+ const dependencyBlocked = selection.warnings.some((warning) => warning.toLowerCase().includes("dependencies not ready"));
3811
+ if (dependencyBlocked) {
3812
+ const fallbackSelection = await this.selectionService.selectTasks({
3813
+ projectKey: request.projectKey,
3814
+ epicKey: request.epicKey,
3815
+ storyKey: request.storyKey,
3816
+ taskKeys: request.taskKeys,
3817
+ statusFilter,
3818
+ ignoreStatusFilter,
3819
+ includeTypes,
3820
+ excludeTypes,
3821
+ ignoreDependencies: true,
3822
+ missingContextPolicy: request.missingContextPolicy ?? "block",
3823
+ parallel: request.parallel,
3824
+ });
3825
+ pushSelectionWarnings(fallbackSelection.warnings);
3826
+ const fallbackTask = this.selectMostDependedTask(fallbackSelection.ordered);
3827
+ if (fallbackTask) {
3828
+ selection = {
3829
+ ...selection,
3830
+ project: selection.project ?? fallbackSelection.project,
3831
+ ordered: [fallbackTask],
3832
+ warnings: [
3833
+ ...selection.warnings,
3834
+ `No dependency-ready tasks available; selected ${fallbackTask.task.key} from dependency-loop fallback.`,
3835
+ ],
3836
+ };
3837
+ }
3838
+ }
3839
+ }
3773
3840
  await this.checkpoint(job.id, "selection", {
3774
3841
  ordered: selection.ordered.map((t) => t.task.key),
3775
3842
  });
@@ -4045,6 +4112,37 @@ export class WorkOnTasksService {
4045
4112
  break;
4046
4113
  newlyEligible.push(entry);
4047
4114
  }
4115
+ if (newlyEligible.length === 0 && !ignoreDependencies && !explicitTaskSelection) {
4116
+ const dependencyBlocked = refreshedSelection.warnings.some((warning) => warning.toLowerCase().includes("dependencies not ready"));
4117
+ if (dependencyBlocked) {
4118
+ const fallbackSelection = await this.selectionService.selectTasks({
4119
+ projectKey: request.projectKey,
4120
+ epicKey: request.epicKey,
4121
+ storyKey: request.storyKey,
4122
+ taskKeys: request.taskKeys,
4123
+ statusFilter,
4124
+ ignoreStatusFilter,
4125
+ includeTypes,
4126
+ excludeTypes,
4127
+ ignoreDependencies: true,
4128
+ missingContextPolicy: request.missingContextPolicy ?? "block",
4129
+ limit: remainingBudget,
4130
+ parallel: request.parallel,
4131
+ });
4132
+ pushSelectionWarnings(fallbackSelection.warnings);
4133
+ const fallbackTask = this.selectMostDependedTask(fallbackSelection.ordered.filter((entry) => !selectedTaskIds.has(entry.task.id)));
4134
+ if (fallbackTask) {
4135
+ const fallbackWarning = `No dependency-ready tasks available; selected ${fallbackTask.task.key} from dependency-loop fallback.`;
4136
+ selection = {
4137
+ ...selection,
4138
+ project: selection.project ?? refreshedSelection.project ?? fallbackSelection.project,
4139
+ warnings: [...selection.warnings, fallbackWarning],
4140
+ };
4141
+ pushSelectionWarnings([fallbackWarning]);
4142
+ newlyEligible.push(fallbackTask);
4143
+ }
4144
+ }
4145
+ }
4048
4146
  if (newlyEligible.length === 0)
4049
4147
  return;
4050
4148
  selection = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcoda/core",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "Core services and APIs for the mcoda CLI.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -32,11 +32,11 @@
32
32
  "dependencies": {
33
33
  "@apidevtools/swagger-parser": "^10.1.0",
34
34
  "yaml": "^2.4.2",
35
- "@mcoda/shared": "0.1.28",
36
- "@mcoda/generators": "0.1.28",
37
- "@mcoda/db": "0.1.28",
38
- "@mcoda/agents": "0.1.28",
39
- "@mcoda/integrations": "0.1.28"
35
+ "@mcoda/db": "0.1.29",
36
+ "@mcoda/generators": "0.1.29",
37
+ "@mcoda/shared": "0.1.29",
38
+ "@mcoda/agents": "0.1.29",
39
+ "@mcoda/integrations": "0.1.29"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.json",