mrvn-cli 0.5.22 → 0.5.24
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 +91 -12
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +90 -11
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +91 -12
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin-serve.js
CHANGED
|
@@ -20732,11 +20732,12 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20732
20732
|
}
|
|
20733
20733
|
}
|
|
20734
20734
|
const primaryHasComments = jiraKey ? (jiraIssues.get(jiraKey)?.comments.length ?? 0) > 0 : false;
|
|
20735
|
+
let commentAnalysisProgress = null;
|
|
20735
20736
|
if (depth < MAX_LLM_DEPTH && jiraKey && primaryHasComments) {
|
|
20736
20737
|
const estimatedChars = estimateCommentTextSize(jiraIssues, linkedJiraIssues, linkedIssueSignals);
|
|
20737
20738
|
if (estimatedChars <= MAX_LLM_COMMENT_CHARS) {
|
|
20738
20739
|
try {
|
|
20739
|
-
const
|
|
20740
|
+
const analysis = await analyzeSingleArtifactComments(
|
|
20740
20741
|
fm.id,
|
|
20741
20742
|
fm.title,
|
|
20742
20743
|
jiraKey,
|
|
@@ -20745,7 +20746,20 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20745
20746
|
linkedJiraIssues,
|
|
20746
20747
|
linkedIssueSignals
|
|
20747
20748
|
);
|
|
20748
|
-
commentSummary = summary;
|
|
20749
|
+
commentSummary = analysis.summary;
|
|
20750
|
+
commentAnalysisProgress = analysis.progressEstimate;
|
|
20751
|
+
if (commentAnalysisProgress !== null) {
|
|
20752
|
+
const hasExplicitProgress = "progress" in fm && typeof fm.progress === "number";
|
|
20753
|
+
if (!hasExplicitProgress && !fm.progressOverride && commentAnalysisProgress !== currentProgress) {
|
|
20754
|
+
proposedUpdates.push({
|
|
20755
|
+
artifactId: fm.id,
|
|
20756
|
+
field: "progress",
|
|
20757
|
+
currentValue: currentProgress,
|
|
20758
|
+
proposedValue: commentAnalysisProgress,
|
|
20759
|
+
reason: `Comment analysis estimates ${commentAnalysisProgress}% progress`
|
|
20760
|
+
});
|
|
20761
|
+
}
|
|
20762
|
+
}
|
|
20749
20763
|
} catch (err) {
|
|
20750
20764
|
errors.push(`Comment analysis failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
20751
20765
|
}
|
|
@@ -20826,6 +20840,23 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20826
20840
|
}
|
|
20827
20841
|
}
|
|
20828
20842
|
}
|
|
20843
|
+
if (options.applyUpdates) {
|
|
20844
|
+
const assessmentSummary = buildAssessmentSummary(
|
|
20845
|
+
commentSummary,
|
|
20846
|
+
commentAnalysisProgress,
|
|
20847
|
+
signals,
|
|
20848
|
+
children,
|
|
20849
|
+
linkedIssues
|
|
20850
|
+
);
|
|
20851
|
+
try {
|
|
20852
|
+
store.update(fm.id, {
|
|
20853
|
+
assessmentSummary,
|
|
20854
|
+
lastAssessedAt: assessmentSummary.generatedAt
|
|
20855
|
+
});
|
|
20856
|
+
} catch (err) {
|
|
20857
|
+
errors.push(`Failed to persist assessment summary: ${err instanceof Error ? err.message : String(err)}`);
|
|
20858
|
+
}
|
|
20859
|
+
}
|
|
20829
20860
|
return {
|
|
20830
20861
|
artifactId: fm.id,
|
|
20831
20862
|
title: fm.title,
|
|
@@ -20843,6 +20874,7 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
20843
20874
|
progressDrift,
|
|
20844
20875
|
commentSignals,
|
|
20845
20876
|
commentSummary,
|
|
20877
|
+
commentAnalysisProgress,
|
|
20846
20878
|
linkedIssues,
|
|
20847
20879
|
linkedIssueSignals,
|
|
20848
20880
|
children,
|
|
@@ -20935,13 +20967,15 @@ function estimateCommentTextSize(jiraIssues, linkedJiraIssues, linkedIssueSignal
|
|
|
20935
20967
|
}
|
|
20936
20968
|
var SINGLE_ARTIFACT_COMMENT_PROMPT = `You are a delivery management assistant analyzing Jira comments for a single work item.
|
|
20937
20969
|
|
|
20938
|
-
|
|
20939
|
-
-
|
|
20940
|
-
-
|
|
20941
|
-
- Any decisions, handoffs, or scheduling mentioned
|
|
20942
|
-
- Relevant context from linked issue comments (if provided)
|
|
20970
|
+
Analyze the comments and produce:
|
|
20971
|
+
1. A 2-3 sentence progress summary covering: what work has been completed, what is pending or blocked, any decisions/handoffs/scheduling mentioned, and relevant context from linked issue comments (if provided).
|
|
20972
|
+
2. A progress estimate (0-100%) based on evidence in the comments \u2014 e.g., if comments indicate all items have been triaged into tasks, or implementation is complete pending review, estimate accordingly. If you cannot determine progress from the comments, set progressEstimate to null.
|
|
20943
20973
|
|
|
20944
|
-
Return
|
|
20974
|
+
Return a JSON object with this exact structure:
|
|
20975
|
+
{"summary": "your 2-3 sentence summary", "progressEstimate": 75}
|
|
20976
|
+
|
|
20977
|
+
Use null for progressEstimate if the comments don't provide enough evidence to estimate.
|
|
20978
|
+
IMPORTANT: Only return the JSON object, no other text.`;
|
|
20945
20979
|
async function analyzeSingleArtifactComments(artifactId, title, jiraKey, jiraStatus, jiraIssues, linkedJiraIssues, linkedIssueSignals) {
|
|
20946
20980
|
const promptParts = [];
|
|
20947
20981
|
const primaryData = jiraIssues.get(jiraKey);
|
|
@@ -20964,7 +20998,7 @@ ${commentTexts}`);
|
|
|
20964
20998
|
promptParts.push(`### Linked: ${signal.sourceKey} (${signal.linkType})
|
|
20965
20999
|
${commentTexts}`);
|
|
20966
21000
|
}
|
|
20967
|
-
if (promptParts.length === 0) return null;
|
|
21001
|
+
if (promptParts.length === 0) return { summary: null, progressEstimate: null };
|
|
20968
21002
|
const prompt = promptParts.join("\n\n");
|
|
20969
21003
|
const result = query2({
|
|
20970
21004
|
prompt,
|
|
@@ -20981,11 +21015,25 @@ ${commentTexts}`);
|
|
|
20981
21015
|
(b) => b.type === "text"
|
|
20982
21016
|
);
|
|
20983
21017
|
if (textBlock) {
|
|
20984
|
-
return textBlock.text.trim();
|
|
21018
|
+
return parseCommentAnalysis(textBlock.text.trim());
|
|
20985
21019
|
}
|
|
20986
21020
|
}
|
|
20987
21021
|
}
|
|
20988
|
-
return null;
|
|
21022
|
+
return { summary: null, progressEstimate: null };
|
|
21023
|
+
}
|
|
21024
|
+
function parseCommentAnalysis(text) {
|
|
21025
|
+
const parsed = parseLlmJson(text);
|
|
21026
|
+
if (parsed && typeof parsed.summary === "string") {
|
|
21027
|
+
const progressEstimate2 = typeof parsed.progressEstimate === "number" && parsed.progressEstimate >= 0 && parsed.progressEstimate <= 100 ? Math.round(parsed.progressEstimate) : null;
|
|
21028
|
+
return { summary: parsed.summary, progressEstimate: progressEstimate2 };
|
|
21029
|
+
}
|
|
21030
|
+
let progressEstimate = null;
|
|
21031
|
+
const pctMatch = text.match(/(\d{1,3})%/);
|
|
21032
|
+
if (pctMatch) {
|
|
21033
|
+
const pct = parseInt(pctMatch[1], 10);
|
|
21034
|
+
if (pct >= 0 && pct <= 100) progressEstimate = pct;
|
|
21035
|
+
}
|
|
21036
|
+
return { summary: text, progressEstimate };
|
|
20989
21037
|
}
|
|
20990
21038
|
function emptyArtifactReport(artifactId, errors) {
|
|
20991
21039
|
return {
|
|
@@ -21005,6 +21053,7 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
21005
21053
|
progressDrift: false,
|
|
21006
21054
|
commentSignals: [],
|
|
21007
21055
|
commentSummary: null,
|
|
21056
|
+
commentAnalysisProgress: null,
|
|
21008
21057
|
linkedIssues: [],
|
|
21009
21058
|
linkedIssueSignals: [],
|
|
21010
21059
|
children: [],
|
|
@@ -21014,6 +21063,33 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
21014
21063
|
errors
|
|
21015
21064
|
};
|
|
21016
21065
|
}
|
|
21066
|
+
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues) {
|
|
21067
|
+
const childProgressValues = children.map((c) => {
|
|
21068
|
+
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
21069
|
+
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
21070
|
+
if (lastStatus && PROGRESS_DONE_STATUSES.has(String(lastStatus.proposedValue))) return 100;
|
|
21071
|
+
const lastProgress = findLast(updates, (u) => u.field === "progress");
|
|
21072
|
+
if (lastProgress) return lastProgress.proposedValue;
|
|
21073
|
+
return c.marvinProgress;
|
|
21074
|
+
});
|
|
21075
|
+
const childDoneCount = children.filter((c, i) => {
|
|
21076
|
+
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
21077
|
+
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
21078
|
+
const effectiveStatus = lastStatus ? String(lastStatus.proposedValue) : c.marvinStatus;
|
|
21079
|
+
return DONE_STATUSES6.has(effectiveStatus);
|
|
21080
|
+
}).length;
|
|
21081
|
+
const childRollupProgress = children.length > 0 ? Math.round(childProgressValues.reduce((s, p) => s + p, 0) / childProgressValues.length) : null;
|
|
21082
|
+
return {
|
|
21083
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
21084
|
+
commentSummary,
|
|
21085
|
+
commentAnalysisProgress,
|
|
21086
|
+
signals,
|
|
21087
|
+
childCount: children.length,
|
|
21088
|
+
childDoneCount,
|
|
21089
|
+
childRollupProgress,
|
|
21090
|
+
linkedIssueCount: linkedIssues.length
|
|
21091
|
+
};
|
|
21092
|
+
}
|
|
21017
21093
|
function formatArtifactReport(report) {
|
|
21018
21094
|
const parts = [];
|
|
21019
21095
|
parts.push(`# Artifact Assessment \u2014 ${report.artifactId}`);
|
|
@@ -21042,6 +21118,9 @@ function formatArtifactReport(report) {
|
|
|
21042
21118
|
if (report.commentSummary) {
|
|
21043
21119
|
parts.push(`## Comments`);
|
|
21044
21120
|
parts.push(report.commentSummary);
|
|
21121
|
+
if (report.commentAnalysisProgress !== null) {
|
|
21122
|
+
parts.push(` \u{1F4CA} Comment-derived progress estimate: ${report.commentAnalysisProgress}%`);
|
|
21123
|
+
}
|
|
21045
21124
|
parts.push("");
|
|
21046
21125
|
}
|
|
21047
21126
|
if (report.children.length > 0) {
|