mrvn-cli 0.5.26 → 0.5.27
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 +76 -7
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +75 -6
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +76 -7
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin-serve.js
CHANGED
|
@@ -20606,6 +20606,15 @@ function analyzeLinkedIssueSignals(linkedIssues, frontmatter, jiraKey, proposedU
|
|
|
20606
20606
|
});
|
|
20607
20607
|
}
|
|
20608
20608
|
}
|
|
20609
|
+
function computeBlockerProgress(linkedIssues, prerequisiteWeight) {
|
|
20610
|
+
const blockerLinks = linkedIssues.filter(
|
|
20611
|
+
(l) => BLOCKER_LINK_PATTERNS.some((p) => l.relationship.toLowerCase().includes(p.split(" ")[0]))
|
|
20612
|
+
);
|
|
20613
|
+
if (blockerLinks.length === 0) return null;
|
|
20614
|
+
const resolved = blockerLinks.filter((l) => l.isDone).length;
|
|
20615
|
+
const blockerProgress = Math.round(resolved / blockerLinks.length * prerequisiteWeight * 100);
|
|
20616
|
+
return { blockerProgress, totalBlockers: blockerLinks.length, resolvedBlockers: resolved };
|
|
20617
|
+
}
|
|
20609
20618
|
var LINKED_COMMENT_ANALYSIS_PROMPT = `You are a delivery management assistant analyzing Jira comments from linked issues for progress signals.
|
|
20610
20619
|
|
|
20611
20620
|
For each linked issue below, read the comments and produce a 1-sentence summary focused on: impact on the parent issue, blockers, or decisions.
|
|
@@ -21019,6 +21028,39 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
21019
21028
|
});
|
|
21020
21029
|
}
|
|
21021
21030
|
}
|
|
21031
|
+
const prerequisiteWeight = options.prerequisiteWeight ?? 0.3;
|
|
21032
|
+
const blockerResult = computeBlockerProgress(linkedIssues, prerequisiteWeight);
|
|
21033
|
+
let blockerProgressValue = null;
|
|
21034
|
+
let totalBlockersCount = 0;
|
|
21035
|
+
let resolvedBlockersCount = 0;
|
|
21036
|
+
if (blockerResult && !fm.progressOverride && !DONE_STATUSES6.has(fm.status)) {
|
|
21037
|
+
blockerProgressValue = blockerResult.blockerProgress;
|
|
21038
|
+
totalBlockersCount = blockerResult.totalBlockers;
|
|
21039
|
+
resolvedBlockersCount = blockerResult.resolvedBlockers;
|
|
21040
|
+
const lastProgressUpdate = findLast(proposedUpdates, (u) => u.artifactId === fm.id && u.field === "progress");
|
|
21041
|
+
const implementationProgress = lastProgressUpdate ? lastProgressUpdate.proposedValue : currentProgress;
|
|
21042
|
+
const combinedProgress = Math.round(
|
|
21043
|
+
blockerResult.blockerProgress + implementationProgress * (1 - prerequisiteWeight)
|
|
21044
|
+
);
|
|
21045
|
+
const estimatedProgress = Math.max(currentProgress, combinedProgress);
|
|
21046
|
+
if (estimatedProgress !== currentProgress && estimatedProgress !== implementationProgress) {
|
|
21047
|
+
for (let i = proposedUpdates.length - 1; i >= 0; i--) {
|
|
21048
|
+
if (proposedUpdates[i].artifactId === fm.id && proposedUpdates[i].field === "progress") {
|
|
21049
|
+
proposedUpdates.splice(i, 1);
|
|
21050
|
+
}
|
|
21051
|
+
}
|
|
21052
|
+
proposedUpdates.push({
|
|
21053
|
+
artifactId: fm.id,
|
|
21054
|
+
field: "progress",
|
|
21055
|
+
currentValue: currentProgress,
|
|
21056
|
+
proposedValue: estimatedProgress,
|
|
21057
|
+
reason: `Blocker resolution (${resolvedBlockersCount}/${totalBlockersCount}) + implementation \u2192 dependency-weighted progress ${estimatedProgress}%`
|
|
21058
|
+
});
|
|
21059
|
+
}
|
|
21060
|
+
} else if (blockerResult) {
|
|
21061
|
+
totalBlockersCount = blockerResult.totalBlockers;
|
|
21062
|
+
resolvedBlockersCount = blockerResult.resolvedBlockers;
|
|
21063
|
+
}
|
|
21022
21064
|
const signals = buildSignals(commentSignals, linkedIssues, statusDrift, proposedMarvinStatus);
|
|
21023
21065
|
const appliedUpdates = [];
|
|
21024
21066
|
if (options.applyUpdates && proposedUpdates.length > 0) {
|
|
@@ -21061,7 +21103,10 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
21061
21103
|
commentAnalysisProgress,
|
|
21062
21104
|
signals,
|
|
21063
21105
|
children,
|
|
21064
|
-
linkedIssues
|
|
21106
|
+
linkedIssues,
|
|
21107
|
+
blockerProgressValue,
|
|
21108
|
+
totalBlockersCount,
|
|
21109
|
+
resolvedBlockersCount
|
|
21065
21110
|
);
|
|
21066
21111
|
const existingHistory = Array.isArray(fm.assessmentHistory) ? fm.assessmentHistory : [];
|
|
21067
21112
|
const legacySummary = fm.assessmentSummary;
|
|
@@ -21110,6 +21155,9 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
21110
21155
|
commentAnalysisProgress,
|
|
21111
21156
|
linkedIssues,
|
|
21112
21157
|
linkedIssueSignals,
|
|
21158
|
+
blockerProgress: blockerProgressValue,
|
|
21159
|
+
totalBlockers: totalBlockersCount,
|
|
21160
|
+
resolvedBlockers: resolvedBlockersCount,
|
|
21113
21161
|
children,
|
|
21114
21162
|
proposedUpdates: options.applyUpdates ? [] : proposedUpdates,
|
|
21115
21163
|
appliedUpdates,
|
|
@@ -21289,6 +21337,9 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
21289
21337
|
commentAnalysisProgress: null,
|
|
21290
21338
|
linkedIssues: [],
|
|
21291
21339
|
linkedIssueSignals: [],
|
|
21340
|
+
blockerProgress: null,
|
|
21341
|
+
totalBlockers: 0,
|
|
21342
|
+
resolvedBlockers: 0,
|
|
21292
21343
|
children: [],
|
|
21293
21344
|
proposedUpdates: [],
|
|
21294
21345
|
appliedUpdates: [],
|
|
@@ -21296,7 +21347,7 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
21296
21347
|
errors
|
|
21297
21348
|
};
|
|
21298
21349
|
}
|
|
21299
|
-
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues) {
|
|
21350
|
+
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues, blockerProgress = null, totalBlockers = 0, resolvedBlockers = 0) {
|
|
21300
21351
|
const childProgressValues = children.map((c) => {
|
|
21301
21352
|
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
21302
21353
|
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
@@ -21320,7 +21371,10 @@ function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals
|
|
|
21320
21371
|
childCount: children.length,
|
|
21321
21372
|
childDoneCount,
|
|
21322
21373
|
childRollupProgress,
|
|
21323
|
-
linkedIssueCount: linkedIssues.length
|
|
21374
|
+
linkedIssueCount: linkedIssues.length,
|
|
21375
|
+
blockerProgress,
|
|
21376
|
+
totalBlockers,
|
|
21377
|
+
resolvedBlockers
|
|
21324
21378
|
};
|
|
21325
21379
|
}
|
|
21326
21380
|
function formatArtifactReport(report) {
|
|
@@ -21356,6 +21410,12 @@ function formatArtifactReport(report) {
|
|
|
21356
21410
|
}
|
|
21357
21411
|
parts.push("");
|
|
21358
21412
|
}
|
|
21413
|
+
if (report.totalBlockers > 0) {
|
|
21414
|
+
parts.push(`## Blocker Resolution`);
|
|
21415
|
+
const bpLabel = report.blockerProgress !== null ? `${report.blockerProgress}%` : "n/a (skipped)";
|
|
21416
|
+
parts.push(` ${report.resolvedBlockers}/${report.totalBlockers} blockers resolved \u2192 ${bpLabel} prerequisite progress`);
|
|
21417
|
+
parts.push("");
|
|
21418
|
+
}
|
|
21359
21419
|
if (report.children.length > 0) {
|
|
21360
21420
|
const doneCount = report.children.filter((c) => DONE_STATUSES6.has(c.marvinStatus)).length;
|
|
21361
21421
|
const childProgress = Math.round(
|
|
@@ -22254,10 +22314,11 @@ function createJiraTools(store, projectConfig) {
|
|
|
22254
22314
|
// --- Single-artifact assessment ---
|
|
22255
22315
|
tool20(
|
|
22256
22316
|
"assess_artifact",
|
|
22257
|
-
"Deep assessment of a single Marvin artifact (task, action, or epic). Fetches live Jira status, analyzes comments with LLM, traverses all linked issues, detects drift, rolls up child progress, and extracts contextual signals (blockers, unblocks, handoffs, superseded work).",
|
|
22317
|
+
"Deep assessment of a single Marvin artifact (task, action, or epic). Fetches live Jira status, analyzes comments with LLM, traverses all linked issues, detects drift, rolls up child progress, computes dependency-weighted progress from blocker resolution, and extracts contextual signals (blockers, unblocks, handoffs, superseded work).",
|
|
22258
22318
|
{
|
|
22259
22319
|
artifactId: external_exports.string().describe("Marvin artifact ID (e.g. 'T-063', 'A-151', 'E-003')"),
|
|
22260
|
-
applyUpdates: external_exports.boolean().optional().describe("Apply proposed status/progress updates to the artifact (default false)")
|
|
22320
|
+
applyUpdates: external_exports.boolean().optional().describe("Apply proposed status/progress updates to the artifact (default false)"),
|
|
22321
|
+
prerequisiteWeight: external_exports.number().min(0).max(1).optional().describe("Weight for blocker-resolution progress signal (0-1, default 0.3). Portion of effort attributed to dependency readiness.")
|
|
22261
22322
|
},
|
|
22262
22323
|
async (args) => {
|
|
22263
22324
|
const jira = createJiraClient(jiraUserConfig);
|
|
@@ -22269,6 +22330,7 @@ function createJiraTools(store, projectConfig) {
|
|
|
22269
22330
|
{
|
|
22270
22331
|
artifactId: args.artifactId,
|
|
22271
22332
|
applyUpdates: args.applyUpdates ?? false,
|
|
22333
|
+
prerequisiteWeight: args.prerequisiteWeight,
|
|
22272
22334
|
statusMap
|
|
22273
22335
|
}
|
|
22274
22336
|
);
|
|
@@ -25907,7 +25969,10 @@ function normalizeEntry(entry) {
|
|
|
25907
25969
|
childCount: typeof entry.childCount === "number" ? entry.childCount : 0,
|
|
25908
25970
|
childDoneCount: typeof entry.childDoneCount === "number" ? entry.childDoneCount : 0,
|
|
25909
25971
|
childRollupProgress: typeof entry.childRollupProgress === "number" ? entry.childRollupProgress : null,
|
|
25910
|
-
linkedIssueCount: typeof entry.linkedIssueCount === "number" ? entry.linkedIssueCount : 0
|
|
25972
|
+
linkedIssueCount: typeof entry.linkedIssueCount === "number" ? entry.linkedIssueCount : 0,
|
|
25973
|
+
blockerProgress: typeof entry.blockerProgress === "number" ? entry.blockerProgress : null,
|
|
25974
|
+
totalBlockers: typeof entry.totalBlockers === "number" ? entry.totalBlockers : 0,
|
|
25975
|
+
resolvedBlockers: typeof entry.resolvedBlockers === "number" ? entry.resolvedBlockers : 0
|
|
25911
25976
|
};
|
|
25912
25977
|
}
|
|
25913
25978
|
function renderAssessmentTimeline(history) {
|
|
@@ -25927,6 +25992,10 @@ function renderAssessmentTimeline(history) {
|
|
|
25927
25992
|
const bar = progressBarHtml(entry.childRollupProgress ?? 0);
|
|
25928
25993
|
parts.push(`<div class="assessment-stat">\u{1F476} Children: ${entry.childDoneCount}/${entry.childCount} done ${bar} ${entry.childRollupProgress ?? 0}%</div>`);
|
|
25929
25994
|
}
|
|
25995
|
+
if (entry.totalBlockers > 0) {
|
|
25996
|
+
const bar = progressBarHtml(entry.blockerProgress ?? 0);
|
|
25997
|
+
parts.push(`<div class="assessment-stat">\u{1F6A7} Blockers: ${entry.resolvedBlockers}/${entry.totalBlockers} resolved ${bar} ${entry.blockerProgress ?? 0}%</div>`);
|
|
25998
|
+
}
|
|
25930
25999
|
if (entry.linkedIssueCount > 0) {
|
|
25931
26000
|
parts.push(`<div class="assessment-stat">\u{1F517} Linked issues: ${entry.linkedIssueCount}</div>`);
|
|
25932
26001
|
}
|