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.js
CHANGED
|
@@ -22430,7 +22430,10 @@ function normalizeEntry(entry) {
|
|
|
22430
22430
|
childCount: typeof entry.childCount === "number" ? entry.childCount : 0,
|
|
22431
22431
|
childDoneCount: typeof entry.childDoneCount === "number" ? entry.childDoneCount : 0,
|
|
22432
22432
|
childRollupProgress: typeof entry.childRollupProgress === "number" ? entry.childRollupProgress : null,
|
|
22433
|
-
linkedIssueCount: typeof entry.linkedIssueCount === "number" ? entry.linkedIssueCount : 0
|
|
22433
|
+
linkedIssueCount: typeof entry.linkedIssueCount === "number" ? entry.linkedIssueCount : 0,
|
|
22434
|
+
blockerProgress: typeof entry.blockerProgress === "number" ? entry.blockerProgress : null,
|
|
22435
|
+
totalBlockers: typeof entry.totalBlockers === "number" ? entry.totalBlockers : 0,
|
|
22436
|
+
resolvedBlockers: typeof entry.resolvedBlockers === "number" ? entry.resolvedBlockers : 0
|
|
22434
22437
|
};
|
|
22435
22438
|
}
|
|
22436
22439
|
function renderAssessmentTimeline(history) {
|
|
@@ -22450,6 +22453,10 @@ function renderAssessmentTimeline(history) {
|
|
|
22450
22453
|
const bar = progressBarHtml(entry.childRollupProgress ?? 0);
|
|
22451
22454
|
parts.push(`<div class="assessment-stat">\u{1F476} Children: ${entry.childDoneCount}/${entry.childCount} done ${bar} ${entry.childRollupProgress ?? 0}%</div>`);
|
|
22452
22455
|
}
|
|
22456
|
+
if (entry.totalBlockers > 0) {
|
|
22457
|
+
const bar = progressBarHtml(entry.blockerProgress ?? 0);
|
|
22458
|
+
parts.push(`<div class="assessment-stat">\u{1F6A7} Blockers: ${entry.resolvedBlockers}/${entry.totalBlockers} resolved ${bar} ${entry.blockerProgress ?? 0}%</div>`);
|
|
22459
|
+
}
|
|
22453
22460
|
if (entry.linkedIssueCount > 0) {
|
|
22454
22461
|
parts.push(`<div class="assessment-stat">\u{1F517} Linked issues: ${entry.linkedIssueCount}</div>`);
|
|
22455
22462
|
}
|
|
@@ -27272,6 +27279,15 @@ function analyzeLinkedIssueSignals(linkedIssues, frontmatter, jiraKey, proposedU
|
|
|
27272
27279
|
});
|
|
27273
27280
|
}
|
|
27274
27281
|
}
|
|
27282
|
+
function computeBlockerProgress(linkedIssues, prerequisiteWeight) {
|
|
27283
|
+
const blockerLinks = linkedIssues.filter(
|
|
27284
|
+
(l) => BLOCKER_LINK_PATTERNS.some((p) => l.relationship.toLowerCase().includes(p.split(" ")[0]))
|
|
27285
|
+
);
|
|
27286
|
+
if (blockerLinks.length === 0) return null;
|
|
27287
|
+
const resolved = blockerLinks.filter((l) => l.isDone).length;
|
|
27288
|
+
const blockerProgress = Math.round(resolved / blockerLinks.length * prerequisiteWeight * 100);
|
|
27289
|
+
return { blockerProgress, totalBlockers: blockerLinks.length, resolvedBlockers: resolved };
|
|
27290
|
+
}
|
|
27275
27291
|
var LINKED_COMMENT_ANALYSIS_PROMPT = `You are a delivery management assistant analyzing Jira comments from linked issues for progress signals.
|
|
27276
27292
|
|
|
27277
27293
|
For each linked issue below, read the comments and produce a 1-sentence summary focused on: impact on the parent issue, blockers, or decisions.
|
|
@@ -27685,6 +27701,39 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
27685
27701
|
});
|
|
27686
27702
|
}
|
|
27687
27703
|
}
|
|
27704
|
+
const prerequisiteWeight = options.prerequisiteWeight ?? 0.3;
|
|
27705
|
+
const blockerResult = computeBlockerProgress(linkedIssues, prerequisiteWeight);
|
|
27706
|
+
let blockerProgressValue = null;
|
|
27707
|
+
let totalBlockersCount = 0;
|
|
27708
|
+
let resolvedBlockersCount = 0;
|
|
27709
|
+
if (blockerResult && !fm.progressOverride && !DONE_STATUSES15.has(fm.status)) {
|
|
27710
|
+
blockerProgressValue = blockerResult.blockerProgress;
|
|
27711
|
+
totalBlockersCount = blockerResult.totalBlockers;
|
|
27712
|
+
resolvedBlockersCount = blockerResult.resolvedBlockers;
|
|
27713
|
+
const lastProgressUpdate = findLast(proposedUpdates, (u) => u.artifactId === fm.id && u.field === "progress");
|
|
27714
|
+
const implementationProgress = lastProgressUpdate ? lastProgressUpdate.proposedValue : currentProgress;
|
|
27715
|
+
const combinedProgress = Math.round(
|
|
27716
|
+
blockerResult.blockerProgress + implementationProgress * (1 - prerequisiteWeight)
|
|
27717
|
+
);
|
|
27718
|
+
const estimatedProgress = Math.max(currentProgress, combinedProgress);
|
|
27719
|
+
if (estimatedProgress !== currentProgress && estimatedProgress !== implementationProgress) {
|
|
27720
|
+
for (let i = proposedUpdates.length - 1; i >= 0; i--) {
|
|
27721
|
+
if (proposedUpdates[i].artifactId === fm.id && proposedUpdates[i].field === "progress") {
|
|
27722
|
+
proposedUpdates.splice(i, 1);
|
|
27723
|
+
}
|
|
27724
|
+
}
|
|
27725
|
+
proposedUpdates.push({
|
|
27726
|
+
artifactId: fm.id,
|
|
27727
|
+
field: "progress",
|
|
27728
|
+
currentValue: currentProgress,
|
|
27729
|
+
proposedValue: estimatedProgress,
|
|
27730
|
+
reason: `Blocker resolution (${resolvedBlockersCount}/${totalBlockersCount}) + implementation \u2192 dependency-weighted progress ${estimatedProgress}%`
|
|
27731
|
+
});
|
|
27732
|
+
}
|
|
27733
|
+
} else if (blockerResult) {
|
|
27734
|
+
totalBlockersCount = blockerResult.totalBlockers;
|
|
27735
|
+
resolvedBlockersCount = blockerResult.resolvedBlockers;
|
|
27736
|
+
}
|
|
27688
27737
|
const signals = buildSignals(commentSignals, linkedIssues, statusDrift, proposedMarvinStatus);
|
|
27689
27738
|
const appliedUpdates = [];
|
|
27690
27739
|
if (options.applyUpdates && proposedUpdates.length > 0) {
|
|
@@ -27727,7 +27776,10 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
27727
27776
|
commentAnalysisProgress,
|
|
27728
27777
|
signals,
|
|
27729
27778
|
children,
|
|
27730
|
-
linkedIssues
|
|
27779
|
+
linkedIssues,
|
|
27780
|
+
blockerProgressValue,
|
|
27781
|
+
totalBlockersCount,
|
|
27782
|
+
resolvedBlockersCount
|
|
27731
27783
|
);
|
|
27732
27784
|
const existingHistory = Array.isArray(fm.assessmentHistory) ? fm.assessmentHistory : [];
|
|
27733
27785
|
const legacySummary = fm.assessmentSummary;
|
|
@@ -27776,6 +27828,9 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
27776
27828
|
commentAnalysisProgress,
|
|
27777
27829
|
linkedIssues,
|
|
27778
27830
|
linkedIssueSignals,
|
|
27831
|
+
blockerProgress: blockerProgressValue,
|
|
27832
|
+
totalBlockers: totalBlockersCount,
|
|
27833
|
+
resolvedBlockers: resolvedBlockersCount,
|
|
27779
27834
|
children,
|
|
27780
27835
|
proposedUpdates: options.applyUpdates ? [] : proposedUpdates,
|
|
27781
27836
|
appliedUpdates,
|
|
@@ -27955,6 +28010,9 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
27955
28010
|
commentAnalysisProgress: null,
|
|
27956
28011
|
linkedIssues: [],
|
|
27957
28012
|
linkedIssueSignals: [],
|
|
28013
|
+
blockerProgress: null,
|
|
28014
|
+
totalBlockers: 0,
|
|
28015
|
+
resolvedBlockers: 0,
|
|
27958
28016
|
children: [],
|
|
27959
28017
|
proposedUpdates: [],
|
|
27960
28018
|
appliedUpdates: [],
|
|
@@ -27962,7 +28020,7 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
27962
28020
|
errors
|
|
27963
28021
|
};
|
|
27964
28022
|
}
|
|
27965
|
-
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues) {
|
|
28023
|
+
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues, blockerProgress = null, totalBlockers = 0, resolvedBlockers = 0) {
|
|
27966
28024
|
const childProgressValues = children.map((c) => {
|
|
27967
28025
|
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
27968
28026
|
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
@@ -27986,7 +28044,10 @@ function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals
|
|
|
27986
28044
|
childCount: children.length,
|
|
27987
28045
|
childDoneCount,
|
|
27988
28046
|
childRollupProgress,
|
|
27989
|
-
linkedIssueCount: linkedIssues.length
|
|
28047
|
+
linkedIssueCount: linkedIssues.length,
|
|
28048
|
+
blockerProgress,
|
|
28049
|
+
totalBlockers,
|
|
28050
|
+
resolvedBlockers
|
|
27990
28051
|
};
|
|
27991
28052
|
}
|
|
27992
28053
|
function formatArtifactReport(report) {
|
|
@@ -28022,6 +28083,12 @@ function formatArtifactReport(report) {
|
|
|
28022
28083
|
}
|
|
28023
28084
|
parts.push("");
|
|
28024
28085
|
}
|
|
28086
|
+
if (report.totalBlockers > 0) {
|
|
28087
|
+
parts.push(`## Blocker Resolution`);
|
|
28088
|
+
const bpLabel = report.blockerProgress !== null ? `${report.blockerProgress}%` : "n/a (skipped)";
|
|
28089
|
+
parts.push(` ${report.resolvedBlockers}/${report.totalBlockers} blockers resolved \u2192 ${bpLabel} prerequisite progress`);
|
|
28090
|
+
parts.push("");
|
|
28091
|
+
}
|
|
28025
28092
|
if (report.children.length > 0) {
|
|
28026
28093
|
const doneCount = report.children.filter((c) => DONE_STATUSES15.has(c.marvinStatus)).length;
|
|
28027
28094
|
const childProgress = Math.round(
|
|
@@ -28920,10 +28987,11 @@ function createJiraTools(store, projectConfig) {
|
|
|
28920
28987
|
// --- Single-artifact assessment ---
|
|
28921
28988
|
tool20(
|
|
28922
28989
|
"assess_artifact",
|
|
28923
|
-
"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).",
|
|
28990
|
+
"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).",
|
|
28924
28991
|
{
|
|
28925
28992
|
artifactId: external_exports.string().describe("Marvin artifact ID (e.g. 'T-063', 'A-151', 'E-003')"),
|
|
28926
|
-
applyUpdates: external_exports.boolean().optional().describe("Apply proposed status/progress updates to the artifact (default false)")
|
|
28993
|
+
applyUpdates: external_exports.boolean().optional().describe("Apply proposed status/progress updates to the artifact (default false)"),
|
|
28994
|
+
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.")
|
|
28927
28995
|
},
|
|
28928
28996
|
async (args) => {
|
|
28929
28997
|
const jira = createJiraClient(jiraUserConfig);
|
|
@@ -28935,6 +29003,7 @@ function createJiraTools(store, projectConfig) {
|
|
|
28935
29003
|
{
|
|
28936
29004
|
artifactId: args.artifactId,
|
|
28937
29005
|
applyUpdates: args.applyUpdates ?? false,
|
|
29006
|
+
prerequisiteWeight: args.prerequisiteWeight,
|
|
28938
29007
|
statusMap
|
|
28939
29008
|
}
|
|
28940
29009
|
);
|
|
@@ -34349,7 +34418,7 @@ function createProgram() {
|
|
|
34349
34418
|
const program2 = new Command();
|
|
34350
34419
|
program2.name("marvin").description(
|
|
34351
34420
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
34352
|
-
).version("0.5.
|
|
34421
|
+
).version("0.5.27");
|
|
34353
34422
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
34354
34423
|
await initCommand();
|
|
34355
34424
|
});
|