mrvn-cli 0.4.7 → 0.4.8
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/README.md +7 -1
- package/dist/index.js +88 -23
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +87 -22
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +88 -23
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/marvin.js
CHANGED
|
@@ -14573,13 +14573,14 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
14573
14573
|
const workItemDocs = allDocs.filter(
|
|
14574
14574
|
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.tags?.includes(sprintTag)
|
|
14575
14575
|
);
|
|
14576
|
+
const primaryDocs = workItemDocs.filter((d) => d.frontmatter.type !== "contribution");
|
|
14576
14577
|
const byStatus = {};
|
|
14577
14578
|
const byType = {};
|
|
14578
14579
|
let doneCount = 0;
|
|
14579
14580
|
let inProgressCount = 0;
|
|
14580
14581
|
let openCount = 0;
|
|
14581
14582
|
let blockedCount = 0;
|
|
14582
|
-
for (const doc of
|
|
14583
|
+
for (const doc of primaryDocs) {
|
|
14583
14584
|
const s = doc.frontmatter.status;
|
|
14584
14585
|
byStatus[s] = (byStatus[s] ?? 0) + 1;
|
|
14585
14586
|
byType[doc.frontmatter.type] = (byType[doc.frontmatter.type] ?? 0) + 1;
|
|
@@ -14588,21 +14589,59 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
14588
14589
|
else if (s === "blocked") blockedCount++;
|
|
14589
14590
|
else openCount++;
|
|
14590
14591
|
}
|
|
14592
|
+
const allItemsById = /* @__PURE__ */ new Map();
|
|
14593
|
+
const childrenByParent = /* @__PURE__ */ new Map();
|
|
14594
|
+
const sprintItemIds = new Set(workItemDocs.map((d) => d.frontmatter.id));
|
|
14595
|
+
for (const doc of workItemDocs) {
|
|
14596
|
+
const about = doc.frontmatter.aboutArtifact;
|
|
14597
|
+
const item = {
|
|
14598
|
+
id: doc.frontmatter.id,
|
|
14599
|
+
title: doc.frontmatter.title,
|
|
14600
|
+
type: doc.frontmatter.type,
|
|
14601
|
+
status: doc.frontmatter.status,
|
|
14602
|
+
aboutArtifact: about
|
|
14603
|
+
};
|
|
14604
|
+
allItemsById.set(item.id, item);
|
|
14605
|
+
if (about && sprintItemIds.has(about)) {
|
|
14606
|
+
if (!childrenByParent.has(about)) childrenByParent.set(about, []);
|
|
14607
|
+
childrenByParent.get(about).push(item);
|
|
14608
|
+
}
|
|
14609
|
+
}
|
|
14610
|
+
const itemsWithChildren = /* @__PURE__ */ new Set();
|
|
14611
|
+
for (const [parentId, children] of childrenByParent) {
|
|
14612
|
+
const parent = allItemsById.get(parentId);
|
|
14613
|
+
if (parent) {
|
|
14614
|
+
parent.children = children;
|
|
14615
|
+
for (const child of children) itemsWithChildren.add(child.id);
|
|
14616
|
+
}
|
|
14617
|
+
}
|
|
14618
|
+
for (const item of allItemsById.values()) {
|
|
14619
|
+
if (item.children) {
|
|
14620
|
+
for (const child of item.children) {
|
|
14621
|
+
const grandchildren = childrenByParent.get(child.id);
|
|
14622
|
+
if (grandchildren) {
|
|
14623
|
+
child.children = grandchildren;
|
|
14624
|
+
for (const gc of grandchildren) itemsWithChildren.add(gc.id);
|
|
14625
|
+
}
|
|
14626
|
+
}
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
const items = [];
|
|
14630
|
+
for (const doc of workItemDocs) {
|
|
14631
|
+
if (!itemsWithChildren.has(doc.frontmatter.id)) {
|
|
14632
|
+
items.push(allItemsById.get(doc.frontmatter.id));
|
|
14633
|
+
}
|
|
14634
|
+
}
|
|
14591
14635
|
const workItems = {
|
|
14592
|
-
total:
|
|
14636
|
+
total: primaryDocs.length,
|
|
14593
14637
|
done: doneCount,
|
|
14594
14638
|
inProgress: inProgressCount,
|
|
14595
14639
|
open: openCount,
|
|
14596
14640
|
blocked: blockedCount,
|
|
14597
|
-
completionPct:
|
|
14641
|
+
completionPct: primaryDocs.length > 0 ? Math.round(doneCount / primaryDocs.length * 100) : 0,
|
|
14598
14642
|
byStatus,
|
|
14599
14643
|
byType,
|
|
14600
|
-
items
|
|
14601
|
-
id: d.frontmatter.id,
|
|
14602
|
-
title: d.frontmatter.title,
|
|
14603
|
-
type: d.frontmatter.type,
|
|
14604
|
-
status: d.frontmatter.status
|
|
14605
|
-
}))
|
|
14644
|
+
items
|
|
14606
14645
|
};
|
|
14607
14646
|
const meetings = [];
|
|
14608
14647
|
if (startDate && endDate) {
|
|
@@ -14684,7 +14723,7 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
14684
14723
|
const prev = completedSprints[0];
|
|
14685
14724
|
const prevTag = `sprint:${prev.frontmatter.id}`;
|
|
14686
14725
|
const prevWorkItems = allDocs.filter(
|
|
14687
|
-
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.tags?.includes(prevTag)
|
|
14726
|
+
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.type !== "contribution" && d.frontmatter.tags?.includes(prevTag)
|
|
14688
14727
|
);
|
|
14689
14728
|
const prevDone = prevWorkItems.filter((d) => DONE_STATUSES.has(d.frontmatter.status)).length;
|
|
14690
14729
|
const prevRate = prevWorkItems.length > 0 ? Math.round(prevDone / prevWorkItems.length * 100) : 0;
|
|
@@ -15577,18 +15616,18 @@ function createContributionTools(store) {
|
|
|
15577
15616
|
content: external_exports.string().describe("Contribution content \u2014 the input from the persona"),
|
|
15578
15617
|
persona: external_exports.string().describe("Persona making the contribution (e.g. 'tech-lead')"),
|
|
15579
15618
|
contributionType: external_exports.string().describe("Type of contribution (e.g. 'action-result', 'risk-finding')"),
|
|
15580
|
-
aboutArtifact: external_exports.string().
|
|
15581
|
-
status: external_exports.string().optional().describe("Status (default: '
|
|
15619
|
+
aboutArtifact: external_exports.string().describe("Artifact ID this contribution relates to (e.g. 'A-001', 'T-003')"),
|
|
15620
|
+
status: external_exports.string().optional().describe("Status (default: 'done')"),
|
|
15582
15621
|
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization")
|
|
15583
15622
|
},
|
|
15584
15623
|
async (args) => {
|
|
15585
15624
|
const frontmatter = {
|
|
15586
15625
|
title: args.title,
|
|
15587
|
-
status: args.status ?? "
|
|
15626
|
+
status: args.status ?? "done",
|
|
15588
15627
|
persona: args.persona,
|
|
15589
15628
|
contributionType: args.contributionType
|
|
15590
15629
|
};
|
|
15591
|
-
|
|
15630
|
+
frontmatter.aboutArtifact = args.aboutArtifact;
|
|
15592
15631
|
if (args.tags) frontmatter.tags = args.tags;
|
|
15593
15632
|
const doc = store.create("contribution", frontmatter, args.content);
|
|
15594
15633
|
return {
|
|
@@ -16072,6 +16111,7 @@ function createTaskTools(store) {
|
|
|
16072
16111
|
title: external_exports.string().describe("Task title"),
|
|
16073
16112
|
content: external_exports.string().describe("Task description and implementation details"),
|
|
16074
16113
|
linkedEpic: linkedEpicArray.describe("Epic ID(s) to link this task to (e.g. ['E-001'] or ['E-001', 'E-002'])"),
|
|
16114
|
+
aboutArtifact: external_exports.string().optional().describe("Parent artifact this task derives from (e.g. 'A-001')"),
|
|
16075
16115
|
status: external_exports.enum(["backlog", "ready", "in-progress", "review", "done"]).optional().describe("Task status (default: 'backlog')"),
|
|
16076
16116
|
acceptanceCriteria: external_exports.string().optional().describe("Acceptance criteria for the task"),
|
|
16077
16117
|
technicalNotes: external_exports.string().optional().describe("Technical implementation notes"),
|
|
@@ -16097,6 +16137,7 @@ function createTaskTools(store) {
|
|
|
16097
16137
|
linkedEpic: linkedEpics,
|
|
16098
16138
|
tags: [...generateEpicTags(linkedEpics), ...args.tags ?? []]
|
|
16099
16139
|
};
|
|
16140
|
+
if (args.aboutArtifact) frontmatter.aboutArtifact = args.aboutArtifact;
|
|
16100
16141
|
if (args.acceptanceCriteria) frontmatter.acceptanceCriteria = args.acceptanceCriteria;
|
|
16101
16142
|
if (args.technicalNotes) frontmatter.technicalNotes = args.technicalNotes;
|
|
16102
16143
|
if (args.estimatedPoints !== void 0) frontmatter.estimatedPoints = args.estimatedPoints;
|
|
@@ -16120,6 +16161,7 @@ function createTaskTools(store) {
|
|
|
16120
16161
|
{
|
|
16121
16162
|
id: external_exports.string().describe("Task ID to update"),
|
|
16122
16163
|
title: external_exports.string().optional().describe("New title"),
|
|
16164
|
+
aboutArtifact: external_exports.string().optional().describe("Parent artifact this task derives from (e.g. 'A-001')"),
|
|
16123
16165
|
status: external_exports.enum(["backlog", "ready", "in-progress", "review", "done"]).optional().describe("New status"),
|
|
16124
16166
|
content: external_exports.string().optional().describe("New content"),
|
|
16125
16167
|
linkedEpic: linkedEpicArray.optional().describe("New linked epic ID(s)"),
|
|
@@ -19419,6 +19461,17 @@ tr:hover td {
|
|
|
19419
19461
|
background: var(--bg-hover);
|
|
19420
19462
|
}
|
|
19421
19463
|
|
|
19464
|
+
/* Hierarchical work-item sub-rows */
|
|
19465
|
+
.child-row td {
|
|
19466
|
+
font-size: 0.8125rem;
|
|
19467
|
+
border-bottom-style: dashed;
|
|
19468
|
+
}
|
|
19469
|
+
.contribution-row td {
|
|
19470
|
+
font-size: 0.8125rem;
|
|
19471
|
+
color: var(--text-dim);
|
|
19472
|
+
border-bottom-style: dashed;
|
|
19473
|
+
}
|
|
19474
|
+
|
|
19422
19475
|
/* GAR */
|
|
19423
19476
|
.gar-overall {
|
|
19424
19477
|
text-align: center;
|
|
@@ -21106,7 +21159,25 @@ function sprintSummaryPage(data, cached2) {
|
|
|
21106
21159
|
</div>`,
|
|
21107
21160
|
{ titleTag: "h3" }
|
|
21108
21161
|
) : "";
|
|
21109
|
-
|
|
21162
|
+
function renderItemRows(items, depth = 0) {
|
|
21163
|
+
return items.flatMap((w) => {
|
|
21164
|
+
const isChild = depth > 0;
|
|
21165
|
+
const isContribution = w.type === "contribution";
|
|
21166
|
+
const rowClass = isContribution ? ' class="contribution-row"' : isChild ? ' class="child-row"' : "";
|
|
21167
|
+
const indent = depth > 0 ? ` style="padding-left: ${0.75 + depth * 1}rem"` : "";
|
|
21168
|
+
const row = `
|
|
21169
|
+
<tr${rowClass}>
|
|
21170
|
+
<td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
21171
|
+
<td>${escapeHtml(w.title)}</td>
|
|
21172
|
+
<td>${escapeHtml(typeLabel(w.type))}</td>
|
|
21173
|
+
<td>${statusBadge(w.status)}</td>
|
|
21174
|
+
</tr>`;
|
|
21175
|
+
const childRows = w.children ? renderItemRows(w.children, depth + 1) : [];
|
|
21176
|
+
return [row, ...childRows];
|
|
21177
|
+
});
|
|
21178
|
+
}
|
|
21179
|
+
const workItemRows = renderItemRows(data.workItems.items);
|
|
21180
|
+
const workItemsSection = workItemRows.length > 0 ? collapsibleSection(
|
|
21110
21181
|
"ss-work-items",
|
|
21111
21182
|
"Work Items",
|
|
21112
21183
|
`<div class="table-wrap">
|
|
@@ -21115,13 +21186,7 @@ function sprintSummaryPage(data, cached2) {
|
|
|
21115
21186
|
<tr><th>ID</th><th>Title</th><th>Type</th><th>Status</th></tr>
|
|
21116
21187
|
</thead>
|
|
21117
21188
|
<tbody>
|
|
21118
|
-
${
|
|
21119
|
-
<tr>
|
|
21120
|
-
<td><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
21121
|
-
<td>${escapeHtml(w.title)}</td>
|
|
21122
|
-
<td>${escapeHtml(typeLabel(w.type))}</td>
|
|
21123
|
-
<td>${statusBadge(w.status)}</td>
|
|
21124
|
-
</tr>`).join("")}
|
|
21189
|
+
${workItemRows.join("")}
|
|
21125
21190
|
</tbody>
|
|
21126
21191
|
</table>
|
|
21127
21192
|
</div>`,
|
|
@@ -26159,7 +26224,7 @@ function createProgram() {
|
|
|
26159
26224
|
const program2 = new Command();
|
|
26160
26225
|
program2.name("marvin").description(
|
|
26161
26226
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
26162
|
-
).version("0.4.
|
|
26227
|
+
).version("0.4.8");
|
|
26163
26228
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
26164
26229
|
await initCommand();
|
|
26165
26230
|
});
|