ticketlens 0.9.9 → 0.9.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ticketlens",
3
- "version": "0.9.9",
3
+ "version": "0.9.10",
4
4
  "description": "Jira CLI for developers — fetch ticket context, triage your queue, and stop tab-switching. Zero dependencies, all local.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,6 +12,7 @@ export function assembleBrief(ticket, codeRefs = null, templateSections = null)
12
12
  sections.push(`# ${ticket.key}: ${ticket.summary}`);
13
13
 
14
14
  const meta = [`**Type:** ${ticket.type}`, `**Status:** ${ticket.status}`, `**Priority:** ${ticket.priority}`, `**Assignee:** ${ticket.assignee ?? 'Unassigned'}`, `**Reporter:** ${ticket.reporter ?? 'Unknown'}`];
15
+ if (ticket.sprint) meta.push(`**Sprint:** ${ticket.sprint}`);
15
16
  if (ticket.created) meta.push(`**Created:** ${ticket.created.split('T')[0]}`);
16
17
  if (ticket.updated) meta.push(`**Updated:** ${ticket.updated.split('T')[0]}`);
17
18
  sections.push(meta.join(' | '));
@@ -12,6 +12,24 @@ function toText(value) {
12
12
  return adfToText(value);
13
13
  }
14
14
 
15
+ /**
16
+ * Extracts the active sprint name from customfield_10020.
17
+ * Cloud v3: array of sprint objects — prefers active, falls back to last.
18
+ * Server v2: serialized Java string — extracts via name= regex.
19
+ */
20
+ function parseSprint(value) {
21
+ if (!value) return null;
22
+ if (Array.isArray(value)) {
23
+ const sprint = value.find(s => s.state === 'active') ?? value[value.length - 1];
24
+ return sprint?.name ?? null;
25
+ }
26
+ if (typeof value === 'string') {
27
+ const m = value.match(/name=([^,\]]+)/);
28
+ return m ? m[1].trim() : null;
29
+ }
30
+ return null;
31
+ }
32
+
15
33
  /**
16
34
  * Returns the ISO date string when the ticket entered its current status,
17
35
  * derived from Jira's changelog history. Walks backwards (most recent first)
@@ -50,6 +68,7 @@ export function normalizeTicket(raw) {
50
68
  created: f.created ?? null,
51
69
  updated: f.updated ?? null,
52
70
  statusChangedAt,
71
+ sprint: parseSprint(f.customfield_10020),
53
72
  labels: f.labels ?? [],
54
73
  components: (f.components ?? []).map(c => c.name),
55
74
  comments: (f.comment?.comments ?? []).map(c => ({
@@ -171,7 +190,7 @@ export async function searchTickets(jql, opts = {}) {
171
190
  const baseUrl = env.JIRA_BASE_URL.replace(/\/$/, '');
172
191
  const headers = { ...buildAuthHeader(env), 'Content-Type': 'application/json' };
173
192
 
174
- const fields = 'summary,status,assignee,priority,issuetype,comment,updated,statuscategorychangedate,created';
193
+ const fields = 'summary,status,assignee,priority,issuetype,comment,updated,statuscategorychangedate,created,customfield_10020';
175
194
  const params = new URLSearchParams({ jql, fields, maxResults: String(maxResults) });
176
195
  if (expandChangelog) params.set('expand', 'changelog');
177
196
  const endpoint = apiVersion >= 3 ? `/rest/api/3/search/jql` : `/rest/api/2/search`;
@@ -7,7 +7,7 @@
7
7
  const RE_GWT = /^\s*(given|when|then)\s+(.+)/i;
8
8
  const RE_MUST_ITEM = /^\s*[-*•]\s+((?:must|should|shall|ensure|verify)\b.+|.+(?:must|should|shall|ensure|verify).+)/i;
9
9
  const RE_NUM_MUST = /^\s*\d+\.\s+((?:must|should|shall|ensure|verify)\b.+|.+(?:must|should|shall|ensure|verify).+)/i;
10
- const RE_AC_HEADER = /^\s*#+\s*acceptance criteria\s*$/i;
10
+ const RE_AC_HEADER = /^\s*(?:#+\s*|h[1-6]\.\s*)?acceptance criteria\s*:?\s*$/i;
11
11
  const RE_BULLET = /^\s*[-*•]\s+(.+)/;
12
12
  const RE_NUM_ITEM = /^\s*\d+\.\s+(.+)/;
13
13
 
@@ -114,6 +114,7 @@ export function styleBrief(ticket, codeRefs = null, opts = {}) {
114
114
  `${s.dim('Priority:')} ${ticket.priority}`,
115
115
  `${s.dim('Assignee:')} ${ticket.assignee ?? 'Unassigned'}`,
116
116
  ];
117
+ if (ticket.sprint) meta.push(`${s.dim('Sprint:')} ${ticket.sprint}`);
117
118
  if (ticket.created) meta.push(`${s.dim('Created:')} ${ticket.created.split('T')[0]}`);
118
119
  if (ticket.updated) meta.push(`${s.dim('Updated:')} ${ticket.updated.split('T')[0]}`);
119
120
  sections.push(meta.join(s.dim(' · ')));