@mcoda/core 0.1.22 → 0.1.23

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.
@@ -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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"}
@@ -472,6 +472,7 @@ export class TaskOrderingService {
472
472
  SELECT
473
473
  td.task_id,
474
474
  td.depends_on_task_id,
475
+ td.relation_type,
475
476
  dep.key as depends_on_key,
476
477
  dep.status as depends_on_status
477
478
  FROM task_dependencies td
@@ -646,47 +647,81 @@ export class TaskOrderingService {
646
647
  return false;
647
648
  }
648
649
  async injectFoundationDependencies(tasks, deps, warnings, persist) {
650
+ const relationType = "inferred_foundation";
649
651
  const classification = new Map();
650
652
  for (const task of tasks) {
651
653
  classification.set(task.id, this.resolveClassification(task));
652
654
  }
653
655
  const foundationTasks = tasks.filter((task) => classification.get(task.id)?.foundation);
654
656
  const nonFoundationTasks = tasks.filter((task) => !classification.get(task.id)?.foundation);
655
- if (foundationTasks.length === 0 || nonFoundationTasks.length === 0)
656
- return;
657
+ let removedInferred = 0;
658
+ for (const task of tasks) {
659
+ const rows = deps.get(task.id) ?? [];
660
+ if (rows.length === 0)
661
+ continue;
662
+ const kept = rows.filter((row) => row.relation_type?.toLowerCase() !== relationType);
663
+ removedInferred += rows.length - kept.length;
664
+ deps.set(task.id, kept);
665
+ }
666
+ const foundationsByStory = new Map();
667
+ const foundationsByEpic = new Map();
668
+ for (const foundation of foundationTasks) {
669
+ const storyEntries = foundationsByStory.get(foundation.story_id) ?? [];
670
+ storyEntries.push(foundation);
671
+ foundationsByStory.set(foundation.story_id, storyEntries);
672
+ const epicEntries = foundationsByEpic.get(foundation.epic_id) ?? [];
673
+ epicEntries.push(foundation);
674
+ foundationsByEpic.set(foundation.epic_id, epicEntries);
675
+ }
676
+ const byRank = (a, b) => {
677
+ const priorityA = a.priority ?? Number.MAX_SAFE_INTEGER;
678
+ const priorityB = b.priority ?? Number.MAX_SAFE_INTEGER;
679
+ if (priorityA !== priorityB)
680
+ return priorityA - priorityB;
681
+ const createdA = Date.parse(a.created_at) || 0;
682
+ const createdB = Date.parse(b.created_at) || 0;
683
+ if (createdA !== createdB)
684
+ return createdA - createdB;
685
+ return a.key.localeCompare(b.key);
686
+ };
687
+ for (const list of foundationsByStory.values())
688
+ list.sort(byRank);
689
+ for (const list of foundationsByEpic.values())
690
+ list.sort(byRank);
657
691
  const taskById = new Map(tasks.map((task) => [task.id, task]));
658
692
  const dependencyGraph = this.buildDependencyGraph(tasks, deps);
659
693
  const inserts = [];
660
694
  let skippedCycles = 0;
661
695
  const skippedEdges = [];
662
696
  for (const task of nonFoundationTasks) {
663
- const existing = new Set((deps.get(task.id) ?? [])
664
- .map((dep) => dep.depends_on_task_id ?? "")
665
- .filter(Boolean));
666
- for (const foundation of foundationTasks) {
667
- if (task.id === foundation.id)
668
- continue;
669
- if (existing.has(foundation.id))
670
- continue;
671
- if (this.hasDependencyPath(dependencyGraph, foundation.id, task.id)) {
672
- skippedCycles += 1;
673
- if (skippedEdges.length < 5) {
674
- skippedEdges.push(`${task.key}->${foundation.key}`);
675
- }
676
- continue;
697
+ const existingDeps = (deps.get(task.id) ?? []).filter((dep) => Boolean(dep.depends_on_task_id));
698
+ if (existingDeps.length > 0)
699
+ continue;
700
+ const scopedCandidates = foundationsByStory.get(task.story_id) ?? foundationsByEpic.get(task.epic_id) ?? [];
701
+ const foundation = scopedCandidates.find((candidate) => candidate.id !== task.id);
702
+ if (!foundation)
703
+ continue;
704
+ if (this.hasDependencyPath(dependencyGraph, foundation.id, task.id)) {
705
+ skippedCycles += 1;
706
+ if (skippedEdges.length < 5) {
707
+ skippedEdges.push(`${task.key}->${foundation.key}`);
677
708
  }
678
- inserts.push({
679
- taskId: task.id,
680
- dependsOnTaskId: foundation.id,
681
- relationType: "inferred_foundation",
682
- });
683
- existing.add(foundation.id);
684
- const edges = dependencyGraph.get(task.id) ?? new Set();
685
- edges.add(foundation.id);
686
- dependencyGraph.set(task.id, edges);
709
+ continue;
687
710
  }
711
+ inserts.push({
712
+ taskId: task.id,
713
+ dependsOnTaskId: foundation.id,
714
+ relationType,
715
+ });
716
+ const edges = dependencyGraph.get(task.id) ?? new Set();
717
+ edges.add(foundation.id);
718
+ dependencyGraph.set(task.id, edges);
688
719
  }
689
- if (inserts.length === 0) {
720
+ if (persist && removedInferred > 0) {
721
+ const placeholders = tasks.map(() => "?").join(", ");
722
+ await this.db.run(`DELETE FROM task_dependencies WHERE relation_type = ? AND task_id IN (${placeholders})`, relationType, ...tasks.map((task) => task.id));
723
+ }
724
+ if (inserts.length === 0 && removedInferred === 0) {
690
725
  if (skippedCycles > 0) {
691
726
  warnings.push(`Skipped ${skippedCycles} inferred foundation deps due to cycles.`);
692
727
  if (skippedEdges.length > 0) {
@@ -704,16 +739,25 @@ export class TaskOrderingService {
704
739
  depList.push({
705
740
  task_id: insert.taskId,
706
741
  depends_on_task_id: insert.dependsOnTaskId,
742
+ relation_type: relationType,
707
743
  depends_on_key: dependsOn?.key,
708
744
  depends_on_status: dependsOn?.status,
709
745
  });
710
746
  deps.set(insert.taskId, depList);
711
747
  }
712
- if (persist) {
713
- warnings.push(`Injected ${inserts.length} inferred foundation deps.`);
748
+ if (persist && removedInferred > 0) {
749
+ warnings.push(`Reconciled ${removedInferred} inferred foundation deps before re-inference.`);
714
750
  }
715
- else {
716
- warnings.push(`Dry run: inferred ${inserts.length} foundation deps (not persisted).`);
751
+ else if (!persist && removedInferred > 0) {
752
+ warnings.push(`Dry run: would reconcile ${removedInferred} inferred foundation deps.`);
753
+ }
754
+ if (inserts.length > 0) {
755
+ if (persist) {
756
+ warnings.push(`Injected ${inserts.length} scoped inferred foundation deps.`);
757
+ }
758
+ else {
759
+ warnings.push(`Dry run: inferred ${inserts.length} scoped foundation deps (not persisted).`);
760
+ }
717
761
  }
718
762
  if (skippedCycles > 0) {
719
763
  warnings.push(`Skipped ${skippedCycles} inferred foundation deps due to cycles.`);
@@ -782,6 +826,7 @@ export class TaskOrderingService {
782
826
  depList.push({
783
827
  task_id: insert.taskId,
784
828
  depends_on_task_id: insert.dependsOnTaskId,
829
+ relation_type: "inferred_agent",
785
830
  depends_on_key: dependsOn?.key,
786
831
  depends_on_status: dependsOn?.status,
787
832
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcoda/core",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
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/db": "0.1.22",
36
- "@mcoda/agents": "0.1.22",
37
- "@mcoda/generators": "0.1.22",
38
- "@mcoda/integrations": "0.1.22",
39
- "@mcoda/shared": "0.1.22"
35
+ "@mcoda/shared": "0.1.23",
36
+ "@mcoda/db": "0.1.23",
37
+ "@mcoda/generators": "0.1.23",
38
+ "@mcoda/agents": "0.1.23",
39
+ "@mcoda/integrations": "0.1.23"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.json",