ticketlens 0.38.56 → 0.38.57

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/README.md CHANGED
@@ -1099,14 +1099,16 @@ npm test
1099
1099
  See [ROADMAP.md](ROADMAP.md) for the full plan.
1100
1100
 
1101
1101
  Recently shipped:
1102
- - **Prefix & status pickers** (`ticketlens init` / `config`, v0.12.0) — ticket prefixes and triage statuses are picked from your Jira instance's live project/status lists via multi-select; editing pre-selects current values, unchecking removes them, and stale entries are flagged `(not on server)`
1103
- - **Collision detection** (`ticketlens collisions`) — shows which files your branch shares with teammates' in-flight branches; `--push` auto-sends git branch data to the team snapshot. Team tier
1104
- - **Shareable triage snapshot** (`ticketlens triage --share`) — generates a 24h signed URL; recipients open it in any browser, no account needed. Team tier
1105
- - **Compliance push** (`ticketlens triage --push`) — enriches the team snapshot with per-ticket compliance status and coverage from the local ledger. Pro tier
1106
- - **"TicketLens for PRs"** (`ticketlens review`) — assembles a code-review context brief from your current branch: linked tickets, changed files, and ticket context in one brief
1107
- - **Confluence pages** — linked Confluence pages fetched automatically and included in the brief; origin-validated, non-fatal, capped at 10 pages
1108
- - **Linear support** — `ticketlens init` → Linear; connects via GraphQL API key, fetches tickets, triage, and statuses
1109
- - **GitHub Issues support** — `ticketlens init` → GitHub Issues; PAT-based, same normalized ticket shape
1102
+ - **Multi-agent AI consensus compliance** (`ticketlens compliance TICKET --consensus`) — routes requirements-vs-diff review through your team's AI provider pool, majority vote after a refinement round. Pro tier
1103
+ - **Dynamic AI Provider Registry** (Console > Admin > AI Provider Pool / AI Roles) — manage arbitrary AI providers and role-based routing, no fixed vendor list
1104
+ - **Full MCP tool coverage** (`ticketlens mcp`) — every CLI action (fetch, triage, compliance, recall, ticket writes) has a matching MCP tool
1105
+ - **`ticketlens issue-types`** — pre-fetches and caches a project's valid issue types, speeds up `ticket_create`
1106
+ - **Recall team sync** (`note add` / `recall`) — shared notes with Console verification, attachments, configurable capture strictness. Pro/Team tier
1107
+ - **`ticketlens doctor`** — diagnoses profile/connection/license/MCP problems; `--fix` for common issues
1108
+ - **Ticket write-back** (`comment`/`transition`/`assign`/`duplicates`/`link`/`update`/`create`) — write directly to Jira/GitHub/Linear from the CLI. Pro tier
1109
+ - **Stale status detection** — flags tickets stuck in a status too long, team-configurable thresholds. Pro tier
1110
+ - **Shared team Jira config** (Console > Admin > Jira) — manager sets the connection once, team inherits it. Pro+ tier
1111
+ - **Slack/Teams alerts** — needs-response, aging, and compliance-gap alerts plus a weekly digest. Team tier
1110
1112
 
1111
1113
  ---
1112
1114
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ticketlens",
3
- "version": "0.38.56",
3
+ "version": "0.38.57",
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": {
@@ -68,8 +68,10 @@ export function writeState(sessionId, state) {
68
68
  } catch { /* best-effort — a lost nudge counter is not worth failing the hook over */ }
69
69
  }
70
70
 
71
- // Two hours — how long a real capture in one directory counts as "recent
72
- // enough" to skip the Stop hook's nag, even from a brand-new session_id.
71
+ // Two hours of IDLE time — how long a real capture in one directory counts as
72
+ // "recent enough" to skip the Stop hook's nag, even from a brand-new session_id.
73
+ // Sliding, not fixed: ongoing ticket work renews the marker (see
74
+ // recall-nudge-stop.mjs, backlog #24), so only a full idle window lets it lapse.
73
75
  export const CAPTURE_FRESHNESS_MS = 2 * 60 * 60 * 1000;
74
76
 
75
77
  /**
@@ -24,7 +24,9 @@
24
24
  * the same boundary for a DISMISSED nag: without it, a session that already
25
25
  * got its one nag and was told "genuinely nothing qualified" would nag
26
26
  * again after the next compaction/resume rollover, since that dismissal
27
- * was never recorded anywhere — only a real capture was.
27
+ * was never recorded anywhere — only a real capture was. Both markers slide:
28
+ * ongoing ticket work renews them while fresh, so only a full idle window
29
+ * (CAPTURE_FRESHNESS_MS) lets either lapse (backlog #24).
28
30
  *
29
31
  * Which of the two cases above actually blocks is governed by the effective
30
32
  * recallStrictness — the active profile's own explicit config-set value, or
@@ -102,7 +104,19 @@ if (isLicensed('pro') && cliToken && !hasRecentAutoCaptureAttempt(cwd)) {
102
104
  // Refreshed on every check, independent of the once-per-session gate below —
103
105
  // a capture that happens AFTER this session already nagged once must still
104
106
  // update the marker, or a later session_id rollover would find it stale.
105
- if (sawNoteAdd) writeLastCaptureAt(cwd, Date.now());
107
+ //
108
+ // Sliding window (backlog #24, 7th report): ongoing ticket work also renews a
109
+ // marker that is still fresh, so it measures idle time, not time since the
110
+ // last capture/nag. A fixed window expired mid-work (capture 17:48, nag 19:48
111
+ // in a session with 23 silent Stops before it) and falsely claimed "nothing
112
+ // was ever captured". Only a session that could itself nag (fetch + mutation)
113
+ // renews, so non-ticket work and read-only lookups in the same cwd can't keep
114
+ // a marker alive; a lapsed marker is never revived. Accepted trade-off: such
115
+ // sessions chained in one cwd with gaps under the window keep suppressing.
116
+ const now = Date.now();
117
+ const isActiveTicketWork = sawFetch && sawMutatingAction;
118
+ if (sawNoteAdd || (isActiveTicketWork && hasRecentCapture(cwd, now))) writeLastCaptureAt(cwd, now);
119
+ if (isActiveTicketWork && hasRecentNag(cwd, now)) writeLastNagAt(cwd, now);
106
120
 
107
121
  const state = readState(sessionId);
108
122
  if (state.stopChecked) process.exit(0); // already asked once this session — respect the answer
@@ -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 = 'http://api.ticketlens.test';
6
+ export const DEFAULT_API_BASE = 'https://api.ticketlens.app';
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,