mrvn-cli 0.5.20 → 0.5.21
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/index.js +50 -29
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +49 -28
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +50 -29
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin-serve.js
CHANGED
|
@@ -14369,24 +14369,26 @@ function getEffectiveProgress(frontmatter) {
|
|
|
14369
14369
|
if (typeof raw === "number") return Math.max(0, Math.min(100, Math.round(raw)));
|
|
14370
14370
|
return STATUS_PROGRESS_DEFAULTS[frontmatter.status] ?? 0;
|
|
14371
14371
|
}
|
|
14372
|
-
function propagateProgressFromTask(store, taskId) {
|
|
14372
|
+
function propagateProgressFromTask(store, taskId, options) {
|
|
14373
14373
|
const updated = [];
|
|
14374
14374
|
const task = store.get(taskId);
|
|
14375
14375
|
if (!task) return updated;
|
|
14376
|
-
if (
|
|
14377
|
-
if (task.frontmatter.
|
|
14378
|
-
|
|
14379
|
-
|
|
14380
|
-
}
|
|
14381
|
-
} else if (!task.frontmatter.progressOverride) {
|
|
14382
|
-
const children = store.list({ type: "contribution" }).filter((d) => d.frontmatter.aboutArtifact === taskId);
|
|
14383
|
-
if (children.length > 0) {
|
|
14384
|
-
const avg = children.reduce((sum, c) => sum + getEffectiveProgress(c.frontmatter), 0) / children.length;
|
|
14385
|
-
const progress = Math.round(avg);
|
|
14386
|
-
if (task.frontmatter.progress !== progress) {
|
|
14387
|
-
store.update(taskId, { progress });
|
|
14376
|
+
if (!options?.skipSelf) {
|
|
14377
|
+
if (DONE_STATUSES.has(task.frontmatter.status)) {
|
|
14378
|
+
if (task.frontmatter.progress !== 100) {
|
|
14379
|
+
store.update(taskId, { progress: 100 });
|
|
14388
14380
|
updated.push(taskId);
|
|
14389
14381
|
}
|
|
14382
|
+
} else if (!task.frontmatter.progressOverride) {
|
|
14383
|
+
const children = store.list({ type: "contribution" }).filter((d) => d.frontmatter.aboutArtifact === taskId);
|
|
14384
|
+
if (children.length > 0) {
|
|
14385
|
+
const avg = children.reduce((sum, c) => sum + getEffectiveProgress(c.frontmatter), 0) / children.length;
|
|
14386
|
+
const progress = Math.round(avg);
|
|
14387
|
+
if (task.frontmatter.progress !== progress) {
|
|
14388
|
+
store.update(taskId, { progress });
|
|
14389
|
+
updated.push(taskId);
|
|
14390
|
+
}
|
|
14391
|
+
}
|
|
14390
14392
|
}
|
|
14391
14393
|
}
|
|
14392
14394
|
const aboutArtifact = task.frontmatter.aboutArtifact;
|
|
@@ -14398,10 +14400,11 @@ function propagateProgressFromTask(store, taskId) {
|
|
|
14398
14400
|
}
|
|
14399
14401
|
return updated;
|
|
14400
14402
|
}
|
|
14401
|
-
function propagateProgressToAction(store, actionId) {
|
|
14403
|
+
function propagateProgressToAction(store, actionId, options) {
|
|
14402
14404
|
const updated = [];
|
|
14403
14405
|
const action = store.get(actionId);
|
|
14404
14406
|
if (!action) return updated;
|
|
14407
|
+
if (options?.skipSelf) return updated;
|
|
14405
14408
|
if (DONE_STATUSES.has(action.frontmatter.status)) {
|
|
14406
14409
|
if (action.frontmatter.progress !== 100) {
|
|
14407
14410
|
store.update(actionId, { progress: 100 });
|
|
@@ -14586,10 +14589,11 @@ function createActionTools(store) {
|
|
|
14586
14589
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace all tags. When provided with sprints, sprint tags are merged into this array."),
|
|
14587
14590
|
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001']."),
|
|
14588
14591
|
workFocus: external_exports.string().optional().describe("Work focus name (e.g. 'Budget UX'). Replaces existing focus:<value> tag."),
|
|
14589
|
-
progress: external_exports.number().nullable().optional().describe("Explicit progress percentage (0-100). Pass null to clear the override and revert to auto-calculation from children.")
|
|
14592
|
+
progress: external_exports.number().nullable().optional().describe("Explicit progress percentage (0-100). Pass null to clear the override and revert to auto-calculation from children."),
|
|
14593
|
+
progressOverride: external_exports.boolean().optional().describe("Control auto-calculation lock. true = lock progress to explicit value, false = allow auto-calculation from children. When omitted: setting progress implies true, null progress implies false.")
|
|
14590
14594
|
},
|
|
14591
14595
|
async (args) => {
|
|
14592
|
-
const { id, content, sprints, tags, workFocus, progress, owner, assignee, ...updates } = args;
|
|
14596
|
+
const { id, content, sprints, tags, workFocus, progress, progressOverride, owner, assignee, ...updates } = args;
|
|
14593
14597
|
if (owner !== void 0) updates.owner = normalizeOwner(owner);
|
|
14594
14598
|
if (assignee !== void 0) updates.assignee = assignee;
|
|
14595
14599
|
if (tags !== void 0) {
|
|
@@ -14628,13 +14632,17 @@ function createActionTools(store) {
|
|
|
14628
14632
|
}
|
|
14629
14633
|
if (typeof progress === "number") {
|
|
14630
14634
|
updates.progress = Math.max(0, Math.min(100, Math.round(progress)));
|
|
14631
|
-
updates.progressOverride = true;
|
|
14635
|
+
updates.progressOverride = progressOverride ?? true;
|
|
14632
14636
|
} else if (progress === null) {
|
|
14633
14637
|
updates.progressOverride = false;
|
|
14638
|
+
} else if (progressOverride !== void 0) {
|
|
14639
|
+
updates.progressOverride = progressOverride;
|
|
14634
14640
|
}
|
|
14635
14641
|
const doc = store.update(id, updates, content);
|
|
14636
14642
|
if (args.status !== void 0 || typeof progress === "number") {
|
|
14637
|
-
propagateProgressToAction(store, id
|
|
14643
|
+
propagateProgressToAction(store, id, {
|
|
14644
|
+
skipSelf: typeof progress === "number"
|
|
14645
|
+
});
|
|
14638
14646
|
}
|
|
14639
14647
|
return {
|
|
14640
14648
|
content: [
|
|
@@ -17867,10 +17875,11 @@ function createTaskTools(store) {
|
|
|
17867
17875
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("New priority"),
|
|
17868
17876
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)"),
|
|
17869
17877
|
workFocus: external_exports.string().optional().describe("Work focus name (e.g. 'Budget UX'). Replaces existing focus:<value> tag."),
|
|
17870
|
-
progress: external_exports.number().nullable().optional().describe("Explicit progress percentage (0-100). Overrides auto-calculation from child contributions. Pass null to clear the override and revert to auto-calculation.")
|
|
17878
|
+
progress: external_exports.number().nullable().optional().describe("Explicit progress percentage (0-100). Overrides auto-calculation from child contributions. Pass null to clear the override and revert to auto-calculation."),
|
|
17879
|
+
progressOverride: external_exports.boolean().optional().describe("Control auto-calculation lock. true = lock progress to explicit value, false = allow auto-calculation from children. When omitted: setting progress implies true, null progress implies false.")
|
|
17871
17880
|
},
|
|
17872
17881
|
async (args) => {
|
|
17873
|
-
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workFocus, progress, ...updates } = args;
|
|
17882
|
+
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workFocus, progress, progressOverride, ...updates } = args;
|
|
17874
17883
|
const warnings = [];
|
|
17875
17884
|
if (rawLinkedEpic !== void 0) {
|
|
17876
17885
|
const linkedEpics = normalizeLinkedEpics(rawLinkedEpic);
|
|
@@ -17899,13 +17908,17 @@ function createTaskTools(store) {
|
|
|
17899
17908
|
}
|
|
17900
17909
|
if (typeof progress === "number") {
|
|
17901
17910
|
updates.progress = Math.max(0, Math.min(100, Math.round(progress)));
|
|
17902
|
-
updates.progressOverride = true;
|
|
17911
|
+
updates.progressOverride = progressOverride ?? true;
|
|
17903
17912
|
} else if (progress === null) {
|
|
17904
17913
|
updates.progressOverride = false;
|
|
17914
|
+
} else if (progressOverride !== void 0) {
|
|
17915
|
+
updates.progressOverride = progressOverride;
|
|
17905
17916
|
}
|
|
17906
17917
|
const doc = store.update(id, updates, content);
|
|
17907
17918
|
if (args.status !== void 0 || typeof progress === "number") {
|
|
17908
|
-
propagateProgressFromTask(store, id
|
|
17919
|
+
propagateProgressFromTask(store, id, {
|
|
17920
|
+
skipSelf: typeof progress === "number"
|
|
17921
|
+
});
|
|
17909
17922
|
}
|
|
17910
17923
|
const parts = [`Updated task ${doc.frontmatter.id}: ${doc.frontmatter.title}`];
|
|
17911
17924
|
if (warnings.length > 0) {
|
|
@@ -20771,8 +20784,14 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20771
20784
|
const signals = buildSignals(commentSignals, linkedIssues, statusDrift, proposedMarvinStatus);
|
|
20772
20785
|
const appliedUpdates = [];
|
|
20773
20786
|
if (options.applyUpdates && proposedUpdates.length > 0) {
|
|
20787
|
+
const doneArtifacts = new Set(
|
|
20788
|
+
proposedUpdates.filter((u) => u.field === "status" && DONE_STATUSES6.has(String(u.proposedValue))).map((u) => u.artifactId)
|
|
20789
|
+
);
|
|
20774
20790
|
for (const update of proposedUpdates) {
|
|
20775
20791
|
if (update.field === "review") continue;
|
|
20792
|
+
if (update.field === "progress" && doneArtifacts.has(update.artifactId)) {
|
|
20793
|
+
if (update.proposedValue !== 100) continue;
|
|
20794
|
+
}
|
|
20776
20795
|
try {
|
|
20777
20796
|
const updatePayload = {
|
|
20778
20797
|
[update.field]: update.proposedValue,
|
|
@@ -20782,12 +20801,14 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20782
20801
|
updatePayload.progressOverride = false;
|
|
20783
20802
|
}
|
|
20784
20803
|
store.update(update.artifactId, updatePayload);
|
|
20785
|
-
|
|
20786
|
-
|
|
20787
|
-
if (updatedDoc
|
|
20788
|
-
|
|
20789
|
-
|
|
20790
|
-
|
|
20804
|
+
if (update.field === "status") {
|
|
20805
|
+
const updatedDoc = store.get(update.artifactId);
|
|
20806
|
+
if (updatedDoc) {
|
|
20807
|
+
if (updatedDoc.frontmatter.type === "task") {
|
|
20808
|
+
propagateProgressFromTask(store, update.artifactId);
|
|
20809
|
+
} else if (updatedDoc.frontmatter.type === "action") {
|
|
20810
|
+
propagateProgressToAction(store, update.artifactId);
|
|
20811
|
+
}
|
|
20791
20812
|
}
|
|
20792
20813
|
}
|
|
20793
20814
|
appliedUpdates.push(update);
|