mrvn-cli 0.5.24 → 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 +7464 -7278
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +195 -11
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +196 -12
- 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"
|
|
21405
21496
|
);
|
|
21406
|
-
const
|
|
21497
|
+
const arrayEntries = Object.entries(fm).filter(
|
|
21498
|
+
([key, value]) => !skipKeys.has(key) && Array.isArray(value) && value.every((v) => typeof v === "string")
|
|
21499
|
+
);
|
|
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();
|
|
@@ -27052,20 +27218,38 @@ async function _assessArtifactRecursive(store, client, host, options, visited, d
|
|
|
27052
27218
|
}
|
|
27053
27219
|
}
|
|
27054
27220
|
if (options.applyUpdates) {
|
|
27055
|
-
const
|
|
27221
|
+
const newEntry = buildAssessmentSummary(
|
|
27056
27222
|
commentSummary,
|
|
27057
27223
|
commentAnalysisProgress,
|
|
27058
27224
|
signals,
|
|
27059
27225
|
children,
|
|
27060
27226
|
linkedIssues
|
|
27061
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);
|
|
27062
27242
|
try {
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
lastAssessedAt:
|
|
27066
|
-
}
|
|
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);
|
|
27067
27251
|
} catch (err) {
|
|
27068
|
-
errors.push(`Failed to persist assessment
|
|
27252
|
+
errors.push(`Failed to persist assessment history: ${err instanceof Error ? err.message : String(err)}`);
|
|
27069
27253
|
}
|
|
27070
27254
|
}
|
|
27071
27255
|
return {
|
|
@@ -33661,7 +33845,7 @@ function createProgram() {
|
|
|
33661
33845
|
const program2 = new Command();
|
|
33662
33846
|
program2.name("marvin").description(
|
|
33663
33847
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
33664
|
-
).version("0.5.
|
|
33848
|
+
).version("0.5.25");
|
|
33665
33849
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
33666
33850
|
await initCommand();
|
|
33667
33851
|
});
|