@markus-global/cli 0.8.4-rc.0 → 0.8.4-rc.2
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/markus.mjs
CHANGED
|
@@ -60132,13 +60132,10 @@ You are ${request.name}.`,
|
|
|
60132
60132
|
throw new Error(`Task not found: ${taskId2}`);
|
|
60133
60133
|
const reviewerId = task.reviewerId;
|
|
60134
60134
|
const _validTypes = /* @__PURE__ */ new Set(["file", "directory"]);
|
|
60135
|
-
const
|
|
60136
|
-
type: "branch",
|
|
60137
|
-
reference: `task/${taskId2}`,
|
|
60138
|
-
summary: `${summary}${knownIssues ? `
|
|
60135
|
+
const completionSummary = `${summary}${knownIssues ? `
|
|
60139
60136
|
|
|
60140
|
-
Known issues: ${knownIssues}` : ""}
|
|
60141
|
-
|
|
60137
|
+
Known issues: ${knownIssues}` : ""}`;
|
|
60138
|
+
const deliverables = [];
|
|
60142
60139
|
if (Array.isArray(inputDeliverables)) {
|
|
60143
60140
|
for (const d of inputDeliverables) {
|
|
60144
60141
|
if (d?.reference) {
|
|
@@ -60150,7 +60147,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
60150
60147
|
}
|
|
60151
60148
|
}
|
|
60152
60149
|
}
|
|
60153
|
-
return ts.submitForReview(taskId2, deliverables, reviewerId);
|
|
60150
|
+
return ts.submitForReview(taskId2, deliverables, reviewerId, completionSummary);
|
|
60154
60151
|
},
|
|
60155
60152
|
proposeRequirement: this.requirementService ? async (params) => {
|
|
60156
60153
|
return this.requirementService.proposeRequirement({
|
|
@@ -60844,13 +60841,10 @@ You are ${row.name}.`,
|
|
|
60844
60841
|
throw new Error(`Task not found: ${taskId2}`);
|
|
60845
60842
|
const reviewerId = task.reviewerId;
|
|
60846
60843
|
const _validTypes = /* @__PURE__ */ new Set(["file", "directory"]);
|
|
60847
|
-
const
|
|
60848
|
-
type: "branch",
|
|
60849
|
-
reference: `task/${taskId2}`,
|
|
60850
|
-
summary: `${summary}${knownIssues ? `
|
|
60844
|
+
const completionSummary = `${summary}${knownIssues ? `
|
|
60851
60845
|
|
|
60852
|
-
Known issues: ${knownIssues}` : ""}
|
|
60853
|
-
|
|
60846
|
+
Known issues: ${knownIssues}` : ""}`;
|
|
60847
|
+
const deliverables = [];
|
|
60854
60848
|
if (Array.isArray(inputDeliverables)) {
|
|
60855
60849
|
for (const d of inputDeliverables) {
|
|
60856
60850
|
if (d?.reference) {
|
|
@@ -60862,7 +60856,7 @@ Known issues: ${knownIssues}` : ""}`
|
|
|
60862
60856
|
}
|
|
60863
60857
|
}
|
|
60864
60858
|
}
|
|
60865
|
-
return ts.submitForReview(taskId2, deliverables, reviewerId);
|
|
60859
|
+
return ts.submitForReview(taskId2, deliverables, reviewerId, completionSummary);
|
|
60866
60860
|
},
|
|
60867
60861
|
proposeRequirement: this.requirementService ? async (params) => {
|
|
60868
60862
|
return this.requirementService.proposeRequirement({
|
|
@@ -81109,11 +81103,17 @@ var init_task_service = __esm({
|
|
|
81109
81103
|
lines.push(`- ${note.slice(0, PROMPT_DEP_NOTE_CHARS)}`);
|
|
81110
81104
|
}
|
|
81111
81105
|
}
|
|
81106
|
+
if (depTask.completionSummary) {
|
|
81107
|
+
lines.push(`**Completion Summary:** ${depTask.completionSummary}`);
|
|
81108
|
+
}
|
|
81112
81109
|
if (depTask.deliverables?.length) {
|
|
81113
|
-
|
|
81114
|
-
|
|
81115
|
-
|
|
81116
|
-
|
|
81110
|
+
const files = depTask.deliverables.filter((d) => d.type !== "branch" && d.reference);
|
|
81111
|
+
if (files.length > 0) {
|
|
81112
|
+
lines.push("**Deliverables (review these for background context):**");
|
|
81113
|
+
for (const d of files) {
|
|
81114
|
+
const refInfo = d.type === "file" ? ` \u2014 File: \`${d.reference}\` (use \`file_read\` to inspect)` : d.reference ? ` \u2014 ref: \`${d.reference}\`` : "";
|
|
81115
|
+
lines.push(`- ${d.summary ?? "(no summary)"}${refInfo}`);
|
|
81116
|
+
}
|
|
81117
81117
|
}
|
|
81118
81118
|
}
|
|
81119
81119
|
depSections.push(lines.join("\n"));
|
|
@@ -81600,6 +81600,7 @@ ${c.content}`;
|
|
|
81600
81600
|
blockedBy,
|
|
81601
81601
|
result: row.result ?? void 0,
|
|
81602
81602
|
deliverables: Array.isArray(row.deliverables) ? row.deliverables : void 0,
|
|
81603
|
+
completionSummary: row.completionSummary ?? void 0,
|
|
81603
81604
|
notes: Array.isArray(row.notes) ? row.notes : void 0,
|
|
81604
81605
|
createdAt: row.createdAt instanceof Date ? row.createdAt.toISOString() : String(row.createdAt),
|
|
81605
81606
|
updatedAt: row.updatedAt instanceof Date ? row.updatedAt.toISOString() : String(row.updatedAt),
|
|
@@ -81622,6 +81623,33 @@ ${c.content}`;
|
|
|
81622
81623
|
log57.warn("Failed to load tasks from DB", { error: String(err) });
|
|
81623
81624
|
}
|
|
81624
81625
|
}
|
|
81626
|
+
/**
|
|
81627
|
+
* One-time migration: extract branch deliverable summaries into task.completionSummary
|
|
81628
|
+
* and remove branch items from task.deliverables JSON.
|
|
81629
|
+
*/
|
|
81630
|
+
async migrateBranchToCompletionSummary() {
|
|
81631
|
+
let migrated = 0;
|
|
81632
|
+
for (const [taskId2, task] of this.tasks) {
|
|
81633
|
+
if (task.completionSummary)
|
|
81634
|
+
continue;
|
|
81635
|
+
if (!task.deliverables?.length)
|
|
81636
|
+
continue;
|
|
81637
|
+
const branchItem = task.deliverables.find((d) => d.type === "branch");
|
|
81638
|
+
if (!branchItem)
|
|
81639
|
+
continue;
|
|
81640
|
+
task.completionSummary = branchItem.summary;
|
|
81641
|
+
task.deliverables = task.deliverables.filter((d) => d.type !== "branch");
|
|
81642
|
+
task.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
81643
|
+
if (this.taskRepo) {
|
|
81644
|
+
this.taskRepo.updateCompletionSummary(taskId2, task.completionSummary).catch((err) => log57.warn("Failed to persist completionSummary migration", { taskId: taskId2, error: String(err) }));
|
|
81645
|
+
this.taskRepo.updateDeliverables(taskId2, task.deliverables).catch((err) => log57.warn("Failed to persist deliverables cleanup", { taskId: taskId2, error: String(err) }));
|
|
81646
|
+
}
|
|
81647
|
+
migrated++;
|
|
81648
|
+
}
|
|
81649
|
+
if (migrated > 0) {
|
|
81650
|
+
log57.info(`Migrated branch->completionSummary for ${migrated} tasks`);
|
|
81651
|
+
}
|
|
81652
|
+
}
|
|
81625
81653
|
static PRIORITY_ORDER = {
|
|
81626
81654
|
urgent: 0,
|
|
81627
81655
|
high: 1,
|
|
@@ -82738,7 +82766,7 @@ Action: ${guidance}` : ""
|
|
|
82738
82766
|
return { allowed: true };
|
|
82739
82767
|
}
|
|
82740
82768
|
// ─── Governance: Submit for Review ─────────────────────────────────────────
|
|
82741
|
-
async submitForReview(taskId2, deliverables, reviewerId) {
|
|
82769
|
+
async submitForReview(taskId2, deliverables, reviewerId, completionSummary) {
|
|
82742
82770
|
const task = this.tasks.get(taskId2);
|
|
82743
82771
|
if (!task)
|
|
82744
82772
|
throw new Error(`Task not found: ${taskId2}`);
|
|
@@ -82789,8 +82817,14 @@ Action: ${guidance}` : ""
|
|
|
82789
82817
|
if (reviewerId) {
|
|
82790
82818
|
task.reviewerId = reviewerId;
|
|
82791
82819
|
}
|
|
82820
|
+
if (completionSummary) {
|
|
82821
|
+
task.completionSummary = completionSummary;
|
|
82822
|
+
}
|
|
82792
82823
|
if (this.taskRepo) {
|
|
82793
82824
|
this.taskRepo.updateDeliverables(task.id, task.deliverables).catch((err) => log57.warn("Failed to persist deliverables to DB", { taskId: task.id, error: String(err) }));
|
|
82825
|
+
if (completionSummary) {
|
|
82826
|
+
this.taskRepo.updateCompletionSummary(task.id, completionSummary).catch((err) => log57.warn("Failed to persist completionSummary to DB", { taskId: task.id, error: String(err) }));
|
|
82827
|
+
}
|
|
82794
82828
|
if (reviewerId) {
|
|
82795
82829
|
this.taskRepo.update(task.id, { reviewerId }).catch((err) => log57.warn("Failed to persist reviewer change to DB", { taskId: task.id, error: String(err) }));
|
|
82796
82830
|
}
|
|
@@ -82881,8 +82915,12 @@ Action: ${guidance}` : ""
|
|
|
82881
82915
|
parts.push(`[REVIEW REQUEST \u2014 ACTION REQUIRED] Task "${task.title}" (ID: ${task.id}) has been submitted for your review by ${assigneeName}.`);
|
|
82882
82916
|
parts.push("");
|
|
82883
82917
|
parts.push(`**Description:** ${task.description}`);
|
|
82918
|
+
if (task.completionSummary) {
|
|
82919
|
+
parts.push("");
|
|
82920
|
+
parts.push(`**Summary:** ${task.completionSummary}`);
|
|
82921
|
+
}
|
|
82884
82922
|
if (task.deliverables && task.deliverables.length > 0) {
|
|
82885
|
-
const files = task.deliverables.filter((d) => d.type !== "branch");
|
|
82923
|
+
const files = task.deliverables.filter((d) => d.type !== "branch" && d.reference);
|
|
82886
82924
|
if (files.length > 0) {
|
|
82887
82925
|
parts.push("");
|
|
82888
82926
|
parts.push("**Deliverables:**");
|
|
@@ -82892,12 +82930,6 @@ Action: ${guidance}` : ""
|
|
|
82892
82930
|
if (files.length > REVIEWER_FILE_LIST_MAX)
|
|
82893
82931
|
parts.push(` ... and ${files.length - REVIEWER_FILE_LIST_MAX} more`);
|
|
82894
82932
|
}
|
|
82895
|
-
const branch = task.deliverables.find((d) => d.type === "branch");
|
|
82896
|
-
if (branch) {
|
|
82897
|
-
parts.push(`**Branch:** ${branch.reference}`);
|
|
82898
|
-
if (branch.summary)
|
|
82899
|
-
parts.push(`**Summary:** ${branch.summary}`);
|
|
82900
|
-
}
|
|
82901
82933
|
}
|
|
82902
82934
|
if (task.subtasks.length > 0) {
|
|
82903
82935
|
const done = task.subtasks.filter((s2) => s2.status === "completed").length;
|
|
@@ -83517,11 +83549,17 @@ ${reason}`
|
|
|
83517
83549
|
for (const note of depTask.notes.slice(-PROMPT_DEP_NOTES_MAX).reverse())
|
|
83518
83550
|
lines.push(`- ${note.slice(0, PROMPT_DEP_NOTE_CHARS)}`);
|
|
83519
83551
|
}
|
|
83552
|
+
if (depTask.completionSummary) {
|
|
83553
|
+
lines.push(`**Completion Summary:** ${depTask.completionSummary}`);
|
|
83554
|
+
}
|
|
83520
83555
|
if (depTask.deliverables?.length) {
|
|
83521
|
-
|
|
83522
|
-
|
|
83523
|
-
|
|
83524
|
-
|
|
83556
|
+
const files = depTask.deliverables.filter((d) => d.type !== "branch" && d.reference);
|
|
83557
|
+
if (files.length > 0) {
|
|
83558
|
+
lines.push("**Deliverables (review these for background context):**");
|
|
83559
|
+
for (const d of files) {
|
|
83560
|
+
const refInfo = d.type === "file" ? ` \u2014 File: \`${d.reference}\` (use \`file_read\` to inspect)` : d.reference ? ` \u2014 ref: \`${d.reference}\`` : "";
|
|
83561
|
+
lines.push(`- ${d.summary ?? "(no summary)"}${refInfo}`);
|
|
83562
|
+
}
|
|
83525
83563
|
}
|
|
83526
83564
|
}
|
|
83527
83565
|
depSections.push(lines.join("\n"));
|
|
@@ -196731,18 +196769,42 @@ ${cleanText}`,
|
|
|
196731
196769
|
}
|
|
196732
196770
|
if (path === "/api/tasks/deliverables" && req.method === "GET") {
|
|
196733
196771
|
const projectId = url.searchParams.get("projectId") ?? void 0;
|
|
196734
|
-
|
|
196735
|
-
|
|
196736
|
-
|
|
196737
|
-
|
|
196738
|
-
|
|
196739
|
-
|
|
196740
|
-
|
|
196741
|
-
|
|
196742
|
-
|
|
196743
|
-
|
|
196744
|
-
|
|
196745
|
-
|
|
196772
|
+
if (this.deliverableService) {
|
|
196773
|
+
const { results } = this.deliverableService.search({ projectId, limit: 500 });
|
|
196774
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
196775
|
+
for (const d of results) {
|
|
196776
|
+
if (!d.taskId)
|
|
196777
|
+
continue;
|
|
196778
|
+
if (!grouped.has(d.taskId)) {
|
|
196779
|
+
const task = this.taskService.getTask(d.taskId);
|
|
196780
|
+
grouped.set(d.taskId, {
|
|
196781
|
+
taskId: d.taskId,
|
|
196782
|
+
taskTitle: task?.title ?? "",
|
|
196783
|
+
taskStatus: task?.status ?? "",
|
|
196784
|
+
projectId: task?.projectId,
|
|
196785
|
+
requirementId: task?.requirementId,
|
|
196786
|
+
assignedAgentId: task?.assignedAgentId,
|
|
196787
|
+
updatedAt: task?.updatedAt,
|
|
196788
|
+
deliverables: []
|
|
196789
|
+
});
|
|
196790
|
+
}
|
|
196791
|
+
grouped.get(d.taskId).deliverables.push(d);
|
|
196792
|
+
}
|
|
196793
|
+
this.json(res, 200, { items: [...grouped.values()] });
|
|
196794
|
+
} else {
|
|
196795
|
+
const all = this.taskService.listTasks({ projectId });
|
|
196796
|
+
const items = all.filter((t2) => t2.deliverables && t2.deliverables.length > 0).map((t2) => ({
|
|
196797
|
+
taskId: t2.id,
|
|
196798
|
+
taskTitle: t2.title,
|
|
196799
|
+
taskStatus: t2.status,
|
|
196800
|
+
projectId: t2.projectId,
|
|
196801
|
+
requirementId: t2.requirementId,
|
|
196802
|
+
assignedAgentId: t2.assignedAgentId,
|
|
196803
|
+
updatedAt: t2.updatedAt,
|
|
196804
|
+
deliverables: t2.deliverables
|
|
196805
|
+
}));
|
|
196806
|
+
this.json(res, 200, { items });
|
|
196807
|
+
}
|
|
196746
196808
|
return;
|
|
196747
196809
|
}
|
|
196748
196810
|
if (path === "/api/deliverables" && req.method === "GET") {
|
|
@@ -208008,56 +208070,23 @@ var init_deliverable_service = __esm({
|
|
|
208008
208070
|
return missing;
|
|
208009
208071
|
}
|
|
208010
208072
|
/**
|
|
208011
|
-
*
|
|
208012
|
-
*
|
|
208013
|
-
* Also cleans up any legacy "branch"-type deliverables by marking them outdated.
|
|
208073
|
+
* Clean up legacy migration markers and branch-type deliverables from the table.
|
|
208074
|
+
* Safe to call on startup — removes only housekeeping rows.
|
|
208014
208075
|
*/
|
|
208015
|
-
async
|
|
208016
|
-
let
|
|
208076
|
+
async cleanupLegacyRows() {
|
|
208077
|
+
let cleaned = 0;
|
|
208017
208078
|
for (const [id, d] of this.cache) {
|
|
208018
|
-
|
|
208019
|
-
|
|
208020
|
-
|
|
208021
|
-
|
|
208022
|
-
|
|
208023
|
-
|
|
208024
|
-
}
|
|
208025
|
-
if (branchCleaned > 0) {
|
|
208026
|
-
log75.info("Cleaned up legacy branch-type deliverables", { count: branchCleaned });
|
|
208027
|
-
}
|
|
208028
|
-
const existingTaskIds = this.repo ? await this.repo.listTaskIdsWithDeliverables() : new Set([...this.cache.values()].map((d) => d.taskId).filter(Boolean));
|
|
208029
|
-
let migrated = 0;
|
|
208030
|
-
for (const task of tasks) {
|
|
208031
|
-
if (!task.deliverables?.length)
|
|
208032
|
-
continue;
|
|
208033
|
-
if (existingTaskIds.has(task.id))
|
|
208034
|
-
continue;
|
|
208035
|
-
for (const d of task.deliverables) {
|
|
208036
|
-
if (d.type === "branch")
|
|
208037
|
-
continue;
|
|
208038
|
-
try {
|
|
208039
|
-
await this.create({
|
|
208040
|
-
type: this.mapTaskDeliverableType(d.type),
|
|
208041
|
-
title: d.summary?.slice(0, 200) || d.reference,
|
|
208042
|
-
summary: d.summary || "",
|
|
208043
|
-
reference: d.reference,
|
|
208044
|
-
taskId: task.id,
|
|
208045
|
-
agentId: task.assignedAgentId,
|
|
208046
|
-
projectId: task.projectId,
|
|
208047
|
-
requirementId: task.requirementId,
|
|
208048
|
-
diffStats: d.diffStats,
|
|
208049
|
-
testResults: d.testResults
|
|
208050
|
-
});
|
|
208051
|
-
migrated++;
|
|
208052
|
-
} catch (err) {
|
|
208053
|
-
log75.warn("Failed to migrate task deliverable", { taskId: task.id, ref: d.reference, error: String(err) });
|
|
208054
|
-
}
|
|
208079
|
+
const isMigrationMarker = d.title === "[migration-processed]" && d.status === "outdated";
|
|
208080
|
+
const isBranchType = d.type === "branch";
|
|
208081
|
+
if (isMigrationMarker || isBranchType) {
|
|
208082
|
+
this.cache.delete(id);
|
|
208083
|
+
await this.repo?.delete(id);
|
|
208084
|
+
cleaned++;
|
|
208055
208085
|
}
|
|
208056
208086
|
}
|
|
208057
|
-
if (
|
|
208058
|
-
log75.info("
|
|
208087
|
+
if (cleaned > 0) {
|
|
208088
|
+
log75.info("Cleaned up legacy deliverable rows", { count: cleaned });
|
|
208059
208089
|
}
|
|
208060
|
-
return migrated;
|
|
208061
208090
|
}
|
|
208062
208091
|
parseTags(raw) {
|
|
208063
208092
|
if (Array.isArray(raw))
|
|
@@ -208074,14 +208103,6 @@ var init_deliverable_service = __esm({
|
|
|
208074
208103
|
}
|
|
208075
208104
|
return [];
|
|
208076
208105
|
}
|
|
208077
|
-
mapTaskDeliverableType(type) {
|
|
208078
|
-
switch (type) {
|
|
208079
|
-
case "file":
|
|
208080
|
-
return "file";
|
|
208081
|
-
default:
|
|
208082
|
-
return "file";
|
|
208083
|
-
}
|
|
208084
|
-
}
|
|
208085
208106
|
rowToDeliverable(r) {
|
|
208086
208107
|
return {
|
|
208087
208108
|
id: r.id,
|
|
@@ -208871,7 +208892,8 @@ function openSqlite(dbPath) {
|
|
|
208871
208892
|
{ table: "agents", column: "disabled", sql: "ALTER TABLE agents ADD COLUMN disabled INTEGER NOT NULL DEFAULT 0" },
|
|
208872
208893
|
{ table: "deliverables", column: "format", sql: "ALTER TABLE deliverables ADD COLUMN format TEXT" },
|
|
208873
208894
|
{ table: "task_comments", column: "reply_to_id", sql: "ALTER TABLE task_comments ADD COLUMN reply_to_id TEXT" },
|
|
208874
|
-
{ table: "requirement_comments", column: "reply_to_id", sql: "ALTER TABLE requirement_comments ADD COLUMN reply_to_id TEXT" }
|
|
208895
|
+
{ table: "requirement_comments", column: "reply_to_id", sql: "ALTER TABLE requirement_comments ADD COLUMN reply_to_id TEXT" },
|
|
208896
|
+
{ table: "tasks", column: "completion_summary", sql: "ALTER TABLE tasks ADD COLUMN completion_summary TEXT" }
|
|
208875
208897
|
];
|
|
208876
208898
|
for (const m of migrations) {
|
|
208877
208899
|
const cols = _db.prepare(`PRAGMA table_info(${m.table})`).all();
|
|
@@ -209819,6 +209841,9 @@ CREATE INDEX IF NOT EXISTS idx_integrations_org ON integrations(org_id, platform
|
|
|
209819
209841
|
async updateDeliverables(id, deliverables) {
|
|
209820
209842
|
this.db.prepare("UPDATE tasks SET deliverables = ?, updated_at = ? WHERE id = ?").run(toJson(deliverables), now2(), id);
|
|
209821
209843
|
}
|
|
209844
|
+
async updateCompletionSummary(id, summary) {
|
|
209845
|
+
this.db.prepare("UPDATE tasks SET completion_summary = ?, updated_at = ? WHERE id = ?").run(summary, now2(), id);
|
|
209846
|
+
}
|
|
209822
209847
|
listByOrg(orgId2, filters2) {
|
|
209823
209848
|
let q = "SELECT * FROM tasks WHERE org_id = ?";
|
|
209824
209849
|
const vals = [orgId2];
|
|
@@ -209890,6 +209915,7 @@ CREATE INDEX IF NOT EXISTS idx_integrations_org ON integrations(org_id, platform
|
|
|
209890
209915
|
completedAt: toDate(r["completed_at"]),
|
|
209891
209916
|
taskType: r["task_type"] ?? "standard",
|
|
209892
209917
|
scheduleConfig: fromJson(r["schedule_config"]),
|
|
209918
|
+
completionSummary: r["completion_summary"] ?? void 0,
|
|
209893
209919
|
createdAt: toDate(r["created_at"]),
|
|
209894
209920
|
updatedAt: toDate(r["updated_at"]),
|
|
209895
209921
|
dueAt: toDate(r["due_at"])
|
|
@@ -211419,6 +211445,9 @@ CREATE INDEX IF NOT EXISTS idx_integrations_org ON integrations(org_id, platform
|
|
|
211419
211445
|
async remove(id) {
|
|
211420
211446
|
this.db.prepare("UPDATE deliverables SET status = 'outdated', updated_at = ? WHERE id = ?").run(now2(), id);
|
|
211421
211447
|
}
|
|
211448
|
+
async delete(id) {
|
|
211449
|
+
this.db.prepare("DELETE FROM deliverables WHERE id = ?").run(id);
|
|
211450
|
+
}
|
|
211422
211451
|
async listAll(limit = 500) {
|
|
211423
211452
|
const rows = this.db.prepare("SELECT * FROM deliverables WHERE status != 'outdated' ORDER BY updated_at DESC LIMIT ?").all(limit);
|
|
211424
211453
|
return rows.map((r) => this.mapRow(r));
|
|
@@ -223899,9 +223928,8 @@ async function startServerCore(config, values, opts) {
|
|
|
223899
223928
|
const knowledgeService = new KnowledgeService(knowledgeStore);
|
|
223900
223929
|
const deliverableService = new DeliverableService(storage?.deliverableRepo);
|
|
223901
223930
|
await deliverableService.load();
|
|
223902
|
-
|
|
223903
|
-
await deliverableService.
|
|
223904
|
-
await deliverableService.deduplicateByReference();
|
|
223931
|
+
await taskService.migrateBranchToCompletionSummary();
|
|
223932
|
+
await deliverableService.cleanupLegacyRows();
|
|
223905
223933
|
const reportService = new ReportService(taskService, billingService, auditService, knowledgeService);
|
|
223906
223934
|
const _trustService = new TrustService();
|
|
223907
223935
|
const requirementService = new RequirementService();
|