mrvn-cli 0.4.9 → 0.4.10
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 +130 -7
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +129 -6
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +130 -7
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15492,7 +15492,7 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
15492
15492
|
});
|
|
15493
15493
|
const sprintTag = `sprint:${fm.id}`;
|
|
15494
15494
|
const workItemDocs = allDocs.filter(
|
|
15495
|
-
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.tags?.includes(sprintTag)
|
|
15495
|
+
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.type !== "meeting" && d.frontmatter.tags?.includes(sprintTag)
|
|
15496
15496
|
);
|
|
15497
15497
|
const primaryDocs = workItemDocs.filter((d) => d.frontmatter.type !== "contribution");
|
|
15498
15498
|
const byStatus = {};
|
|
@@ -16477,6 +16477,12 @@ a:hover { text-decoration: underline; }
|
|
|
16477
16477
|
.badge-closed, .badge-resolved { background: rgba(52, 211, 153, 0.15); color: var(--green); }
|
|
16478
16478
|
.badge-blocked { background: rgba(248, 113, 113, 0.15); color: var(--red); }
|
|
16479
16479
|
.badge-default { background: rgba(139, 143, 164, 0.1); color: var(--text-dim); }
|
|
16480
|
+
.badge-subtle {
|
|
16481
|
+
background: rgba(139, 143, 164, 0.12);
|
|
16482
|
+
color: var(--text-dim);
|
|
16483
|
+
text-transform: none;
|
|
16484
|
+
font-weight: 500;
|
|
16485
|
+
}
|
|
16480
16486
|
|
|
16481
16487
|
/* Table */
|
|
16482
16488
|
.table-wrap {
|
|
@@ -17293,6 +17299,22 @@ tr:hover td {
|
|
|
17293
17299
|
max-height: 0;
|
|
17294
17300
|
opacity: 0;
|
|
17295
17301
|
}
|
|
17302
|
+
|
|
17303
|
+
/* Sortable table headers */
|
|
17304
|
+
.sortable-th {
|
|
17305
|
+
cursor: pointer;
|
|
17306
|
+
user-select: none;
|
|
17307
|
+
}
|
|
17308
|
+
.sortable-th:hover {
|
|
17309
|
+
text-decoration: underline;
|
|
17310
|
+
color: var(--text);
|
|
17311
|
+
}
|
|
17312
|
+
.sort-arrow {
|
|
17313
|
+
display: inline-block;
|
|
17314
|
+
margin-left: 0.3rem;
|
|
17315
|
+
font-size: 0.65rem;
|
|
17316
|
+
opacity: 0.7;
|
|
17317
|
+
}
|
|
17296
17318
|
`;
|
|
17297
17319
|
}
|
|
17298
17320
|
|
|
@@ -18214,15 +18236,53 @@ function sprintSummaryPage(data, cached2) {
|
|
|
18214
18236
|
</div>`,
|
|
18215
18237
|
{ titleTag: "h3" }
|
|
18216
18238
|
) : "";
|
|
18239
|
+
const STREAM_PALETTE = [
|
|
18240
|
+
"hsla(220, 30%, 22%, 0.45)",
|
|
18241
|
+
"hsla(160, 30%, 20%, 0.45)",
|
|
18242
|
+
"hsla(280, 25%, 22%, 0.45)",
|
|
18243
|
+
"hsla(30, 35%, 22%, 0.45)",
|
|
18244
|
+
"hsla(340, 25%, 22%, 0.45)",
|
|
18245
|
+
"hsla(190, 30%, 20%, 0.45)",
|
|
18246
|
+
"hsla(60, 25%, 20%, 0.45)",
|
|
18247
|
+
"hsla(120, 20%, 20%, 0.45)"
|
|
18248
|
+
];
|
|
18249
|
+
function hashString(s) {
|
|
18250
|
+
let h = 0;
|
|
18251
|
+
for (let i = 0; i < s.length; i++) {
|
|
18252
|
+
h = (h << 5) - h + s.charCodeAt(i) | 0;
|
|
18253
|
+
}
|
|
18254
|
+
return Math.abs(h);
|
|
18255
|
+
}
|
|
18256
|
+
function collectStreams(items) {
|
|
18257
|
+
const streams = /* @__PURE__ */ new Set();
|
|
18258
|
+
for (const w of items) {
|
|
18259
|
+
if (w.workStream) streams.add(w.workStream);
|
|
18260
|
+
if (w.children) {
|
|
18261
|
+
for (const s of collectStreams(w.children)) streams.add(s);
|
|
18262
|
+
}
|
|
18263
|
+
}
|
|
18264
|
+
return streams;
|
|
18265
|
+
}
|
|
18266
|
+
const uniqueStreams = collectStreams(data.workItems.items);
|
|
18267
|
+
const streamColorMap = /* @__PURE__ */ new Map();
|
|
18268
|
+
for (const name of uniqueStreams) {
|
|
18269
|
+
streamColorMap.set(name, STREAM_PALETTE[hashString(name) % STREAM_PALETTE.length]);
|
|
18270
|
+
}
|
|
18271
|
+
const streamStyleRules = [...streamColorMap.entries()].map(([name, color]) => `tr[data-stream="${escapeHtml(name)}"] td { background: ${color}; }`).join("\n");
|
|
18272
|
+
const streamStyleBlock = streamStyleRules ? `<style>${streamStyleRules}</style>` : "";
|
|
18217
18273
|
function renderItemRows(items, depth = 0) {
|
|
18218
18274
|
return items.flatMap((w) => {
|
|
18219
18275
|
const isChild = depth > 0;
|
|
18220
18276
|
const isContribution = w.type === "contribution";
|
|
18221
|
-
const
|
|
18277
|
+
const classes = [];
|
|
18278
|
+
if (isContribution) classes.push("contribution-row");
|
|
18279
|
+
else if (isChild) classes.push("child-row");
|
|
18280
|
+
const dataStream = w.workStream ? ` data-stream="${escapeHtml(w.workStream)}"` : "";
|
|
18281
|
+
const rowAttrs = classes.length > 0 ? ` class="${classes.join(" ")}"` : "";
|
|
18222
18282
|
const indent = depth > 0 ? ` style="padding-left: ${0.75 + depth * 1}rem"` : "";
|
|
18223
18283
|
const streamCell = w.workStream ? `<span class="badge badge-subtle">${escapeHtml(w.workStream)}</span>` : "";
|
|
18224
18284
|
const row = `
|
|
18225
|
-
<tr${
|
|
18285
|
+
<tr${rowAttrs}${dataStream}>
|
|
18226
18286
|
<td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
18227
18287
|
<td>${escapeHtml(w.title)}</td>
|
|
18228
18288
|
<td>${streamCell}</td>
|
|
@@ -18234,13 +18294,21 @@ function sprintSummaryPage(data, cached2) {
|
|
|
18234
18294
|
});
|
|
18235
18295
|
}
|
|
18236
18296
|
const workItemRows = renderItemRows(data.workItems.items);
|
|
18297
|
+
const sortableHeaders = `<tr>
|
|
18298
|
+
<th class="sortable-th" onclick="sortWorkItems(0)">ID<span class="sort-arrow" id="sort-arrow-0"></span></th>
|
|
18299
|
+
<th class="sortable-th" onclick="sortWorkItems(1)">Title<span class="sort-arrow" id="sort-arrow-1"></span></th>
|
|
18300
|
+
<th class="sortable-th" onclick="sortWorkItems(2)">Stream<span class="sort-arrow" id="sort-arrow-2"></span></th>
|
|
18301
|
+
<th class="sortable-th" onclick="sortWorkItems(3)">Type<span class="sort-arrow" id="sort-arrow-3"></span></th>
|
|
18302
|
+
<th class="sortable-th" onclick="sortWorkItems(4)">Status<span class="sort-arrow" id="sort-arrow-4"></span></th>
|
|
18303
|
+
</tr>`;
|
|
18237
18304
|
const workItemsSection = workItemRows.length > 0 ? collapsibleSection(
|
|
18238
18305
|
"ss-work-items",
|
|
18239
18306
|
"Work Items",
|
|
18240
|
-
|
|
18241
|
-
|
|
18307
|
+
`${streamStyleBlock}
|
|
18308
|
+
<div class="table-wrap">
|
|
18309
|
+
<table id="work-items-table">
|
|
18242
18310
|
<thead>
|
|
18243
|
-
|
|
18311
|
+
${sortableHeaders}
|
|
18244
18312
|
</thead>
|
|
18245
18313
|
<tbody>
|
|
18246
18314
|
${workItemRows.join("")}
|
|
@@ -18319,6 +18387,61 @@ function sprintSummaryPage(data, cached2) {
|
|
|
18319
18387
|
</div>
|
|
18320
18388
|
|
|
18321
18389
|
<script>
|
|
18390
|
+
var _sortCol = -1;
|
|
18391
|
+
var _sortAsc = true;
|
|
18392
|
+
|
|
18393
|
+
function sortWorkItems(col) {
|
|
18394
|
+
var table = document.getElementById('work-items-table');
|
|
18395
|
+
if (!table) return;
|
|
18396
|
+
var tbody = table.querySelector('tbody');
|
|
18397
|
+
var allRows = Array.from(tbody.querySelectorAll('tr'));
|
|
18398
|
+
|
|
18399
|
+
// Toggle direction if clicking the same column
|
|
18400
|
+
if (_sortCol === col) {
|
|
18401
|
+
_sortAsc = !_sortAsc;
|
|
18402
|
+
} else {
|
|
18403
|
+
_sortCol = col;
|
|
18404
|
+
_sortAsc = true;
|
|
18405
|
+
}
|
|
18406
|
+
|
|
18407
|
+
// Update sort arrows
|
|
18408
|
+
for (var i = 0; i < 5; i++) {
|
|
18409
|
+
var arrow = document.getElementById('sort-arrow-' + i);
|
|
18410
|
+
if (arrow) arrow.textContent = i === col ? (_sortAsc ? ' \\u25B2' : ' \\u25BC') : '';
|
|
18411
|
+
}
|
|
18412
|
+
|
|
18413
|
+
// Group rows: root rows + their child/contribution rows
|
|
18414
|
+
var groups = [];
|
|
18415
|
+
var current = null;
|
|
18416
|
+
for (var r = 0; r < allRows.length; r++) {
|
|
18417
|
+
var row = allRows[r];
|
|
18418
|
+
var isChild = row.classList.contains('child-row') || row.classList.contains('contribution-row');
|
|
18419
|
+
if (!isChild) {
|
|
18420
|
+
current = { root: row, children: [] };
|
|
18421
|
+
groups.push(current);
|
|
18422
|
+
} else if (current) {
|
|
18423
|
+
current.children.push(row);
|
|
18424
|
+
}
|
|
18425
|
+
}
|
|
18426
|
+
|
|
18427
|
+
// Sort groups by root row text content of target column
|
|
18428
|
+
groups.sort(function(a, b) {
|
|
18429
|
+
var aText = (a.root.children[col] ? a.root.children[col].textContent : '').trim().toLowerCase();
|
|
18430
|
+
var bText = (b.root.children[col] ? b.root.children[col].textContent : '').trim().toLowerCase();
|
|
18431
|
+
if (aText < bText) return _sortAsc ? -1 : 1;
|
|
18432
|
+
if (aText > bText) return _sortAsc ? 1 : -1;
|
|
18433
|
+
return 0;
|
|
18434
|
+
});
|
|
18435
|
+
|
|
18436
|
+
// Re-append rows in sorted order
|
|
18437
|
+
for (var g = 0; g < groups.length; g++) {
|
|
18438
|
+
tbody.appendChild(groups[g].root);
|
|
18439
|
+
for (var c = 0; c < groups[g].children.length; c++) {
|
|
18440
|
+
tbody.appendChild(groups[g].children[c]);
|
|
18441
|
+
}
|
|
18442
|
+
}
|
|
18443
|
+
}
|
|
18444
|
+
|
|
18322
18445
|
async function generateSummary() {
|
|
18323
18446
|
var btn = document.getElementById('generate-btn');
|
|
18324
18447
|
var loading = document.getElementById('summary-loading');
|
|
@@ -26277,7 +26400,7 @@ function createProgram() {
|
|
|
26277
26400
|
const program = new Command();
|
|
26278
26401
|
program.name("marvin").description(
|
|
26279
26402
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
26280
|
-
).version("0.4.
|
|
26403
|
+
).version("0.4.10");
|
|
26281
26404
|
program.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
26282
26405
|
await initCommand();
|
|
26283
26406
|
});
|