mrvn-cli 0.5.15 → 0.5.16

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.d.ts CHANGED
@@ -16,8 +16,12 @@ interface MarvinUserConfig {
16
16
  interface GitConfig {
17
17
  remote?: string;
18
18
  }
19
+ interface ConditionalJiraStatusEntry {
20
+ default: string[];
21
+ inSprint?: string[];
22
+ }
19
23
  interface JiraStatusMap {
20
- [marvinStatus: string]: string[];
24
+ [marvinStatus: string]: string[] | ConditionalJiraStatusEntry;
21
25
  }
22
26
  interface JiraProjectConfig {
23
27
  projectKey?: string;
package/dist/index.js CHANGED
@@ -25092,24 +25092,53 @@ var DEFAULT_TASK_STATUS_MAP = {
25092
25092
  blocked: ["Blocked"],
25093
25093
  backlog: ["To Do", "Open", "Backlog", "New"]
25094
25094
  };
25095
- function buildStatusLookup(configMap, defaults) {
25095
+ function isConditionalEntry(value) {
25096
+ return !Array.isArray(value) && typeof value === "object" && "default" in value;
25097
+ }
25098
+ function buildStatusLookup(configMap, defaults, inSprint = false) {
25096
25099
  const map2 = configMap ?? defaults;
25097
25100
  const lookup = /* @__PURE__ */ new Map();
25098
- for (const [marvinStatus, jiraStatuses] of Object.entries(map2)) {
25099
- for (const js of jiraStatuses) {
25101
+ for (const [marvinStatus, value] of Object.entries(map2)) {
25102
+ const statuses = isConditionalEntry(value) ? value.default : value;
25103
+ for (const js of statuses) {
25100
25104
  lookup.set(js.toLowerCase(), marvinStatus);
25101
25105
  }
25102
25106
  }
25107
+ if (inSprint) {
25108
+ for (const [marvinStatus, value] of Object.entries(map2)) {
25109
+ if (isConditionalEntry(value) && value.inSprint) {
25110
+ for (const js of value.inSprint) {
25111
+ lookup.set(js.toLowerCase(), marvinStatus);
25112
+ }
25113
+ }
25114
+ }
25115
+ }
25103
25116
  return lookup;
25104
25117
  }
25105
- function mapJiraStatusForAction(status, configMap) {
25106
- const lookup = buildStatusLookup(configMap, DEFAULT_ACTION_STATUS_MAP);
25118
+ function mapJiraStatusForAction(status, configMap, inSprint) {
25119
+ const lookup = buildStatusLookup(configMap, DEFAULT_ACTION_STATUS_MAP, inSprint ?? false);
25107
25120
  return lookup.get(status.toLowerCase()) ?? "open";
25108
25121
  }
25109
- function mapJiraStatusForTask(status, configMap) {
25110
- const lookup = buildStatusLookup(configMap, DEFAULT_TASK_STATUS_MAP);
25122
+ function mapJiraStatusForTask(status, configMap, inSprint) {
25123
+ const lookup = buildStatusLookup(configMap, DEFAULT_TASK_STATUS_MAP, inSprint ?? false);
25111
25124
  return lookup.get(status.toLowerCase()) ?? "backlog";
25112
25125
  }
25126
+ function isInActiveSprint(store, tags) {
25127
+ if (!tags) return false;
25128
+ const sprintTags = tags.filter((t) => t.startsWith("sprint:"));
25129
+ if (sprintTags.length === 0) return false;
25130
+ for (const tag of sprintTags) {
25131
+ const sprintId = tag.slice(7);
25132
+ const sprintDoc = store.get(sprintId);
25133
+ if (sprintDoc) {
25134
+ const status = sprintDoc.frontmatter.status;
25135
+ if (status === "active" || status === "completed") {
25136
+ return true;
25137
+ }
25138
+ }
25139
+ }
25140
+ return false;
25141
+ }
25113
25142
  function extractJiraKeyFromTags(tags) {
25114
25143
  if (!tags) return void 0;
25115
25144
  const tag = tags.find((t) => /^jira:[A-Z]+-\d+$/i.test(t));
@@ -25151,7 +25180,8 @@ async function fetchJiraStatus(store, client, host, artifactId, statusMap) {
25151
25180
  const artifactType = doc.frontmatter.type;
25152
25181
  try {
25153
25182
  const issue2 = await client.getIssueWithLinks(jiraKey);
25154
- const proposedStatus = artifactType === "task" ? mapJiraStatusForTask(issue2.fields.status.name, statusMap?.task) : mapJiraStatusForAction(issue2.fields.status.name, statusMap?.action);
25183
+ const inSprint = isInActiveSprint(store, doc.frontmatter.tags);
25184
+ const proposedStatus = artifactType === "task" ? mapJiraStatusForTask(issue2.fields.status.name, statusMap?.task, inSprint) : mapJiraStatusForAction(issue2.fields.status.name, statusMap?.action, inSprint);
25155
25185
  const currentStatus = doc.frontmatter.status;
25156
25186
  const linkedIssues = [];
25157
25187
  if (issue2.fields.subtasks) {
@@ -25503,7 +25533,7 @@ async function fetchJiraDaily(store, client, host, projectKey, dateRange, status
25503
25533
  const batch = issues.slice(i, i + BATCH_SIZE2);
25504
25534
  const results = await Promise.allSettled(
25505
25535
  batch.map(
25506
- (issue2) => processIssue(issue2, client, host, dateRange, jiraKeyToArtifacts, allDocs, statusMap)
25536
+ (issue2) => processIssue(issue2, client, host, dateRange, jiraKeyToArtifacts, allDocs, statusMap, store)
25507
25537
  )
25508
25538
  );
25509
25539
  for (let j = 0; j < results.length; j++) {
@@ -25520,7 +25550,7 @@ async function fetchJiraDaily(store, client, host, projectKey, dateRange, status
25520
25550
  summary.proposedActions = generateProposedActions(summary.issues);
25521
25551
  return summary;
25522
25552
  }
25523
- async function processIssue(issue2, client, host, dateRange, jiraKeyToArtifacts, allDocs, statusMap) {
25553
+ async function processIssue(issue2, client, host, dateRange, jiraKeyToArtifacts, allDocs, statusMap, store) {
25524
25554
  const [changelogResult, commentsResult, remoteLinksResult, issueWithLinks] = await Promise.all([
25525
25555
  client.getChangelog(issue2.key).catch(() => []),
25526
25556
  client.getComments(issue2.key).catch(() => []),
@@ -25608,7 +25638,8 @@ async function processIssue(issue2, client, host, dateRange, jiraKeyToArtifacts,
25608
25638
  if (artifactType === "action" || artifactType === "task") {
25609
25639
  const jiraStatus = issue2.fields.status?.name;
25610
25640
  if (jiraStatus) {
25611
- proposedStatus = artifactType === "task" ? mapJiraStatusForTask(jiraStatus, statusMap?.task) : mapJiraStatusForAction(jiraStatus, statusMap?.action);
25641
+ const inSprint = store ? isInActiveSprint(store, fm.tags) : false;
25642
+ proposedStatus = artifactType === "task" ? mapJiraStatusForTask(jiraStatus, statusMap?.task, inSprint) : mapJiraStatusForAction(jiraStatus, statusMap?.action, inSprint);
25612
25643
  }
25613
25644
  }
25614
25645
  marvinArtifacts.push({
@@ -25860,7 +25891,8 @@ async function assessSprintProgress(store, client, host, options = {}) {
25860
25891
  const commentSignals = [];
25861
25892
  if (jiraData) {
25862
25893
  jiraStatus = jiraData.issue.fields.status.name;
25863
- proposedMarvinStatus = fm.type === "task" ? mapJiraStatusForTask(jiraStatus, options.statusMap?.task) : mapJiraStatusForAction(jiraStatus, options.statusMap?.action);
25894
+ const inSprint = isInActiveSprint(store, fm.tags);
25895
+ proposedMarvinStatus = fm.type === "task" ? mapJiraStatusForTask(jiraStatus, options.statusMap?.task, inSprint) : mapJiraStatusForAction(jiraStatus, options.statusMap?.action, inSprint);
25864
25896
  const subtasks = jiraData.issue.fields.subtasks ?? [];
25865
25897
  if (subtasks.length > 0) {
25866
25898
  jiraSubtaskProgress = computeSubtaskProgress(subtasks);
@@ -26899,12 +26931,20 @@ function createJiraTools(store, projectConfig) {
26899
26931
  const actionMap = statusMap?.action ?? DEFAULT_ACTION_STATUS_MAP;
26900
26932
  const taskMap = statusMap?.task ?? DEFAULT_TASK_STATUS_MAP;
26901
26933
  const actionLookup = /* @__PURE__ */ new Map();
26902
- for (const [marvin, jiraStatuses] of Object.entries(actionMap)) {
26934
+ for (const [marvin, value] of Object.entries(actionMap)) {
26935
+ const jiraStatuses = Array.isArray(value) ? value : value.default;
26903
26936
  for (const js of jiraStatuses) actionLookup.set(js.toLowerCase(), marvin);
26937
+ if (!Array.isArray(value) && value.inSprint) {
26938
+ for (const js of value.inSprint) actionLookup.set(js.toLowerCase(), `${marvin} (inSprint)`);
26939
+ }
26904
26940
  }
26905
26941
  const taskLookup = /* @__PURE__ */ new Map();
26906
- for (const [marvin, jiraStatuses] of Object.entries(taskMap)) {
26942
+ for (const [marvin, value] of Object.entries(taskMap)) {
26943
+ const jiraStatuses = Array.isArray(value) ? value : value.default;
26907
26944
  for (const js of jiraStatuses) taskLookup.set(js.toLowerCase(), marvin);
26945
+ if (!Array.isArray(value) && value.inSprint) {
26946
+ for (const js of value.inSprint) taskLookup.set(js.toLowerCase(), `${marvin} (inSprint)`);
26947
+ }
26908
26948
  }
26909
26949
  const parts = [
26910
26950
  `Found ${statusCounts.size} distinct statuses in ${resolvedProjectKey} (scanned ${data.issues.length} of ${data.total} issues):`,
@@ -32475,11 +32515,13 @@ async function jiraStatusesCommand(projectKey) {
32475
32515
  statusCounts.set(s, (statusCounts.get(s) ?? 0) + 1);
32476
32516
  }
32477
32517
  const actionLookup = /* @__PURE__ */ new Map();
32478
- for (const [marvin, jiraStatuses] of Object.entries(actionMap)) {
32518
+ for (const [marvin, value] of Object.entries(actionMap)) {
32519
+ const jiraStatuses = Array.isArray(value) ? value : value.default;
32479
32520
  for (const js of jiraStatuses) actionLookup.set(js.toLowerCase(), marvin);
32480
32521
  }
32481
32522
  const taskLookup = /* @__PURE__ */ new Map();
32482
- for (const [marvin, jiraStatuses] of Object.entries(taskMap)) {
32523
+ for (const [marvin, value] of Object.entries(taskMap)) {
32524
+ const jiraStatuses = Array.isArray(value) ? value : value.default;
32483
32525
  for (const js of jiraStatuses) taskLookup.set(js.toLowerCase(), marvin);
32484
32526
  }
32485
32527
  console.log(
@@ -32662,7 +32704,7 @@ function createProgram() {
32662
32704
  const program = new Command();
32663
32705
  program.name("marvin").description(
32664
32706
  "AI-powered product development assistant with Product Owner, Delivery Manager, and Technical Lead personas"
32665
- ).version("0.5.15");
32707
+ ).version("0.5.16");
32666
32708
  program.command("init").description("Initialize a new Marvin project in the current directory").action(async () => {
32667
32709
  await initCommand();
32668
32710
  });