@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 deliverables = [{
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 deliverables = [{
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
- lines.push("**Deliverables (review these for background context):**");
81114
- for (const d of depTask.deliverables) {
81115
- const refInfo = d.type === "file" ? ` \u2014 File: \`${d.reference}\` (use \`file_read\` to inspect)` : d.type === "branch" ? ` [branch: ${d.reference}]` : d.reference ? ` \u2014 ref: \`${d.reference}\`` : "";
81116
- lines.push(`- ${d.summary ?? "(no summary)"}${refInfo}`);
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
- lines.push("**Deliverables (review these for background context):**");
83522
- for (const d of depTask.deliverables) {
83523
- const refInfo = d.type === "file" ? ` \u2014 File: \`${d.reference}\` (use \`file_read\` to inspect)` : d.type === "branch" ? ` [branch: ${d.reference}]` : d.reference ? ` \u2014 ref: \`${d.reference}\`` : "";
83524
- lines.push(`- ${d.summary ?? "(no summary)"}${refInfo}`);
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
- const all = this.taskService.listTasks({ projectId });
196735
- const items = all.filter((t2) => t2.deliverables && t2.deliverables.length > 0).map((t2) => ({
196736
- taskId: t2.id,
196737
- taskTitle: t2.title,
196738
- taskStatus: t2.status,
196739
- projectId: t2.projectId,
196740
- requirementId: t2.requirementId,
196741
- assignedAgentId: t2.assignedAgentId,
196742
- updatedAt: t2.updatedAt,
196743
- deliverables: t2.deliverables
196744
- }));
196745
- this.json(res, 200, { items });
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
- * One-time migration: scan existing tasks and create Deliverable entries
208012
- * for any task.deliverables that don't yet have a corresponding row.
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 migrateFromTasks(tasks) {
208016
- let branchCleaned = 0;
208076
+ async cleanupLegacyRows() {
208077
+ let cleaned = 0;
208017
208078
  for (const [id, d] of this.cache) {
208018
- if (d.type === "branch" && d.status !== "outdated") {
208019
- d.status = "outdated";
208020
- d.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
208021
- await this.repo?.update(id, { status: "outdated" });
208022
- branchCleaned++;
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 (migrated > 0) {
208058
- log75.info("Migrated task deliverables to unified table", { migrated });
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
- const allTasks = taskService.listTasks({ orgId: "default" });
223903
- await deliverableService.migrateFromTasks(allTasks);
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();