mrvn-cli 0.5.23 → 0.5.25
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 +7496 -7266
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +233 -5
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +234 -6
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin.js
CHANGED
|
@@ -19522,8 +19522,30 @@ function inline(text) {
|
|
|
19522
19522
|
s = s.replace(/__([^_]+)__/g, "<strong>$1</strong>");
|
|
19523
19523
|
s = s.replace(/\*([^*]+)\*/g, "<em>$1</em>");
|
|
19524
19524
|
s = s.replace(/_([^_]+)_/g, "<em>$1</em>");
|
|
19525
|
+
s = linkArtifactIds(s);
|
|
19525
19526
|
return s;
|
|
19526
19527
|
}
|
|
19528
|
+
var ID_PREFIX_TO_TYPE = (() => {
|
|
19529
|
+
const entries = [];
|
|
19530
|
+
for (const [type, prefix] of Object.entries(CORE_ID_PREFIXES)) {
|
|
19531
|
+
entries.push([prefix, type]);
|
|
19532
|
+
}
|
|
19533
|
+
for (const reg of COMMON_REGISTRATIONS) {
|
|
19534
|
+
if (!entries.some(([p]) => p === reg.idPrefix)) {
|
|
19535
|
+
entries.push([reg.idPrefix, reg.type]);
|
|
19536
|
+
}
|
|
19537
|
+
}
|
|
19538
|
+
entries.sort((a, b) => b[0].length - a[0].length);
|
|
19539
|
+
return new Map(entries);
|
|
19540
|
+
})();
|
|
19541
|
+
function linkArtifactIds(html) {
|
|
19542
|
+
return html.replace(/\b([A-Z]{1,3})-(\d{3,})\b/g, (match, prefix, num) => {
|
|
19543
|
+
const type = ID_PREFIX_TO_TYPE.get(prefix);
|
|
19544
|
+
if (!type) return match;
|
|
19545
|
+
const id = `${prefix}-${num}`;
|
|
19546
|
+
return `<a href="/docs/${type}/${id}" class="artifact-link">${match}</a>`;
|
|
19547
|
+
});
|
|
19548
|
+
}
|
|
19527
19549
|
function layout(opts, body) {
|
|
19528
19550
|
const switcherHtml = opts.personaSwitcherHtml ?? "";
|
|
19529
19551
|
let navHtml;
|
|
@@ -20235,6 +20257,75 @@ tr:hover td {
|
|
|
20235
20257
|
margin: 0.75rem 0;
|
|
20236
20258
|
}
|
|
20237
20259
|
|
|
20260
|
+
/* Artifact cross-links */
|
|
20261
|
+
a.artifact-link {
|
|
20262
|
+
color: var(--accent);
|
|
20263
|
+
text-decoration: none;
|
|
20264
|
+
font-weight: 500;
|
|
20265
|
+
border-bottom: 1px dotted var(--accent);
|
|
20266
|
+
}
|
|
20267
|
+
a.artifact-link:hover {
|
|
20268
|
+
border-bottom-style: solid;
|
|
20269
|
+
}
|
|
20270
|
+
|
|
20271
|
+
/* Assessment timeline */
|
|
20272
|
+
.assessment-timeline {
|
|
20273
|
+
margin-top: 1.5rem;
|
|
20274
|
+
}
|
|
20275
|
+
.assessment-timeline h3 {
|
|
20276
|
+
font-size: 1rem;
|
|
20277
|
+
font-weight: 600;
|
|
20278
|
+
margin-bottom: 0.75rem;
|
|
20279
|
+
}
|
|
20280
|
+
.assessment-entry {
|
|
20281
|
+
background: var(--bg-card);
|
|
20282
|
+
border: 1px solid var(--border);
|
|
20283
|
+
border-radius: var(--radius);
|
|
20284
|
+
padding: 0.75rem 1rem;
|
|
20285
|
+
margin-bottom: 0.75rem;
|
|
20286
|
+
}
|
|
20287
|
+
.assessment-entry.assessment-latest {
|
|
20288
|
+
border-left: 3px solid var(--accent);
|
|
20289
|
+
}
|
|
20290
|
+
.assessment-header {
|
|
20291
|
+
display: flex;
|
|
20292
|
+
align-items: center;
|
|
20293
|
+
gap: 0.5rem;
|
|
20294
|
+
margin-bottom: 0.5rem;
|
|
20295
|
+
}
|
|
20296
|
+
.assessment-date {
|
|
20297
|
+
font-size: 0.8rem;
|
|
20298
|
+
color: var(--text-dim);
|
|
20299
|
+
font-family: var(--mono);
|
|
20300
|
+
}
|
|
20301
|
+
.assessment-comment {
|
|
20302
|
+
font-size: 0.875rem;
|
|
20303
|
+
line-height: 1.6;
|
|
20304
|
+
margin-bottom: 0.5rem;
|
|
20305
|
+
}
|
|
20306
|
+
.assessment-stat {
|
|
20307
|
+
font-size: 0.8rem;
|
|
20308
|
+
color: var(--text-dim);
|
|
20309
|
+
margin-bottom: 0.25rem;
|
|
20310
|
+
}
|
|
20311
|
+
.assessment-stat strong {
|
|
20312
|
+
color: var(--text);
|
|
20313
|
+
}
|
|
20314
|
+
.assessment-signals {
|
|
20315
|
+
list-style: none;
|
|
20316
|
+
padding: 0;
|
|
20317
|
+
margin: 0.5rem 0 0;
|
|
20318
|
+
}
|
|
20319
|
+
.assessment-signals li {
|
|
20320
|
+
font-size: 0.8rem;
|
|
20321
|
+
padding: 0.15rem 0;
|
|
20322
|
+
}
|
|
20323
|
+
.progress-bar-inline {
|
|
20324
|
+
font-family: var(--mono);
|
|
20325
|
+
font-size: 0.75rem;
|
|
20326
|
+
letter-spacing: -0.5px;
|
|
20327
|
+
}
|
|
20328
|
+
|
|
20238
20329
|
/* Filters */
|
|
20239
20330
|
.filters {
|
|
20240
20331
|
display: flex;
|
|
@@ -21399,23 +21490,33 @@ function documentsPage(data) {
|
|
|
21399
21490
|
function documentDetailPage(doc) {
|
|
21400
21491
|
const fm = doc.frontmatter;
|
|
21401
21492
|
const label = typeLabel(fm.type);
|
|
21402
|
-
const skipKeys = /* @__PURE__ */ new Set(["title", "type"]);
|
|
21493
|
+
const skipKeys = /* @__PURE__ */ new Set(["title", "type", "assessmentHistory", "assessmentSummary"]);
|
|
21403
21494
|
const entries = Object.entries(fm).filter(
|
|
21404
|
-
([key]) => !skipKeys.has(key) &&
|
|
21495
|
+
([key, value]) => !skipKeys.has(key) && value != null && typeof value !== "object"
|
|
21496
|
+
);
|
|
21497
|
+
const arrayEntries = Object.entries(fm).filter(
|
|
21498
|
+
([key, value]) => !skipKeys.has(key) && Array.isArray(value) && value.every((v) => typeof v === "string")
|
|
21405
21499
|
);
|
|
21406
|
-
const
|
|
21500
|
+
const allEntries = [
|
|
21501
|
+
...entries.filter(([, v]) => !Array.isArray(v)),
|
|
21502
|
+
...arrayEntries
|
|
21503
|
+
];
|
|
21504
|
+
const dtDd = allEntries.map(([key, value]) => {
|
|
21407
21505
|
let rendered;
|
|
21408
21506
|
if (key === "status") {
|
|
21409
21507
|
rendered = statusBadge(value);
|
|
21410
21508
|
} else if (key === "tags" && Array.isArray(value)) {
|
|
21411
21509
|
rendered = value.map((t) => `<span class="badge badge-default">${escapeHtml(t)}</span>`).join(" ");
|
|
21412
|
-
} else if (key === "created" || key === "updated") {
|
|
21510
|
+
} else if (key === "created" || key === "updated" || key === "lastAssessedAt" || key === "lastJiraSyncAt") {
|
|
21413
21511
|
rendered = formatDate(value);
|
|
21414
21512
|
} else {
|
|
21415
|
-
rendered = escapeHtml(String(value));
|
|
21513
|
+
rendered = linkArtifactIds(escapeHtml(String(value)));
|
|
21416
21514
|
}
|
|
21417
21515
|
return `<dt>${escapeHtml(key)}</dt><dd>${rendered}</dd>`;
|
|
21418
21516
|
}).join("\n ");
|
|
21517
|
+
const rawHistory = Array.isArray(fm.assessmentHistory) ? fm.assessmentHistory : fm.assessmentSummary && typeof fm.assessmentSummary === "object" ? [fm.assessmentSummary] : [];
|
|
21518
|
+
const assessmentHistory = rawHistory.filter(isValidAssessmentEntry).sort((a, b) => (b.generatedAt ?? "").localeCompare(a.generatedAt ?? ""));
|
|
21519
|
+
const timelineHtml = assessmentHistory.length > 0 ? renderAssessmentTimeline(assessmentHistory) : "";
|
|
21419
21520
|
return `
|
|
21420
21521
|
<div class="breadcrumb">
|
|
21421
21522
|
<a href="/">Overview</a><span class="sep">/</span>
|
|
@@ -21435,8 +21536,73 @@ function documentDetailPage(doc) {
|
|
|
21435
21536
|
</div>
|
|
21436
21537
|
|
|
21437
21538
|
${doc.content.trim() ? `<div class="detail-content">${renderMarkdown(doc.content)}</div>` : ""}
|
|
21539
|
+
|
|
21540
|
+
${timelineHtml}
|
|
21438
21541
|
`;
|
|
21439
21542
|
}
|
|
21543
|
+
function isValidAssessmentEntry(value) {
|
|
21544
|
+
if (typeof value !== "object" || value === null) return false;
|
|
21545
|
+
const obj = value;
|
|
21546
|
+
if (typeof obj.generatedAt !== "string") return false;
|
|
21547
|
+
if (obj.signals !== void 0 && !Array.isArray(obj.signals)) return false;
|
|
21548
|
+
return true;
|
|
21549
|
+
}
|
|
21550
|
+
function normalizeEntry(entry) {
|
|
21551
|
+
return {
|
|
21552
|
+
generatedAt: entry.generatedAt ?? "",
|
|
21553
|
+
commentSummary: typeof entry.commentSummary === "string" ? entry.commentSummary : null,
|
|
21554
|
+
commentAnalysisProgress: typeof entry.commentAnalysisProgress === "number" ? entry.commentAnalysisProgress : null,
|
|
21555
|
+
signals: Array.isArray(entry.signals) ? entry.signals.filter((s) => typeof s === "string") : [],
|
|
21556
|
+
childCount: typeof entry.childCount === "number" ? entry.childCount : 0,
|
|
21557
|
+
childDoneCount: typeof entry.childDoneCount === "number" ? entry.childDoneCount : 0,
|
|
21558
|
+
childRollupProgress: typeof entry.childRollupProgress === "number" ? entry.childRollupProgress : null,
|
|
21559
|
+
linkedIssueCount: typeof entry.linkedIssueCount === "number" ? entry.linkedIssueCount : 0
|
|
21560
|
+
};
|
|
21561
|
+
}
|
|
21562
|
+
function renderAssessmentTimeline(history) {
|
|
21563
|
+
const entries = history.map((raw, i) => {
|
|
21564
|
+
const entry = normalizeEntry(raw);
|
|
21565
|
+
const date5 = entry.generatedAt ? formatDate(entry.generatedAt) : "Unknown date";
|
|
21566
|
+
const time3 = entry.generatedAt?.slice(11, 16) ?? "";
|
|
21567
|
+
const isLatest = i === 0;
|
|
21568
|
+
const parts = [];
|
|
21569
|
+
if (entry.commentSummary) {
|
|
21570
|
+
parts.push(`<div class="assessment-comment">${linkArtifactIds(escapeHtml(entry.commentSummary))}</div>`);
|
|
21571
|
+
}
|
|
21572
|
+
if (entry.commentAnalysisProgress !== null) {
|
|
21573
|
+
parts.push(`<div class="assessment-stat">\u{1F4CA} Comment-derived progress: <strong>${entry.commentAnalysisProgress}%</strong></div>`);
|
|
21574
|
+
}
|
|
21575
|
+
if (entry.childCount > 0) {
|
|
21576
|
+
const bar = progressBarHtml(entry.childRollupProgress ?? 0);
|
|
21577
|
+
parts.push(`<div class="assessment-stat">\u{1F476} Children: ${entry.childDoneCount}/${entry.childCount} done ${bar} ${entry.childRollupProgress ?? 0}%</div>`);
|
|
21578
|
+
}
|
|
21579
|
+
if (entry.linkedIssueCount > 0) {
|
|
21580
|
+
parts.push(`<div class="assessment-stat">\u{1F517} Linked issues: ${entry.linkedIssueCount}</div>`);
|
|
21581
|
+
}
|
|
21582
|
+
if (entry.signals.length > 0) {
|
|
21583
|
+
const signalItems = entry.signals.map((s) => `<li>${linkArtifactIds(escapeHtml(s))}</li>`).join("");
|
|
21584
|
+
parts.push(`<ul class="assessment-signals">${signalItems}</ul>`);
|
|
21585
|
+
}
|
|
21586
|
+
return `
|
|
21587
|
+
<div class="assessment-entry${isLatest ? " assessment-latest" : ""}">
|
|
21588
|
+
<div class="assessment-header">
|
|
21589
|
+
<span class="assessment-date">${escapeHtml(date5)} ${escapeHtml(time3)}</span>
|
|
21590
|
+
${isLatest ? '<span class="badge badge-default">Latest</span>' : ""}
|
|
21591
|
+
</div>
|
|
21592
|
+
${parts.join("\n")}
|
|
21593
|
+
</div>`;
|
|
21594
|
+
});
|
|
21595
|
+
return `
|
|
21596
|
+
<div class="assessment-timeline">
|
|
21597
|
+
<h3>Assessment History</h3>
|
|
21598
|
+
${entries.join("\n")}
|
|
21599
|
+
</div>`;
|
|
21600
|
+
}
|
|
21601
|
+
function progressBarHtml(pct) {
|
|
21602
|
+
const filled = Math.round(Math.max(0, Math.min(100, pct)) / 10);
|
|
21603
|
+
const empty = 10 - filled;
|
|
21604
|
+
return `<span class="progress-bar-inline">${"\u2588".repeat(filled)}${"\u2591".repeat(empty)}</span>`;
|
|
21605
|
+
}
|
|
21440
21606
|
|
|
21441
21607
|
// src/web/persona-views.ts
|
|
21442
21608
|
var VIEWS = /* @__PURE__ */ new Map();
|
|
@@ -27051,6 +27217,41 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
27051
27217
|
}
|
|
27052
27218
|
}
|
|
27053
27219
|
}
|
|
27220
|
+
if (options.applyUpdates) {
|
|
27221
|
+
const newEntry = buildAssessmentSummary(
|
|
27222
|
+
commentSummary,
|
|
27223
|
+
commentAnalysisProgress,
|
|
27224
|
+
signals,
|
|
27225
|
+
children,
|
|
27226
|
+
linkedIssues
|
|
27227
|
+
);
|
|
27228
|
+
const existingHistory = Array.isArray(fm.assessmentHistory) ? fm.assessmentHistory : [];
|
|
27229
|
+
const legacySummary = fm.assessmentSummary;
|
|
27230
|
+
const allEntries = [newEntry, ...existingHistory];
|
|
27231
|
+
if (legacySummary?.generatedAt) {
|
|
27232
|
+
allEntries.push(legacySummary);
|
|
27233
|
+
}
|
|
27234
|
+
const MAX_HISTORY = 100;
|
|
27235
|
+
const seen = /* @__PURE__ */ new Set();
|
|
27236
|
+
const assessmentHistory = allEntries.filter((entry) => {
|
|
27237
|
+
if (!entry.generatedAt) return false;
|
|
27238
|
+
if (seen.has(entry.generatedAt)) return false;
|
|
27239
|
+
seen.add(entry.generatedAt);
|
|
27240
|
+
return true;
|
|
27241
|
+
}).sort((a, b) => (b.generatedAt ?? "").localeCompare(a.generatedAt ?? "")).slice(0, MAX_HISTORY);
|
|
27242
|
+
try {
|
|
27243
|
+
const payload = {
|
|
27244
|
+
assessmentHistory,
|
|
27245
|
+
lastAssessedAt: newEntry.generatedAt
|
|
27246
|
+
};
|
|
27247
|
+
if (fm.assessmentSummary !== void 0) {
|
|
27248
|
+
payload.assessmentSummary = void 0;
|
|
27249
|
+
}
|
|
27250
|
+
store.update(fm.id, payload);
|
|
27251
|
+
} catch (err) {
|
|
27252
|
+
errors.push(`Failed to persist assessment history: ${err instanceof Error ? err.message : String(err)}`);
|
|
27253
|
+
}
|
|
27254
|
+
}
|
|
27054
27255
|
return {
|
|
27055
27256
|
artifactId: fm.id,
|
|
27056
27257
|
title: fm.title,
|
|
@@ -27257,6 +27458,33 @@ function emptyArtifactReport(artifactId, errors) {
|
|
|
27257
27458
|
errors
|
|
27258
27459
|
};
|
|
27259
27460
|
}
|
|
27461
|
+
function buildAssessmentSummary(commentSummary, commentAnalysisProgress, signals, children, linkedIssues) {
|
|
27462
|
+
const childProgressValues = children.map((c) => {
|
|
27463
|
+
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
27464
|
+
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
27465
|
+
if (lastStatus && PROGRESS_DONE_STATUSES.has(String(lastStatus.proposedValue))) return 100;
|
|
27466
|
+
const lastProgress = findLast(updates, (u) => u.field === "progress");
|
|
27467
|
+
if (lastProgress) return lastProgress.proposedValue;
|
|
27468
|
+
return c.marvinProgress;
|
|
27469
|
+
});
|
|
27470
|
+
const childDoneCount = children.filter((c, i) => {
|
|
27471
|
+
const updates = c.appliedUpdates.length > 0 ? c.appliedUpdates : c.proposedUpdates;
|
|
27472
|
+
const lastStatus = findLast(updates, (u) => u.field === "status");
|
|
27473
|
+
const effectiveStatus = lastStatus ? String(lastStatus.proposedValue) : c.marvinStatus;
|
|
27474
|
+
return DONE_STATUSES15.has(effectiveStatus);
|
|
27475
|
+
}).length;
|
|
27476
|
+
const childRollupProgress = children.length > 0 ? Math.round(childProgressValues.reduce((s, p) => s + p, 0) / childProgressValues.length) : null;
|
|
27477
|
+
return {
|
|
27478
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27479
|
+
commentSummary,
|
|
27480
|
+
commentAnalysisProgress,
|
|
27481
|
+
signals,
|
|
27482
|
+
childCount: children.length,
|
|
27483
|
+
childDoneCount,
|
|
27484
|
+
childRollupProgress,
|
|
27485
|
+
linkedIssueCount: linkedIssues.length
|
|
27486
|
+
};
|
|
27487
|
+
}
|
|
27260
27488
|
function formatArtifactReport(report) {
|
|
27261
27489
|
const parts = [];
|
|
27262
27490
|
parts.push(`# Artifact Assessment \u2014 ${report.artifactId}`);
|
|
@@ -33617,7 +33845,7 @@ function createProgram() {
|
|
|
33617
33845
|
const program2 = new Command();
|
|
33618
33846
|
program2.name("marvin").description(
|
|
33619
33847
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
33620
|
-
).version("0.5.
|
|
33848
|
+
).version("0.5.25");
|
|
33621
33849
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
33622
33850
|
await initCommand();
|
|
33623
33851
|
});
|