trackerctl 0.4.1 → 0.4.2

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
@@ -92,6 +92,7 @@ Read commands serve from a local sqlite cache that auto-syncs when older than
92
92
  | `tracker attach <id> <file...> [-m <msg>]` | Upload files, reference them from one comment; prints markdown |
93
93
  | `tracker label <id> [--add a,b] [--remove c,d]` | Add/remove labels without clobbering the rest |
94
94
  | `tracker spend <id> <duration>` | Add time spent (`1h30m`, `2d`; `-30m` subtracts) |
95
+ | `tracker spend <id> --since-claim` | Log wall-clock elapsed since the latest 🔒 claim note (claim-to-done timing) |
95
96
  | `tracker estimate <id> <duration>` | Set the time estimate (`0` clears it) |
96
97
  | `tracker dep <id> --blocked-by <o> \| --blocks <o>` | Add a dependency edge |
97
98
  | `tracker parent <child> <parent>` | Re-parent an item |
@@ -176,8 +177,9 @@ domain refusal (e.g. lost a claim race) — pick different work, don't retry.
176
177
  - Land it: `tracker pr merge <id> --close-issues` — also closes the `-i` issues
177
178
  with a comment explaining why; never rely on provider auto-close
178
179
 
179
- - Track time: `tracker spend <id> 1h30m` after finishing work (estimate vs spent
180
- feeds later evaluations; durations use 1d=8h, -30m subtracts)
180
+ - Track time: `tracker spend <id> --since-claim` after landing work logs the
181
+ elapsed claim-to-done wall clock from server timestamps (or an
182
+ explicit `tracker spend <id> 1h30m`; durations use 1d=8h, -30m subtracts)
181
183
  - Project memory: `tracker remember <key> "<fact>"`, `tracker memories --json`,
182
184
  `tracker forget <key>`
183
185
 
package/dist/tracker.js CHANGED
@@ -1003,6 +1003,17 @@ function electWinner(comments, nowMs, ttlMs) {
1003
1003
  live.sort((a, b) => a.ts - b.ts || compareCommentIds(a.commentId, b.commentId));
1004
1004
  return live[0] ?? null;
1005
1005
  }
1006
+ function secondsSinceClaim(comments, nowMs) {
1007
+ let latest = null;
1008
+ for (const c of comments) {
1009
+ if (!c.body.startsWith(CLAIM_MARK))
1010
+ continue;
1011
+ const ts = Date.parse(c.createdAt);
1012
+ if (Number.isFinite(ts) && (latest === null || ts > latest))
1013
+ latest = ts;
1014
+ }
1015
+ return latest === null ? null : Math.max(0, Math.round((nowMs - latest) / 1000));
1016
+ }
1006
1017
  var realClaimDeps = {
1007
1018
  now: () => Date.now(),
1008
1019
  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),
@@ -1359,6 +1370,7 @@ write commands:
1359
1370
  attach <id> <file...> [-m <message>]
1360
1371
  upload files and attach them via a comment
1361
1372
  spend <id> <duration> add time spent (1h30m, 45m, 2d; -30m subtracts)
1373
+ spend <id> --since-claim log elapsed time since the latest claim note
1362
1374
  estimate <id> <duration> set the time estimate (0 clears it)
1363
1375
  dep <id> --blocked-by <other> | --blocks <other>
1364
1376
  parent <child-id> <parent-id>
@@ -1482,14 +1494,19 @@ Lists the item's comments oldest-first (system notes are filtered out). Claim
1482
1494
  notes (\uD83D\uDD12/\uD83D\uDD13) and memory entries (\uD83D\uDCCC) appear here too \u2014 useful for debugging.
1483
1495
 
1484
1496
  example: tracker comments 42 --json`,
1485
- spend: `usage: tracker spend <id> <duration>
1497
+ spend: `usage: tracker spend <id> <duration> | tracker spend <id> --since-claim
1486
1498
 
1487
1499
  Adds to the item's time spent. Durations use GitLab conventions:
1488
1500
  units w/d/h/m/s with 1d = 8h and 1w = 5d. A leading "-" subtracts.
1489
1501
 
1502
+ --since-claim logs the wall-clock elapsed since the latest \uD83D\uDD12 claim note
1503
+ (rounded to whole minutes, minimum 1m) \u2014 claim-to-done ticket timing with
1504
+ no client-side clock needed. Exit 2 if the item was never claimed.
1505
+
1490
1506
  examples:
1491
1507
  tracker spend 42 1h30m
1492
- tracker spend 42 -30m # logged too much, take 30m back`,
1508
+ tracker spend 42 -30m # logged too much, take 30m back
1509
+ tracker spend 42 --since-claim`,
1493
1510
  estimate: `usage: tracker estimate <id> <duration>
1494
1511
 
1495
1512
  Sets the item's time estimate (same duration format as spend). 0 clears it.
@@ -1804,9 +1821,21 @@ async function cmdSpend(ctx, args) {
1804
1821
  requireTimeTracking(ctx);
1805
1822
  const [idArg, durationArg] = args.positionals;
1806
1823
  const id = normalizeId(idArg);
1807
- if (!durationArg)
1824
+ const sinceClaim = args.flags.get("--since-claim") === true;
1825
+ if (sinceClaim && durationArg) {
1826
+ throw new UsageError("pass either a duration or --since-claim, not both");
1827
+ }
1828
+ if (!sinceClaim && !durationArg)
1808
1829
  throw new UsageError(commandHelp("spend"));
1809
- const seconds = parseDuration(durationArg);
1830
+ let seconds;
1831
+ if (sinceClaim) {
1832
+ const elapsed = secondsSinceClaim(await ctx.adapter.listComments(id), Date.now());
1833
+ if (elapsed === null)
1834
+ throw new DomainError(`#${id} has no claim note to measure from`);
1835
+ seconds = Math.max(60, Math.round(elapsed / 60) * 60);
1836
+ } else {
1837
+ seconds = parseDuration(durationArg);
1838
+ }
1810
1839
  if (seconds === 0)
1811
1840
  throw new UsageError("spend needs a non-zero duration (e.g. 1h30m or -30m)");
1812
1841
  await ctx.adapter.addTimeSpent(id, seconds);
@@ -2205,7 +2234,7 @@ var VALUE_FLAGS = {
2205
2234
  "--message": "value",
2206
2235
  "--json": "bool"
2207
2236
  },
2208
- spend: {},
2237
+ spend: { "--since-claim": "bool" },
2209
2238
  estimate: {},
2210
2239
  sync: {},
2211
2240
  claim: {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trackerctl",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Multi-backend issue-tracking CLI for humans and AI agents — claim races, dependencies, hierarchy, local FTS search, project memory. GitLab adapter first.",
5
5
  "license": "MIT",
6
6
  "author": "refo",