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.js
CHANGED
|
@@ -14517,24 +14517,26 @@ function getEffectiveProgress(frontmatter) {
|
|
|
14517
14517
|
if (typeof raw === "number") return Math.max(0, Math.min(100, Math.round(raw)));
|
|
14518
14518
|
return STATUS_PROGRESS_DEFAULTS[frontmatter.status] ?? 0;
|
|
14519
14519
|
}
|
|
14520
|
-
function propagateProgressFromTask(store, taskId) {
|
|
14520
|
+
function propagateProgressFromTask(store, taskId, options) {
|
|
14521
14521
|
const updated = [];
|
|
14522
14522
|
const task = store.get(taskId);
|
|
14523
14523
|
if (!task) return updated;
|
|
14524
|
-
if (
|
|
14525
|
-
if (task.frontmatter.
|
|
14526
|
-
|
|
14527
|
-
|
|
14528
|
-
}
|
|
14529
|
-
} else if (!task.frontmatter.progressOverride) {
|
|
14530
|
-
const children = store.list({ type: "contribution" }).filter((d) => d.frontmatter.aboutArtifact === taskId);
|
|
14531
|
-
if (children.length > 0) {
|
|
14532
|
-
const avg = children.reduce((sum, c) => sum + getEffectiveProgress(c.frontmatter), 0) / children.length;
|
|
14533
|
-
const progress = Math.round(avg);
|
|
14534
|
-
if (task.frontmatter.progress !== progress) {
|
|
14535
|
-
store.update(taskId, { progress });
|
|
14524
|
+
if (!options?.skipSelf) {
|
|
14525
|
+
if (DONE_STATUSES.has(task.frontmatter.status)) {
|
|
14526
|
+
if (task.frontmatter.progress !== 100) {
|
|
14527
|
+
store.update(taskId, { progress: 100 });
|
|
14536
14528
|
updated.push(taskId);
|
|
14537
14529
|
}
|
|
14530
|
+
} else if (!task.frontmatter.progressOverride) {
|
|
14531
|
+
const children = store.list({ type: "contribution" }).filter((d) => d.frontmatter.aboutArtifact === taskId);
|
|
14532
|
+
if (children.length > 0) {
|
|
14533
|
+
const avg = children.reduce((sum, c) => sum + getEffectiveProgress(c.frontmatter), 0) / children.length;
|
|
14534
|
+
const progress = Math.round(avg);
|
|
14535
|
+
if (task.frontmatter.progress !== progress) {
|
|
14536
|
+
store.update(taskId, { progress });
|
|
14537
|
+
updated.push(taskId);
|
|
14538
|
+
}
|
|
14539
|
+
}
|
|
14538
14540
|
}
|
|
14539
14541
|
}
|
|
14540
14542
|
const aboutArtifact = task.frontmatter.aboutArtifact;
|
|
@@ -14546,10 +14548,11 @@ function propagateProgressFromTask(store, taskId) {
|
|
|
14546
14548
|
}
|
|
14547
14549
|
return updated;
|
|
14548
14550
|
}
|
|
14549
|
-
function propagateProgressToAction(store, actionId) {
|
|
14551
|
+
function propagateProgressToAction(store, actionId, options) {
|
|
14550
14552
|
const updated = [];
|
|
14551
14553
|
const action = store.get(actionId);
|
|
14552
14554
|
if (!action) return updated;
|
|
14555
|
+
if (options?.skipSelf) return updated;
|
|
14553
14556
|
if (DONE_STATUSES.has(action.frontmatter.status)) {
|
|
14554
14557
|
if (action.frontmatter.progress !== 100) {
|
|
14555
14558
|
store.update(actionId, { progress: 100 });
|
|
@@ -16824,10 +16827,11 @@ function createTaskTools(store) {
|
|
|
16824
16827
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("New priority"),
|
|
16825
16828
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)"),
|
|
16826
16829
|
workFocus: external_exports.string().optional().describe("Work focus name (e.g. 'Budget UX'). Replaces existing focus:<value> tag."),
|
|
16827
|
-
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.")
|
|
16830
|
+
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."),
|
|
16831
|
+
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.")
|
|
16828
16832
|
},
|
|
16829
16833
|
async (args) => {
|
|
16830
|
-
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workFocus, progress, ...updates } = args;
|
|
16834
|
+
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workFocus, progress, progressOverride, ...updates } = args;
|
|
16831
16835
|
const warnings = [];
|
|
16832
16836
|
if (rawLinkedEpic !== void 0) {
|
|
16833
16837
|
const linkedEpics = normalizeLinkedEpics(rawLinkedEpic);
|
|
@@ -16856,13 +16860,17 @@ function createTaskTools(store) {
|
|
|
16856
16860
|
}
|
|
16857
16861
|
if (typeof progress === "number") {
|
|
16858
16862
|
updates.progress = Math.max(0, Math.min(100, Math.round(progress)));
|
|
16859
|
-
updates.progressOverride = true;
|
|
16863
|
+
updates.progressOverride = progressOverride ?? true;
|
|
16860
16864
|
} else if (progress === null) {
|
|
16861
16865
|
updates.progressOverride = false;
|
|
16866
|
+
} else if (progressOverride !== void 0) {
|
|
16867
|
+
updates.progressOverride = progressOverride;
|
|
16862
16868
|
}
|
|
16863
16869
|
const doc = store.update(id, updates, content);
|
|
16864
16870
|
if (args.status !== void 0 || typeof progress === "number") {
|
|
16865
|
-
propagateProgressFromTask(store, id
|
|
16871
|
+
propagateProgressFromTask(store, id, {
|
|
16872
|
+
skipSelf: typeof progress === "number"
|
|
16873
|
+
});
|
|
16866
16874
|
}
|
|
16867
16875
|
const parts = [`Updated task ${doc.frontmatter.id}: ${doc.frontmatter.title}`];
|
|
16868
16876
|
if (warnings.length > 0) {
|
|
@@ -18915,10 +18923,11 @@ function createActionTools(store) {
|
|
|
18915
18923
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace all tags. When provided with sprints, sprint tags are merged into this array."),
|
|
18916
18924
|
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001']."),
|
|
18917
18925
|
workFocus: external_exports.string().optional().describe("Work focus name (e.g. 'Budget UX'). Replaces existing focus:<value> tag."),
|
|
18918
|
-
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.")
|
|
18926
|
+
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."),
|
|
18927
|
+
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.")
|
|
18919
18928
|
},
|
|
18920
18929
|
async (args) => {
|
|
18921
|
-
const { id, content, sprints, tags, workFocus, progress, owner, assignee, ...updates } = args;
|
|
18930
|
+
const { id, content, sprints, tags, workFocus, progress, progressOverride, owner, assignee, ...updates } = args;
|
|
18922
18931
|
if (owner !== void 0) updates.owner = normalizeOwner(owner);
|
|
18923
18932
|
if (assignee !== void 0) updates.assignee = assignee;
|
|
18924
18933
|
if (tags !== void 0) {
|
|
@@ -18957,13 +18966,17 @@ function createActionTools(store) {
|
|
|
18957
18966
|
}
|
|
18958
18967
|
if (typeof progress === "number") {
|
|
18959
18968
|
updates.progress = Math.max(0, Math.min(100, Math.round(progress)));
|
|
18960
|
-
updates.progressOverride = true;
|
|
18969
|
+
updates.progressOverride = progressOverride ?? true;
|
|
18961
18970
|
} else if (progress === null) {
|
|
18962
18971
|
updates.progressOverride = false;
|
|
18972
|
+
} else if (progressOverride !== void 0) {
|
|
18973
|
+
updates.progressOverride = progressOverride;
|
|
18963
18974
|
}
|
|
18964
18975
|
const doc = store.update(id, updates, content);
|
|
18965
18976
|
if (args.status !== void 0 || typeof progress === "number") {
|
|
18966
|
-
propagateProgressToAction(store, id
|
|
18977
|
+
propagateProgressToAction(store, id, {
|
|
18978
|
+
skipSelf: typeof progress === "number"
|
|
18979
|
+
});
|
|
18967
18980
|
}
|
|
18968
18981
|
return {
|
|
18969
18982
|
content: [
|
|
@@ -26982,8 +26995,14 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
26982
26995
|
const signals = buildSignals(commentSignals, linkedIssues, statusDrift, proposedMarvinStatus);
|
|
26983
26996
|
const appliedUpdates = [];
|
|
26984
26997
|
if (options.applyUpdates && proposedUpdates.length > 0) {
|
|
26998
|
+
const doneArtifacts = new Set(
|
|
26999
|
+
proposedUpdates.filter((u) => u.field === "status" && DONE_STATUSES15.has(String(u.proposedValue))).map((u) => u.artifactId)
|
|
27000
|
+
);
|
|
26985
27001
|
for (const update of proposedUpdates) {
|
|
26986
27002
|
if (update.field === "review") continue;
|
|
27003
|
+
if (update.field === "progress" && doneArtifacts.has(update.artifactId)) {
|
|
27004
|
+
if (update.proposedValue !== 100) continue;
|
|
27005
|
+
}
|
|
26987
27006
|
try {
|
|
26988
27007
|
const updatePayload = {
|
|
26989
27008
|
[update.field]: update.proposedValue,
|
|
@@ -26993,12 +27012,14 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
26993
27012
|
updatePayload.progressOverride = false;
|
|
26994
27013
|
}
|
|
26995
27014
|
store.update(update.artifactId, updatePayload);
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
if (updatedDoc
|
|
26999
|
-
|
|
27000
|
-
|
|
27001
|
-
|
|
27015
|
+
if (update.field === "status") {
|
|
27016
|
+
const updatedDoc = store.get(update.artifactId);
|
|
27017
|
+
if (updatedDoc) {
|
|
27018
|
+
if (updatedDoc.frontmatter.type === "task") {
|
|
27019
|
+
propagateProgressFromTask(store, update.artifactId);
|
|
27020
|
+
} else if (updatedDoc.frontmatter.type === "action") {
|
|
27021
|
+
propagateProgressToAction(store, update.artifactId);
|
|
27022
|
+
}
|
|
27002
27023
|
}
|
|
27003
27024
|
}
|
|
27004
27025
|
appliedUpdates.push(update);
|
|
@@ -33546,7 +33567,7 @@ function createProgram() {
|
|
|
33546
33567
|
const program2 = new Command();
|
|
33547
33568
|
program2.name("marvin").description(
|
|
33548
33569
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
33549
|
-
).version("0.5.
|
|
33570
|
+
).version("0.5.21");
|
|
33550
33571
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
33551
33572
|
await initCommand();
|
|
33552
33573
|
});
|