ticketlens 0.43.2 → 0.43.4

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.43.2",
3
+ "version": "0.43.4",
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": {
@@ -207,7 +207,7 @@ async function applySummarize(brief, args, opts, configDir, conn, licensedFn, up
207
207
  const cliToken = opts.cliToken ?? readCliToken(configDir);
208
208
  const provider = opts.provider ?? resolveAiProvider(args, credentials);
209
209
  const aiInput = augmentBriefForAi(brief, ticket?.localAttachments);
210
- const summary = await summarizerFn({ brief: aiInput, mode, credentials, cliToken, provider });
210
+ const summary = await summarizerFn({ brief: aiInput, mode, credentials, cliToken, provider, ticketKey });
211
211
  if (ticketKey && !opts.summarizer) writeSummaryCache(ticketKey, profileName, summary, configDir);
212
212
  const divider = '─'.repeat(60);
213
213
  return brief + `\n\n${divider}\n─── AI Summary ${'─'.repeat(45)}\n${summary}\n${divider}\n`;
@@ -241,7 +241,7 @@ async function applyHandoff(ticket, args, opts, configDir, licensedFn, upgradeFn
241
241
  const cliToken = opts.cliToken ?? readCliToken(configDir);
242
242
  const provider = opts.provider ?? resolveAiProvider(args, credentials);
243
243
  const input = buildHandoffInput(ticket);
244
- const body = await summarizerFn({ brief: input, mode, credentials, cliToken, prompt: HANDOFF_PROMPT, maxTokens: 512, provider });
244
+ const body = await summarizerFn({ brief: input, mode, credentials, cliToken, prompt: HANDOFF_PROMPT, maxTokens: 512, provider, ticketKey: ticket?.key ?? null });
245
245
  return `## Handoff Brief — ${ticket.key}\n\n${body}\n`;
246
246
  } catch (err) {
247
247
  const onErrorFn = opts.onError ?? ((msg) => process.stderr.write(msg + '\n'));
@@ -3,7 +3,7 @@
3
3
  * Centralised here to avoid triplicating the regex and warning logic.
4
4
  */
5
5
 
6
- export const DEFAULT_API_BASE = 'https://api.ticketlens.app';
6
+ export const DEFAULT_API_BASE = 'http://api.ticketlens.test';
7
7
  export const DEFAULT_SITE_BASE = 'https://ticketlens.app';
8
8
 
9
9
  // Matches localhost, 127.0.0.1, and any hostname ending in .test or .local,
@@ -4,6 +4,17 @@ import { detectBase } from './branch-scanner.mjs';
4
4
  const TICKET_KEY_RE = /^[A-Z][A-Z0-9]+-\d+$/;
5
5
  const SPAWN_OPTS = { encoding: 'utf8', timeout: 10_000 };
6
6
 
7
+ // Backlog #26b: markdown never carries source evidence for an acceptance
8
+ // criterion, so unrelated doc edits must not leak into `analyzeDiff` or the
9
+ // raw diff sent to `--consensus`'s external AI providers.
10
+ //
11
+ // `top` anchors the pattern to the repo root; without it `*.md` resolves
12
+ // relative to `cwd`, and callers routinely run from a monorepo subdirectory.
13
+ //
14
+ // Scoped to `.md`, not `docs/**`: non-markdown files under `docs/` can be
15
+ // real evidence (e.g. a docs site's own source).
16
+ const EXCLUDED_DIFF_PATHSPECS = [':(exclude,top)*.md'];
17
+
7
18
  function run(execFn, cmd, args, cwd) {
8
19
  const result = execFn(cmd, args, { ...SPAWN_OPTS, cwd });
9
20
  return result.status === 0 ? (result.stdout || '') : null;
@@ -19,10 +30,10 @@ function computeDiff(execFn, cwd) {
19
30
  if (base) {
20
31
  const mergeBase = run(execFn, 'git', ['merge-base', 'HEAD', base], cwd)?.trim();
21
32
  if (mergeBase) {
22
- return run(execFn, 'git', ['diff', mergeBase], cwd);
33
+ return run(execFn, 'git', ['diff', mergeBase, '--', ...EXCLUDED_DIFF_PATHSPECS], cwd);
23
34
  }
24
35
  }
25
- return run(execFn, 'git', ['diff', 'HEAD'], cwd);
36
+ return run(execFn, 'git', ['diff', 'HEAD', '--', ...EXCLUDED_DIFF_PATHSPECS], cwd);
26
37
  }
27
38
 
28
39
  export function findLinkedCommits(ticketKey, opts = {}) {
@@ -17,13 +17,13 @@ const DEFAULT_MAX_TOKENS = 256;
17
17
  * @param {number} [opts.timeoutMs]
18
18
  * @returns {Promise<string>} Summary text
19
19
  */
20
- export async function summarize({ brief, mode, credentials = null, cliToken = null, fetcher = globalThis.fetch, timeoutMs = 30_000, prompt, maxTokens, provider }) {
20
+ export async function summarize({ brief, mode, credentials = null, cliToken = null, fetcher = globalThis.fetch, timeoutMs = 30_000, prompt, maxTokens, provider, ticketKey }) {
21
21
  const effectivePrompt = prompt ?? DEFAULT_PROMPT;
22
22
  const effectiveMaxTokens = maxTokens ?? DEFAULT_MAX_TOKENS;
23
23
  if (mode === 'byok') {
24
24
  return byok({ brief, credentials, fetcher, timeoutMs, prompt: effectivePrompt, maxTokens: effectiveMaxTokens, provider });
25
25
  }
26
- return cloud({ brief, cliToken, fetcher, timeoutMs });
26
+ return cloud({ brief, ticketKey, cliToken, fetcher, timeoutMs });
27
27
  }
28
28
 
29
29
  async function byok({ brief, credentials, fetcher, timeoutMs, prompt, maxTokens, provider }) {
@@ -137,8 +137,10 @@ async function callGroq({ brief, apiKey, fetcher, timeoutMs, prompt, maxTokens }
137
137
  return data.choices[0].message.content;
138
138
  }
139
139
 
140
- async function cloud({ brief, cliToken, fetcher, timeoutMs }) {
140
+ async function cloud({ brief, ticketKey, cliToken, fetcher, timeoutMs }) {
141
141
  if (!cliToken) throw new Error('Not logged in. Run `ticketlens login` first.');
142
+ const payload = { brief };
143
+ if (ticketKey) payload.ticketKey = ticketKey;
142
144
  const res = await fetcher(`${apiBase()}/v1/summarize`, {
143
145
  method: 'POST',
144
146
  signal: AbortSignal.timeout(timeoutMs),
@@ -146,7 +148,7 @@ async function cloud({ brief, cliToken, fetcher, timeoutMs }) {
146
148
  'Content-Type': 'application/json',
147
149
  'Authorization': `Bearer ${cliToken}`,
148
150
  },
149
- body: JSON.stringify({ brief }),
151
+ body: JSON.stringify(payload),
150
152
  });
151
153
 
152
154
  if (!res.ok) {