mrvn-cli 0.4.8 → 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/dist/index.js +68 -21
- package/dist/index.js.map +1 -1
- package/dist/marvin-serve.js +67 -20
- package/dist/marvin-serve.js.map +1 -1
- package/dist/marvin.js +68 -21
- package/dist/marvin.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14557,7 +14557,8 @@ function createActionTools(store) {
|
|
|
14557
14557
|
priority: external_exports.string().optional().describe("Priority (high, medium, low)"),
|
|
14558
14558
|
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization"),
|
|
14559
14559
|
dueDate: external_exports.string().optional().describe("Due date in ISO format (e.g. '2026-03-15')"),
|
|
14560
|
-
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (e.g. ['SP-001']). Adds sprint:SP-xxx tags.")
|
|
14560
|
+
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (e.g. ['SP-001']). Adds sprint:SP-xxx tags."),
|
|
14561
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
14561
14562
|
},
|
|
14562
14563
|
async (args) => {
|
|
14563
14564
|
const tags = [...args.tags ?? []];
|
|
@@ -14567,6 +14568,9 @@ function createActionTools(store) {
|
|
|
14567
14568
|
if (!tags.includes(tag)) tags.push(tag);
|
|
14568
14569
|
}
|
|
14569
14570
|
}
|
|
14571
|
+
if (args.workStream) {
|
|
14572
|
+
tags.push(`stream:${args.workStream}`);
|
|
14573
|
+
}
|
|
14570
14574
|
const doc = store.create(
|
|
14571
14575
|
"action",
|
|
14572
14576
|
{
|
|
@@ -14604,10 +14608,11 @@ function createActionTools(store) {
|
|
|
14604
14608
|
priority: external_exports.string().optional().describe("New priority"),
|
|
14605
14609
|
dueDate: external_exports.string().optional().describe("Due date in ISO format (e.g. '2026-03-15')"),
|
|
14606
14610
|
tags: external_exports.array(external_exports.string()).optional().describe("Replace all tags. When provided with sprints, sprint tags are merged into this array."),
|
|
14607
|
-
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001'].")
|
|
14611
|
+
sprints: external_exports.array(external_exports.string()).optional().describe("Sprint IDs to assign (replaces existing sprint tags). E.g. ['SP-001']."),
|
|
14612
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
14608
14613
|
},
|
|
14609
14614
|
async (args) => {
|
|
14610
|
-
const { id, content, sprints, tags, ...updates } = args;
|
|
14615
|
+
const { id, content, sprints, tags, workStream, ...updates } = args;
|
|
14611
14616
|
if (tags !== void 0) {
|
|
14612
14617
|
const merged = [...tags];
|
|
14613
14618
|
if (sprints) {
|
|
@@ -14616,8 +14621,14 @@ function createActionTools(store) {
|
|
|
14616
14621
|
if (!merged.includes(tag)) merged.push(tag);
|
|
14617
14622
|
}
|
|
14618
14623
|
}
|
|
14619
|
-
|
|
14620
|
-
|
|
14624
|
+
if (workStream !== void 0) {
|
|
14625
|
+
const filtered = merged.filter((t) => !t.startsWith("stream:"));
|
|
14626
|
+
filtered.push(`stream:${workStream}`);
|
|
14627
|
+
updates.tags = filtered;
|
|
14628
|
+
} else {
|
|
14629
|
+
updates.tags = merged;
|
|
14630
|
+
}
|
|
14631
|
+
} else if (sprints !== void 0 || workStream !== void 0) {
|
|
14621
14632
|
const existing = store.get(id);
|
|
14622
14633
|
if (!existing) {
|
|
14623
14634
|
return {
|
|
@@ -14625,10 +14636,16 @@ function createActionTools(store) {
|
|
|
14625
14636
|
isError: true
|
|
14626
14637
|
};
|
|
14627
14638
|
}
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14639
|
+
let existingTags = existing.frontmatter.tags ?? [];
|
|
14640
|
+
if (sprints !== void 0) {
|
|
14641
|
+
existingTags = existingTags.filter((t) => !t.startsWith("sprint:"));
|
|
14642
|
+
existingTags.push(...sprints.map((s) => `sprint:${s}`));
|
|
14643
|
+
}
|
|
14644
|
+
if (workStream !== void 0) {
|
|
14645
|
+
existingTags = existingTags.filter((t) => !t.startsWith("stream:"));
|
|
14646
|
+
existingTags.push(`stream:${workStream}`);
|
|
14647
|
+
}
|
|
14648
|
+
updates.tags = existingTags;
|
|
14632
14649
|
}
|
|
14633
14650
|
const doc = store.update(id, updates, content);
|
|
14634
14651
|
return {
|
|
@@ -14793,14 +14810,19 @@ function createDocumentTools(store) {
|
|
|
14793
14810
|
{
|
|
14794
14811
|
type: external_exports.string().optional().describe(`Filter by document type (registered types: ${store.registeredTypes.join(", ")})`),
|
|
14795
14812
|
status: external_exports.string().optional().describe("Filter by status"),
|
|
14796
|
-
tag: external_exports.string().optional().describe("Filter by tag")
|
|
14813
|
+
tag: external_exports.string().optional().describe("Filter by tag"),
|
|
14814
|
+
workStream: external_exports.string().optional().describe("Filter by work stream name (matches stream:<value> tag)")
|
|
14797
14815
|
},
|
|
14798
14816
|
async (args) => {
|
|
14799
|
-
|
|
14817
|
+
let docs = store.list({
|
|
14800
14818
|
type: args.type,
|
|
14801
14819
|
status: args.status,
|
|
14802
14820
|
tag: args.tag
|
|
14803
14821
|
});
|
|
14822
|
+
if (args.workStream) {
|
|
14823
|
+
const streamTag = `stream:${args.workStream}`;
|
|
14824
|
+
docs = docs.filter((d) => d.frontmatter.tags?.includes(streamTag));
|
|
14825
|
+
}
|
|
14804
14826
|
const summary = docs.map((d) => ({
|
|
14805
14827
|
id: d.frontmatter.id,
|
|
14806
14828
|
title: d.frontmatter.title,
|
|
@@ -15493,11 +15515,13 @@ function collectSprintSummaryData(store, sprintId) {
|
|
|
15493
15515
|
const sprintItemIds = new Set(workItemDocs.map((d) => d.frontmatter.id));
|
|
15494
15516
|
for (const doc of workItemDocs) {
|
|
15495
15517
|
const about = doc.frontmatter.aboutArtifact;
|
|
15518
|
+
const streamTag = (doc.frontmatter.tags ?? []).find((t) => t.startsWith("stream:"));
|
|
15496
15519
|
const item = {
|
|
15497
15520
|
id: doc.frontmatter.id,
|
|
15498
15521
|
title: doc.frontmatter.title,
|
|
15499
15522
|
type: doc.frontmatter.type,
|
|
15500
15523
|
status: doc.frontmatter.status,
|
|
15524
|
+
workStream: streamTag ? streamTag.slice(7) : void 0,
|
|
15501
15525
|
aboutArtifact: about
|
|
15502
15526
|
};
|
|
15503
15527
|
allItemsById.set(item.id, item);
|
|
@@ -18196,10 +18220,12 @@ function sprintSummaryPage(data, cached2) {
|
|
|
18196
18220
|
const isContribution = w.type === "contribution";
|
|
18197
18221
|
const rowClass = isContribution ? ' class="contribution-row"' : isChild ? ' class="child-row"' : "";
|
|
18198
18222
|
const indent = depth > 0 ? ` style="padding-left: ${0.75 + depth * 1}rem"` : "";
|
|
18223
|
+
const streamCell = w.workStream ? `<span class="badge badge-subtle">${escapeHtml(w.workStream)}</span>` : "";
|
|
18199
18224
|
const row = `
|
|
18200
18225
|
<tr${rowClass}>
|
|
18201
18226
|
<td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
|
|
18202
18227
|
<td>${escapeHtml(w.title)}</td>
|
|
18228
|
+
<td>${streamCell}</td>
|
|
18203
18229
|
<td>${escapeHtml(typeLabel(w.type))}</td>
|
|
18204
18230
|
<td>${statusBadge(w.status)}</td>
|
|
18205
18231
|
</tr>`;
|
|
@@ -18214,7 +18240,7 @@ function sprintSummaryPage(data, cached2) {
|
|
|
18214
18240
|
`<div class="table-wrap">
|
|
18215
18241
|
<table>
|
|
18216
18242
|
<thead>
|
|
18217
|
-
<tr><th>ID</th><th>Title</th><th>Type</th><th>Status</th></tr>
|
|
18243
|
+
<tr><th>ID</th><th>Title</th><th>Stream</th><th>Type</th><th>Status</th></tr>
|
|
18218
18244
|
</thead>
|
|
18219
18245
|
<tbody>
|
|
18220
18246
|
${workItemRows.join("")}
|
|
@@ -19513,7 +19539,8 @@ function createContributionTools(store) {
|
|
|
19513
19539
|
contributionType: external_exports.string().describe("Type of contribution (e.g. 'action-result', 'risk-finding')"),
|
|
19514
19540
|
aboutArtifact: external_exports.string().describe("Artifact ID this contribution relates to (e.g. 'A-001', 'T-003')"),
|
|
19515
19541
|
status: external_exports.string().optional().describe("Status (default: 'done')"),
|
|
19516
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization")
|
|
19542
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Tags for categorization"),
|
|
19543
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
19517
19544
|
},
|
|
19518
19545
|
async (args) => {
|
|
19519
19546
|
const frontmatter = {
|
|
@@ -19523,7 +19550,9 @@ function createContributionTools(store) {
|
|
|
19523
19550
|
contributionType: args.contributionType
|
|
19524
19551
|
};
|
|
19525
19552
|
frontmatter.aboutArtifact = args.aboutArtifact;
|
|
19526
|
-
|
|
19553
|
+
const tags = [...args.tags ?? []];
|
|
19554
|
+
if (args.workStream) tags.push(`stream:${args.workStream}`);
|
|
19555
|
+
if (tags.length > 0) frontmatter.tags = tags;
|
|
19527
19556
|
const doc = store.create("contribution", frontmatter, args.content);
|
|
19528
19557
|
return {
|
|
19529
19558
|
content: [
|
|
@@ -19542,10 +19571,18 @@ function createContributionTools(store) {
|
|
|
19542
19571
|
id: external_exports.string().describe("Contribution ID to update"),
|
|
19543
19572
|
title: external_exports.string().optional().describe("New title"),
|
|
19544
19573
|
status: external_exports.string().optional().describe("New status"),
|
|
19545
|
-
content: external_exports.string().optional().describe("New content")
|
|
19574
|
+
content: external_exports.string().optional().describe("New content"),
|
|
19575
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
19546
19576
|
},
|
|
19547
19577
|
async (args) => {
|
|
19548
|
-
const { id, content, ...updates } = args;
|
|
19578
|
+
const { id, content, workStream, ...updates } = args;
|
|
19579
|
+
if (workStream !== void 0) {
|
|
19580
|
+
const existing = store.get(id);
|
|
19581
|
+
const existingTags = existing?.frontmatter.tags ?? [];
|
|
19582
|
+
const filtered = existingTags.filter((t) => !t.startsWith("stream:"));
|
|
19583
|
+
filtered.push(`stream:${workStream}`);
|
|
19584
|
+
updates.tags = filtered;
|
|
19585
|
+
}
|
|
19549
19586
|
const doc = store.update(id, updates, content);
|
|
19550
19587
|
return {
|
|
19551
19588
|
content: [
|
|
@@ -20013,7 +20050,8 @@ function createTaskTools(store) {
|
|
|
20013
20050
|
estimatedPoints: external_exports.number().optional().describe("Story point estimate"),
|
|
20014
20051
|
complexity: external_exports.enum(["trivial", "simple", "moderate", "complex", "very-complex"]).optional().describe("Task complexity"),
|
|
20015
20052
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("Task priority"),
|
|
20016
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Additional tags")
|
|
20053
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Additional tags"),
|
|
20054
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Adds a stream:<value> tag.")
|
|
20017
20055
|
},
|
|
20018
20056
|
async (args) => {
|
|
20019
20057
|
const linkedEpics = normalizeLinkedEpics(args.linkedEpic);
|
|
@@ -20026,11 +20064,13 @@ function createTaskTools(store) {
|
|
|
20026
20064
|
warnings.push(`Warning: ${epicId} is a ${epic.frontmatter.type}, not an epic`);
|
|
20027
20065
|
}
|
|
20028
20066
|
}
|
|
20067
|
+
const baseTags = [...generateEpicTags(linkedEpics), ...args.tags ?? []];
|
|
20068
|
+
if (args.workStream) baseTags.push(`stream:${args.workStream}`);
|
|
20029
20069
|
const frontmatter = {
|
|
20030
20070
|
title: args.title,
|
|
20031
20071
|
status: args.status ?? "backlog",
|
|
20032
20072
|
linkedEpic: linkedEpics,
|
|
20033
|
-
tags:
|
|
20073
|
+
tags: baseTags
|
|
20034
20074
|
};
|
|
20035
20075
|
if (args.aboutArtifact) frontmatter.aboutArtifact = args.aboutArtifact;
|
|
20036
20076
|
if (args.acceptanceCriteria) frontmatter.acceptanceCriteria = args.acceptanceCriteria;
|
|
@@ -20065,10 +20105,11 @@ function createTaskTools(store) {
|
|
|
20065
20105
|
estimatedPoints: external_exports.number().optional().describe("New story point estimate"),
|
|
20066
20106
|
complexity: external_exports.enum(["trivial", "simple", "moderate", "complex", "very-complex"]).optional().describe("New complexity"),
|
|
20067
20107
|
priority: external_exports.enum(["critical", "high", "medium", "low"]).optional().describe("New priority"),
|
|
20068
|
-
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)")
|
|
20108
|
+
tags: external_exports.array(external_exports.string()).optional().describe("Replace tags (e.g. remove old tags, add new ones)"),
|
|
20109
|
+
workStream: external_exports.string().optional().describe("Work stream name (e.g. 'Budget UX'). Replaces existing stream:<value> tag.")
|
|
20069
20110
|
},
|
|
20070
20111
|
async (args) => {
|
|
20071
|
-
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, ...updates } = args;
|
|
20112
|
+
const { id, content, linkedEpic: rawLinkedEpic, tags: userTags, workStream, ...updates } = args;
|
|
20072
20113
|
const warnings = [];
|
|
20073
20114
|
if (rawLinkedEpic !== void 0) {
|
|
20074
20115
|
const linkedEpics = normalizeLinkedEpics(rawLinkedEpic);
|
|
@@ -20089,6 +20130,12 @@ function createTaskTools(store) {
|
|
|
20089
20130
|
} else if (userTags !== void 0) {
|
|
20090
20131
|
updates.tags = userTags;
|
|
20091
20132
|
}
|
|
20133
|
+
if (workStream !== void 0) {
|
|
20134
|
+
const currentTags = updates.tags ?? store.get(id)?.frontmatter.tags ?? [];
|
|
20135
|
+
const filtered = currentTags.filter((t) => !t.startsWith("stream:"));
|
|
20136
|
+
filtered.push(`stream:${workStream}`);
|
|
20137
|
+
updates.tags = filtered;
|
|
20138
|
+
}
|
|
20092
20139
|
const doc = store.update(id, updates, content);
|
|
20093
20140
|
const parts = [`Updated task ${doc.frontmatter.id}: ${doc.frontmatter.title}`];
|
|
20094
20141
|
if (warnings.length > 0) {
|
|
@@ -26230,7 +26277,7 @@ function createProgram() {
|
|
|
26230
26277
|
const program = new Command();
|
|
26231
26278
|
program.name("marvin").description(
|
|
26232
26279
|
"AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
|
|
26233
|
-
).version("0.4.
|
|
26280
|
+
).version("0.4.9");
|
|
26234
26281
|
program.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
|
|
26235
26282
|
await initCommand();
|
|
26236
26283
|
});
|