mrvn-cli 0.4.7 → 0.4.9
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 +155 -43
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +154 -42
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +155 -43
- 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,61 @@ 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 streamTag = (doc.frontmatter.tags ?? []).find((t) => t.startsWith("stream:"));
|
|
14598
|
+
const item = {
|
|
14599
|
+
id: doc.frontmatter.id,
|
|
14600
|
+
title: doc.frontmatter.title,
|
|
14601
|
+
type: doc.frontmatter.type,
|
|
14602
|
+
status: doc.frontmatter.status,
|
|
14603
|
+
workStream: streamTag ? streamTag.slice(7) : void 0,
|
|
14604
|
+
aboutArtifact: about
|
|
14605
|
+
};
|
|
14606
|
+
allItemsById.set(item.id, item);
|
|
14607
|
+
if (about && sprintItemIds.has(about)) {
|
|
14608
|
+
if (!childrenByParent.has(about)) childrenByParent.set(about, []);
|
|
14609
|
+
childrenByParent.get(about).push(item);
|
|
14610
|
+
}
|
|
14611
|
+
}
|
|
14612
|
+
const itemsWithChildren = /* @__PURE__ */ new Set();
|
|
14613
|
+
for (const [parentId, children] of childrenByParent) {
|
|
14614
|
+
const parent = allItemsById.get(parentId);
|
|
14615
|
+
if (parent) {
|
|
14616
|
+
parent.children = children;
|
|
14617
|
+
for (const child of children) itemsWithChildren.add(child.id);
|
|
14618
|
+
}
|
|
14619
|
+
}
|
|
14620
|
+
for (const item of allItemsById.values()) {
|
|
14621
|
+
if (item.children) {
|
|
14622
|
+
for (const child of item.children) {
|
|
14623
|
+
const grandchildren = childrenByParent.get(child.id);
|
|
14624
|
+
if (grandchildren) {
|
|
14625
|
+
child.children = grandchildren;
|
|
14626
|
+
for (const gc of grandchildren) itemsWithChildren.add(gc.id);
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
}
|
|
14630
|
+
}
|
|
14631
|
+
const items = [];
|
|
14632
|
+
for (const doc of workItemDocs) {
|
|
14633
|
+
if (!itemsWithChildren.has(doc.frontmatter.id)) {
|
|
14634
|
+
items.push(allItemsById.get(doc.frontmatter.id));
|
|
14635
|
+
}
|
|
14636
|
+
}
|
|
14591
14637
|
const workItems = {
|
|
14592
|
-
total:
|
|
14638
|
+
total: primaryDocs.length,
|
|
14593
14639
|
done: doneCount,
|
|
14594
14640
|
inProgress: inProgressCount,
|
|
14595
14641
|
open: openCount,
|
|
14596
14642
|
blocked: blockedCount,
|
|
14597
|
-
completionPct:
|
|
14643
|
+
completionPct: primaryDocs.length > 0 ? Math.round(doneCount / primaryDocs.length * 100) : 0,
|
|
14598
14644
|
byStatus,
|
|
14599
14645
|
byType,
|
|
14600
|
-
items
|
|
14601
|
-
id: d.frontmatter.id,
|
|
14602
|
-
title: d.frontmatter.title,
|
|
14603
|
-
type: d.frontmatter.type,
|
|
14604
|
-
status: d.frontmatter.status
|
|
14605
|
-
}))
|
|
14646
|
+
items
|
|
14606
14647
|
};
|
|
14607
14648
|
const meetings = [];
|
|
14608
14649
|
if (startDate && endDate) {
|
|
@@ -14684,7 +14725,7 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
14684
14725
|
const prev = completedSprints[0];
|
|
14685
14726
|
const prevTag = `sprint:${prev.frontmatter.id}`;
|
|
14686
14727
|
const prevWorkItems = allDocs.filter(
|
|
14687
|
-
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.tags?.includes(prevTag)
|
|
14728
|
+
(d) => d.frontmatter.type !== "sprint" && d.frontmatter.type !== "epic" && d.frontmatter.type !== "contribution" && d.frontmatter.tags?.includes(prevTag)
|
|
14688
14729
|
);
|
|
14689
14730
|
const prevDone = prevWorkItems.filter((d) => DONE_STATUSES.has(d.frontmatter.status)).length;
|
|
14690
14731
|
const prevRate = prevWorkItems.length > 0 ? Math.round(prevDone / prevWorkItems.length * 100) : 0;
|
|
@@ -15577,19 +15618,22 @@ function createContributionTools(store) {
|
|
|
15577
15618
|
content: external_exports.string().describe("Contribution content \u2014 the input from the persona"),
|
|
15578
15619
|
persona: external_exports.string().describe("Persona making the contribution (e.g. 'tech-lead')"),
|
|
15579
15620
|
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: '
|
|
15582
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization")
|
|
15621
|
+
aboutArtifact: external_exports.string().describe("Artifact ID this contribution relates to (e.g. 'A-001', 'T-003')"),
|
|
15622
|
+
status: external_exports.string().optional().describe("Status (default: 'done')"),
|
|
15623
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization"),
|
|
15624
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
15583
15625
|
},
|
|
15584
15626
|
async (args) => {
|
|
15585
15627
|
const frontmatter = {
|
|
15586
15628
|
title: args.title,
|
|
15587
|
-
status: args.status ?? "
|
|
15629
|
+
status: args.status ?? "done",
|
|
15588
15630
|
persona: args.persona,
|
|
15589
15631
|
contributionType: args.contributionType
|
|
15590
15632
|
};
|
|
15591
|
-
|
|
15592
|
-
|
|
15633
|
+
frontmatter.aboutArtifact = args.aboutArtifact;
|
|
15634
|
+
const tags = [...args.tags ?? []];
|
|
15635
|
+
if (args.workStream) tags.push(`stream:${args.workStream}`);
|
|
15636
|
+
if (tags.length > 0) frontmatter.tags = tags;
|
|
15593
15637
|
const doc = store.create("contribution", frontmatter, args.content);
|
|
15594
15638
|
return {
|
|
15595
15639
|
content: [
|
|
@@ -15608,10 +15652,18 @@ function createContributionTools(store) {
|
|
|
15608
15652
|
id: external_exports.string().describe("Contribution ID to update"),
|
|
15609
15653
|
title: external_exports.string().optional().describe("New title"),
|
|
15610
15654
|
status: external_exports.string().optional().describe("New status"),
|
|
15611
|
-
content: external_exports.string().optional().describe("New content")
|
|
15655
|
+
content: external_exports.string().optional().describe("New content"),
|
|
15656
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
15612
15657
|
},
|
|
15613
15658
|
async (args) => {
|
|
15614
|
-
const { id, content, ...updates } = args;
|
|
15659
|
+
const { id, content, workStream, ...updates } = args;
|
|
15660
|
+
if (workStream !== void 0) {
|
|
15661
|
+
const existing = store.get(id);
|
|
15662
|
+
const existingTags = existing?.frontmatter.tags ?? [];
|
|
15663
|
+
const filtered = existingTags.filter((t) => !t.startsWith("stream:"));
|
|
15664
|
+
filtered.push(`stream:${workStream}`);
|
|
15665
|
+
updates.tags = filtered;
|
|
15666
|
+
}
|
|
15615
15667
|
const doc = store.update(id, updates, content);
|
|
15616
15668
|
return {
|
|
15617
15669
|
content: [
|
|
@@ -16072,13 +16124,15 @@ function createTaskTools(store) {
|
|
|
16072
16124
|
title: external_exports.string().describe("Task title"),
|
|
16073
16125
|
content: external_exports.string().describe("Task description and implementation details"),
|
|
16074
16126
|
linkedEpic: linkedEpicArray.describe("Epic ID(s) to link this task to (e.g. ['E-001'] or ['E-001', 'E-002'])"),
|
|
16127
|
+
aboutArtifact: external_exports.string().optional().describe("Parent artifact this task derives from (e.g. 'A-001')"),
|
|
16075
16128
|
status: external_exports.enum(["backlog", "ready", "in-progress", "review", "done"]).optional().describe("Task status (default: 'backlog')"),
|
|
16076
16129
|
acceptanceCriteria: external_exports.string().optional().describe("Acceptance criteria for the task"),
|
|
16077
16130
|
technicalNotes: external_exports.string().optional().describe("Technical implementation notes"),
|
|
16078
16131
|
estimatedPoints: external_exports.number().optional().describe("Story point estimate"),
|
|
16079
16132
|
complexity: external_exports.enum(["trivial", "simple", "moderate", "complex", "very-complex"]).optional().describe("Task complexity"),
|
|
16080
16133
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("Task priority"),
|
|
16081
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Additional tags")
|
|
16134
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Additional tags"),
|
|
16135
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
16082
16136
|
},
|
|
16083
16137
|
async (args) => {
|
|
16084
16138
|
const linkedEpics = normalizeLinkedEpics(args.linkedEpic);
|
|
@@ -16091,12 +16145,15 @@ function createTaskTools(store) {
|
|
|
16091
16145
|
warnings.push(`Warning: ${epicId} is a ${epic.frontmatter.type}, not an epic`);
|
|
16092
16146
|
}
|
|
16093
16147
|
}
|
|
16148
|
+
const baseTags = [...generateEpicTags(linkedEpics), ...args.tags ?? []];
|
|
16149
|
+
if (args.workStream) baseTags.push(`stream:${args.workStream}`);
|
|
16094
16150
|
const frontmatter = {
|
|
16095
16151
|
title: args.title,
|
|
16096
16152
|
status: args.status ?? "backlog",
|
|
16097
16153
|
linkedEpic: linkedEpics,
|
|
16098
|
-
tags:
|
|
16154
|
+
tags: baseTags
|
|
16099
16155
|
};
|
|
16156
|
+
if (args.aboutArtifact) frontmatter.aboutArtifact = args.aboutArtifact;
|
|
16100
16157
|
if (args.acceptanceCriteria) frontmatter.acceptanceCriteria = args.acceptanceCriteria;
|
|
16101
16158
|
if (args.technicalNotes) frontmatter.technicalNotes = args.technicalNotes;
|
|
16102
16159
|
if (args.estimatedPoints !== void 0) frontmatter.estimatedPoints = args.estimatedPoints;
|
|
@@ -16120,6 +16177,7 @@ function createTaskTools(store) {
|
|
|
16120
16177
|
{
|
|
16121
16178
|
id: external_exports.string().describe("Task ID to update"),
|
|
16122
16179
|
title: external_exports.string().optional().describe("New title"),
|
|
16180
|
+
aboutArtifact: external_exports.string().optional().describe("Parent artifact this task derives from (e.g. 'A-001')"),
|
|
16123
16181
|
status: external_exports.enum(["backlog", "ready", "in-progress", "review", "done"]).optional().describe("New status"),
|
|
16124
16182
|
content: external_exports.string().optional().describe("New content"),
|
|
16125
16183
|
linkedEpic: linkedEpicArray.optional().describe("New linked epic ID(s)"),
|
|
@@ -16128,10 +16186,11 @@ function createTaskTools(store) {
|
|
|
16128
16186
|
estimatedPoints: external_exports.number().optional().describe("New story point estimate"),
|
|
16129
16187
|
complexity: external_exports.enum(["trivial", "simple", "moderate", "complex", "very-complex"]).optional().describe("New complexity"),
|
|
16130
16188
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("New priority"),
|
|
16131
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)")
|
|
16189
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)"),
|
|
16190
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
16132
16191
|
},
|
|
16133
16192
|
async (args) => {
|
|
16134
|
-
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, ...updates } = args;
|
|
16193
|
+
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workStream, ...updates } = args;
|
|
16135
16194
|
const warnings = [];
|
|
16136
16195
|
if (rawLinkedEpic !== void 0) {
|
|
16137
16196
|
const linkedEpics = normalizeLinkedEpics(rawLinkedEpic);
|
|
@@ -16152,6 +16211,12 @@ function createTaskTools(store) {
|
|
|
16152
16211
|
} else if (userTags !== void 0) {
|
|
16153
16212
|
updates.tags = userTags;
|
|
16154
16213
|
}
|
|
16214
|
+
if (workStream !== void 0) {
|
|
16215
|
+
const currentTags = updates.tags ?? store.get(id)?.frontmatter.tags ?? [];
|
|
16216
|
+
const filtered = currentTags.filter((t) => !t.startsWith("stream:"));
|
|
16217
|
+
filtered.push(`stream:${workStream}`);
|
|
16218
|
+
updates.tags = filtered;
|
|
16219
|
+
}
|
|
16155
16220
|
const doc = store.update(id, updates, content);
|
|
16156
16221
|
const parts = [`Updated task ${doc.frontmatter.id}: ${doc.frontmatter.title}`];
|
|
16157
16222
|
if (warnings.length > 0) {
|
|
@@ -18138,7 +18203,8 @@ function createActionTools(store) {
|
|
|
18138
18203
|
priority: external_exports.string().optional().describe("Priority (high, medium, low)"),
|
|
18139
18204
|
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization"),
|
|
18140
18205
|
dueDate: external_exports.string().optional().describe("Due date in ISO format (e.g. '2026-03-15')"),
|
|
18141
|
-
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (e.g. ['SP-001']). Adds sprint:SP-xxx tags.")
|
|
18206
|
+
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (e.g. ['SP-001']). Adds sprint:SP-xxx tags."),
|
|
18207
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
18142
18208
|
},
|
|
18143
18209
|
async (args) => {
|
|
18144
18210
|
const tags = [...args.tags ?? []];
|
|
@@ -18148,6 +18214,9 @@ function createActionTools(store) {
|
|
|
18148
18214
|
if (!tags.includes(tag)) tags.push(tag);
|
|
18149
18215
|
}
|
|
18150
18216
|
}
|
|
18217
|
+
if (args.workStream) {
|
|
18218
|
+
tags.push(`stream:${args.workStream}`);
|
|
18219
|
+
}
|
|
18151
18220
|
const doc = store.create(
|
|
18152
18221
|
"action",
|
|
18153
18222
|
{
|
|
@@ -18185,10 +18254,11 @@ function createActionTools(store) {
|
|
|
18185
18254
|
priority: external_exports.string().optional().describe("New priority"),
|
|
18186
18255
|
dueDate: external_exports.string().optional().describe("Due date in ISO format (e.g. '2026-03-15')"),
|
|
18187
18256
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace all tags. When provided with sprints, sprint tags are merged into this array."),
|
|
18188
|
-
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001'].")
|
|
18257
|
+
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001']."),
|
|
18258
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
18189
18259
|
},
|
|
18190
18260
|
async (args) => {
|
|
18191
|
-
const { id, content, sprints, tags, ...updates } = args;
|
|
18261
|
+
const { id, content, sprints, tags, workStream, ...updates } = args;
|
|
18192
18262
|
if (tags !== void 0) {
|
|
18193
18263
|
const merged = [...tags];
|
|
18194
18264
|
if (sprints) {
|
|
@@ -18197,8 +18267,14 @@ function createActionTools(store) {
|
|
|
18197
18267
|
if (!merged.includes(tag)) merged.push(tag);
|
|
18198
18268
|
}
|
|
18199
18269
|
}
|
|
18200
|
-
|
|
18201
|
-
|
|
18270
|
+
if (workStream !== void 0) {
|
|
18271
|
+
const filtered = merged.filter((t) => !t.startsWith("stream:"));
|
|
18272
|
+
filtered.push(`stream:${workStream}`);
|
|
18273
|
+
updates.tags = filtered;
|
|
18274
|
+
} else {
|
|
18275
|
+
updates.tags = merged;
|
|
18276
|
+
}
|
|
18277
|
+
} else if (sprints !== void 0 || workStream !== void 0) {
|
|
18202
18278
|
const existing = store.get(id);
|
|
18203
18279
|
if (!existing) {
|
|
18204
18280
|
return {
|
|
@@ -18206,10 +18282,16 @@ function createActionTools(store) {
|
|
|
18206
18282
|
isError: true
|
|
18207
18283
|
};
|
|
18208
18284
|
}
|
|
18209
|
-
|
|
18210
|
-
|
|
18211
|
-
|
|
18212
|
-
|
|
18285
|
+
let existingTags = existing.frontmatter.tags ?? [];
|
|
18286
|
+
if (sprints !== void 0) {
|
|
18287
|
+
existingTags = existingTags.filter((t) => !t.startsWith("sprint:"));
|
|
18288
|
+
existingTags.push(...sprints.map((s) => `sprint:${s}`));
|
|
18289
|
+
}
|
|
18290
|
+
if (workStream !== void 0) {
|
|
18291
|
+
existingTags = existingTags.filter((t) => !t.startsWith("stream:"));
|
|
18292
|
+
existingTags.push(`stream:${workStream}`);
|
|
18293
|
+
}
|
|
18294
|
+
updates.tags = existingTags;
|
|
18213
18295
|
}
|
|
18214
18296
|
const doc = store.update(id, updates, content);
|
|
18215
18297
|
return {
|
|
@@ -18374,14 +18456,19 @@ function createDocumentTools(store) {
|
|
|
18374
18456
|
{
|
|
18375
18457
|
type: external_exports.string().optional().describe(`Filter by document type (registered types: ${store.registeredTypes.join(", ")})`),
|
|
18376
18458
|
status: external_exports.string().optional().describe("Filter by status"),
|
|
18377
|
-
tag: external_exports.string().optional().describe("Filter by tag")
|
|
18459
|
+
tag: external_exports.string().optional().describe("Filter by tag"),
|
|
18460
|
+
workStream: external_exports.string().optional().describe("Filter by work stream name (matches stream:<value> tag)")
|
|
18378
18461
|
},
|
|
18379
18462
|
async (args) => {
|
|
18380
|
-
|
|
18463
|
+
let docs = store.list({
|
|
18381
18464
|
type: args.type,
|
|
18382
18465
|
status: args.status,
|
|
18383
18466
|
tag: args.tag
|
|
18384
18467
|
});
|
|
18468
|
+
if (args.workStream) {
|
|
18469
|
+
const streamTag = `stream:${args.workStream}`;
|
|
18470
|
+
docs = docs.filter((d) => d.frontmatter.tags?.includes(streamTag));
|
|
18471
|
+
}
|
|
18385
18472
|
const summary = docs.map((d) => ({
|
|
18386
18473
|
id: d.frontmatter.id,
|
|
18387
18474
|
title: d.frontmatter.title,
|
|
@@ -19419,6 +19506,17 @@ tr:hover td {
|
|
|
19419
19506
|
background: var(--bg-hover);
|
|
19420
19507
|
}
|
|
19421
19508
|
|
|
19509
|
+
/* Hierarchical work-item sub-rows */
|
|
19510
|
+
.child-row td {
|
|
19511
|
+
font-size: 0.8125rem;
|
|
19512
|
+
border-bottom-style: dashed;
|
|
19513
|
+
}
|
|
19514
|
+
.contribution-row td {
|
|
19515
|
+
font-size: 0.8125rem;
|
|
19516
|
+
color: var(--text-dim);
|
|
19517
|
+
border-bottom-style: dashed;
|
|
19518
|
+
}
|
|
19519
|
+
|
|
19422
19520
|
/* GAR */
|
|
19423
19521
|
.gar-overall {
|
|
19424
19522
|
text-align: center;
|
|
@@ -21106,22 +21204,36 @@ function sprintSummaryPage(data, cached2) {
|
|
|
21106
21204
|
</div>`,
|
|
21107
21205
|
{ titleTag: "h3" }
|
|
21108
21206
|
) : "";
|
|
21109
|
-
|
|
21207
|
+
function renderItemRows(items, depth = 0) {
|
|
21208
|
+
return items.flatMap((w) => {
|
|
21209
|
+
const isChild = depth > 0;
|
|
21210
|
+
const isContribution = w.type === "contribution";
|
|
21211
|
+
const rowClass = isContribution ? ' class="contribution-row"' : isChild ? ' class="child-row"' : "";
|
|
21212
|
+
const indent = depth > 0 ? ` style="padding-left: ${0.75 + depth * 1}rem"` : "";
|
|
21213
|
+
const streamCell = w.workStream ? `<span class="badge badge-subtle">${escapeHtml(w.workStream)}</span>` : "";
|
|
21214
|
+
const row = `
|
|
21215
|
+
<tr${rowClass}>
|
|
21216
|
+
<td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
21217
|
+
<td>${escapeHtml(w.title)}</td>
|
|
21218
|
+
<td>${streamCell}</td>
|
|
21219
|
+
<td>${escapeHtml(typeLabel(w.type))}</td>
|
|
21220
|
+
<td>${statusBadge(w.status)}</td>
|
|
21221
|
+
</tr>`;
|
|
21222
|
+
const childRows = w.children ? renderItemRows(w.children, depth + 1) : [];
|
|
21223
|
+
return [row, ...childRows];
|
|
21224
|
+
});
|
|
21225
|
+
}
|
|
21226
|
+
const workItemRows = renderItemRows(data.workItems.items);
|
|
21227
|
+
const workItemsSection = workItemRows.length > 0 ? collapsibleSection(
|
|
21110
21228
|
"ss-work-items",
|
|
21111
21229
|
"Work Items",
|
|
21112
21230
|
`<div class="table-wrap">
|
|
21113
21231
|
<table>
|
|
21114
21232
|
<thead>
|
|
21115
|
-
<tr><th>ID</th><th>Title</th><th>Type</th><th>Status</th></tr>
|
|
21233
|
+
<tr><th>ID</th><th>Title</th><th>Stream</th><th>Type</th><th>Status</th></tr>
|
|
21116
21234
|
</thead>
|
|
21117
21235
|
<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("")}
|
|
21236
|
+
${workItemRows.join("")}
|
|
21125
21237
|
</tbody>
|
|
21126
21238
|
</table>
|
|
21127
21239
|
</div>`,
|
|
@@ -26159,7 +26271,7 @@ function createProgram() {
|
|
|
26159
26271
|
const program2 = new Command();
|
|
26160
26272
|
program2.name("marvin").description(
|
|
26161
26273
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
26162
|
-
).version("0.4.
|
|
26274
|
+
).version("0.4.9");
|
|
26163
26275
|
program2.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
26164
26276
|
await initCommand();
|
|
26165
26277
|
});
|