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 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 rowClass = isContribution ? ' class="contribution-row"' : isChild ? ' class="child-row"' : "";
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${rowClass}>
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
- `<div class="table-wrap">
18241
- <table>
18307
+ `${streamStyleBlock}
18308
+ <div class="table-wrap">
18309
+ <table id="work-items-table">
18242
18310
  <thead>
18243
- <tr><th>ID</th><th>Title</th><th>Stream</th><th>Type</th><th>Status</th></tr>
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.9");
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
  });