mrvn-cli 0.5.10 → 0.5.11

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
@@ -15773,7 +15773,9 @@ function collectSprintSummaryData(store, sprintId) {
15773
15773
  progress: getEffectiveProgress(doc.frontmatter),
15774
15774
  owner: doc.frontmatter.owner,
15775
15775
  workFocus: focusTag ? focusTag.slice(6) : void 0,
15776
- aboutArtifact: about
15776
+ aboutArtifact: about,
15777
+ jiraKey: doc.frontmatter.jiraKey,
15778
+ jiraUrl: doc.frontmatter.jiraUrl
15777
15779
  };
15778
15780
  allItemsById.set(item.id, item);
15779
15781
  if (about && sprintItemIds.has(about)) {
@@ -16284,6 +16286,12 @@ function formatDate(iso) {
16284
16286
  function typeLabel(type) {
16285
16287
  return type.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
16286
16288
  }
16289
+ function jiraIcon(jiraKey, jiraUrl) {
16290
+ if (!jiraKey) return "";
16291
+ const href = jiraUrl ?? "#";
16292
+ const title = escapeHtml(jiraKey);
16293
+ return `<a href="${escapeHtml(href)}" target="_blank" rel="noopener" title="Jira: ${title}" class="jira-link"><svg class="jira-icon" viewBox="0 0 24 24" width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.005 2L6.5 7.505l5.505 5.505L17.51 7.505 12.005 2z" fill="#2684FF"/><path d="M6.5 7.505L1 13.01l5.505 5.505L12.01 13.01 6.5 7.505z" fill="url(#jira-g1)"/><path d="M17.51 7.505L12.005 13.01l5.505 5.505L23.015 13.01 17.51 7.505z" fill="url(#jira-g2)"/><path d="M12.005 13.01L6.5 18.515l5.505 5.505 5.505-5.505-5.505-5.505z" fill="#2684FF"/><defs><linearGradient id="jira-g1" x1="9.25" y1="7.51" x2="3.85" y2="12.91" gradientUnits="userSpaceOnUse"><stop stop-color="#0052CC"/><stop offset="1" stop-color="#2684FF"/></linearGradient><linearGradient id="jira-g2" x1="14.76" y1="7.51" x2="20.16" y2="12.91" gradientUnits="userSpaceOnUse"><stop stop-color="#0052CC"/><stop offset="1" stop-color="#2684FF"/></linearGradient></defs></svg></a>`;
16294
+ }
16287
16295
  function renderMarkdown(md) {
16288
16296
  const lines = md.split("\n");
16289
16297
  const out = [];
@@ -18149,6 +18157,18 @@ tr:hover td {
18149
18157
  .owner-badge-dm { background: rgba(52, 211, 153, 0.18); color: #34d399; }
18150
18158
  .owner-badge-other { background: rgba(139, 143, 164, 0.12); color: var(--text-dim); }
18151
18159
 
18160
+ /* Jira link icon */
18161
+ .jira-link {
18162
+ display: inline-flex;
18163
+ align-items: center;
18164
+ vertical-align: middle;
18165
+ margin-left: 0.35rem;
18166
+ opacity: 0.7;
18167
+ transition: opacity 0.15s;
18168
+ }
18169
+ .jira-link:hover { opacity: 1; }
18170
+ .jira-icon { vertical-align: middle; }
18171
+
18152
18172
  /* Group header rows (PO dashboard decisions/deps) */
18153
18173
  .group-header-row td {
18154
18174
  background: var(--bg-hover);
@@ -18173,7 +18193,7 @@ function documentsPage(data) {
18173
18193
  (doc) => `
18174
18194
  <tr>
18175
18195
  <td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.id)}</a></td>
18176
- <td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.title)}</a></td>
18196
+ <td><a href="/docs/${data.type}/${doc.frontmatter.id}">${escapeHtml(doc.frontmatter.title)}</a>${jiraIcon(doc.frontmatter.jiraKey, doc.frontmatter.jiraUrl)}</td>
18177
18197
  <td>${statusBadge(doc.frontmatter.status)}</td>
18178
18198
  <td>${escapeHtml(doc.frontmatter.owner ?? "\u2014")}</td>
18179
18199
  <td>${doc.frontmatter.priority ? `<span class="priority-${doc.frontmatter.priority.toLowerCase()}">${escapeHtml(doc.frontmatter.priority)}</span>` : "\u2014"}</td>
@@ -18262,7 +18282,7 @@ function documentDetailPage(doc) {
18262
18282
  </div>
18263
18283
 
18264
18284
  <div class="page-header">
18265
- <h2>${escapeHtml(fm.title)}</h2>
18285
+ <h2>${escapeHtml(fm.title)}${jiraIcon(fm.jiraKey, fm.jiraUrl)}</h2>
18266
18286
  <div class="subtitle">${escapeHtml(fm.id)} &middot; ${escapeHtml(label)}</div>
18267
18287
  </div>
18268
18288
 
@@ -19684,7 +19704,7 @@ function renderItemRows(items, borderColor, showOwner, depth = 0) {
19684
19704
  const row = `
19685
19705
  <tr class="${classes.join(" ")}" style="--focus-color: ${borderColor}">
19686
19706
  <td${indent}><a href="/docs/${escapeHtml(w.type)}/${escapeHtml(w.id)}">${escapeHtml(w.id)}</a></td>
19687
- <td>${escapeHtml(w.title)}</td>
19707
+ <td>${escapeHtml(w.title)}${jiraIcon(w.jiraKey, w.jiraUrl)}</td>
19688
19708
  ${ownerCell}
19689
19709
  <td>${statusBadge(w.status)}</td>
19690
19710
  <td>${progressCell}</td>
@@ -21309,7 +21329,7 @@ function boardPage(data, basePath = "/board") {
21309
21329
  <div class="board-card">
21310
21330
  <a href="/docs/${doc.frontmatter.type}/${doc.frontmatter.id}">
21311
21331
  <div class="bc-id">${escapeHtml(doc.frontmatter.id)}</div>
21312
- <div class="bc-title">${escapeHtml(doc.frontmatter.title)}</div>
21332
+ <div class="bc-title">${escapeHtml(doc.frontmatter.title)}${jiraIcon(doc.frontmatter.jiraKey, doc.frontmatter.jiraUrl)}</div>
21313
21333
  ${doc.frontmatter.owner ? `<div class="bc-owner">${escapeHtml(doc.frontmatter.owner)}</div>` : ""}
21314
21334
  </a>
21315
21335
  </div>`
@@ -25745,6 +25765,58 @@ function createJiraTools(store, projectConfig) {
25745
25765
  },
25746
25766
  { annotations: { readOnlyHint: true } }
25747
25767
  ),
25768
+ // --- Jira search (read-only) ---
25769
+ tool20(
25770
+ "search_jira",
25771
+ "Search Jira issues via JQL query. Read-only \u2014 returns results without creating any local documents. Use this to preview before importing or to find issues for linking.",
25772
+ {
25773
+ jql: external_exports.string().describe(`JQL query (e.g. 'project = PROJ AND status = "In Progress"')`),
25774
+ maxResults: external_exports.number().optional().describe("Max issues to return (default 20)")
25775
+ },
25776
+ async (args) => {
25777
+ const jira = createJiraClient(jiraUserConfig);
25778
+ if (!jira) return jiraNotConfiguredError();
25779
+ const result = await jira.client.searchIssuesV3(
25780
+ args.jql,
25781
+ ["summary", "status", "issuetype", "priority", "assignee", "labels"],
25782
+ args.maxResults ?? 20
25783
+ );
25784
+ const allDocs = store.registeredTypes.flatMap((t) => store.list({ type: t }));
25785
+ const jiraKeyToArtifact = /* @__PURE__ */ new Map();
25786
+ for (const doc of allDocs) {
25787
+ const jk = doc.frontmatter.jiraKey;
25788
+ if (jk) jiraKeyToArtifact.set(jk, doc.frontmatter.id);
25789
+ }
25790
+ const issues = result.issues.map((issue2) => {
25791
+ const marvinId = jiraKeyToArtifact.get(issue2.key);
25792
+ return {
25793
+ key: issue2.key,
25794
+ summary: issue2.fields.summary,
25795
+ status: issue2.fields.status.name,
25796
+ issueType: issue2.fields.issuetype.name,
25797
+ priority: issue2.fields.priority?.name ?? "None",
25798
+ assignee: issue2.fields.assignee?.displayName ?? "unassigned",
25799
+ labels: issue2.fields.labels ?? [],
25800
+ marvinArtifact: marvinId ?? null
25801
+ };
25802
+ });
25803
+ const parts = [
25804
+ `Found ${result.total ?? issues.length} issues (showing ${issues.length}).`,
25805
+ ""
25806
+ ];
25807
+ for (const issue2 of issues) {
25808
+ const linked = issue2.marvinArtifact ? ` \u2192 ${issue2.marvinArtifact}` : " (not linked)";
25809
+ parts.push(`${issue2.key} \u2014 ${issue2.summary} [${issue2.status}]${linked}`);
25810
+ parts.push(` Type: ${issue2.issueType} | Priority: ${issue2.priority} | Assignee: ${issue2.assignee}`);
25811
+ }
25812
+ parts.push("");
25813
+ parts.push("This is read-only. Use link_to_jira to link issues to Marvin artifacts, or pull_jira_issue to import as JI-xxx documents.");
25814
+ return {
25815
+ content: [{ type: "text", text: parts.join("\n") }]
25816
+ };
25817
+ },
25818
+ { annotations: { readOnlyHint: true } }
25819
+ ),
25748
25820
  // --- Jira → Local tools ---
25749
25821
  tool20(
25750
25822
  "pull_jira_issue",
@@ -26349,6 +26421,7 @@ var COMMON_TOOLS = `**Available tools:**
26349
26421
  - \`fetch_jira_status\` \u2014 **read-only**: fetch current Jira status, subtask progress, and linked issues for Jira-linked actions/tasks. Returns proposed changes without applying them.
26350
26422
  - \`fetch_jira_daily\` \u2014 **read-only**: fetch a daily/range summary of all Jira changes \u2014 status transitions, comments, linked Confluence pages, and cross-references with Marvin artifacts. Returns proposed actions (status updates, unlinked issues, question candidates, Confluence pages to review).
26351
26423
  - \`fetch_jira_statuses\` \u2014 **read-only**: discover all Jira statuses in a project and show their Marvin mappings (mapped vs unmapped).
26424
+ - \`search_jira\` \u2014 **read-only**: search Jira via JQL and return results with Marvin cross-references. No documents created \u2014 use to preview before importing or find issues for linking.
26352
26425
  - \`pull_jira_issue\` / \`pull_jira_issues_jql\` \u2014 import Jira issues as local JI-xxx documents (for Jira-originated items with no existing Marvin artifact).
26353
26426
  - \`list_jira_issues\` / \`get_jira_issue\` \u2014 browse locally imported JI-xxx documents.
26354
26427
  - \`sync_jira_issue\` \u2014 bidirectional sync of a local JI-xxx with Jira.
@@ -31875,7 +31948,7 @@ function createProgram() {
31875
31948
  const program = new Command();
31876
31949
  program.name("marvin").description(
31877
31950
  "AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
31878
- ).version("0.5.10");
31951
+ ).version("0.5.11");
31879
31952
  program.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
31880
31953
  await initCommand();
31881
31954
  });