trackerctl 0.4.0 → 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 +5 -2
- package/dist/tracker.js +65 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -90,7 +90,9 @@ Read commands serve from a local sqlite cache that auto-syncs when older than
|
|
|
90
90
|
| `tracker close <id> [--reason <text>]` | Close (clears assignee + in-progress label) |
|
|
91
91
|
| `tracker comment <id> <text>` | Post a comment on an item |
|
|
92
92
|
| `tracker attach <id> <file...> [-m <msg>]` | Upload files, reference them from one comment; prints markdown |
|
|
93
|
+
| `tracker label <id> [--add a,b] [--remove c,d]` | Add/remove labels without clobbering the rest |
|
|
93
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) |
|
|
94
96
|
| `tracker estimate <id> <duration>` | Set the time estimate (`0` clears it) |
|
|
95
97
|
| `tracker dep <id> --blocked-by <o> \| --blocks <o>` | Add a dependency edge |
|
|
96
98
|
| `tracker parent <child> <parent>` | Re-parent an item |
|
|
@@ -175,8 +177,9 @@ domain refusal (e.g. lost a claim race) — pick different work, don't retry.
|
|
|
175
177
|
- Land it: `tracker pr merge <id> --close-issues` — also closes the `-i` issues
|
|
176
178
|
with a comment explaining why; never rely on provider auto-close
|
|
177
179
|
|
|
178
|
-
- Track time: `tracker spend <id>
|
|
179
|
-
|
|
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)
|
|
180
183
|
- Project memory: `tracker remember <key> "<fact>"`, `tracker memories --json`,
|
|
181
184
|
`tracker forget <key>`
|
|
182
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)),
|
|
@@ -1354,9 +1365,12 @@ write commands:
|
|
|
1354
1365
|
release <id> clear assignee/label, tombstone live claim tokens
|
|
1355
1366
|
close <id> [--reason <text>]
|
|
1356
1367
|
comment <id> <text> post a comment on an item
|
|
1368
|
+
label <id> [--add a,b] [--remove c,d]
|
|
1369
|
+
add/remove labels without touching the others
|
|
1357
1370
|
attach <id> <file...> [-m <message>]
|
|
1358
1371
|
upload files and attach them via a comment
|
|
1359
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
|
|
1360
1374
|
estimate <id> <duration> set the time estimate (0 clears it)
|
|
1361
1375
|
dep <id> --blocked-by <other> | --blocks <other>
|
|
1362
1376
|
parent <child-id> <parent-id>
|
|
@@ -1430,6 +1444,14 @@ Posts a comment on the item. Everything after the id is joined into one
|
|
|
1430
1444
|
comment body, so quoting multi-word text is optional.
|
|
1431
1445
|
|
|
1432
1446
|
example: tracker comment 42 "blocked on the design review, see thread"`,
|
|
1447
|
+
label: `usage: tracker label <id> [--add <a,b>] [--remove <c,d>]
|
|
1448
|
+
|
|
1449
|
+
Adds and/or removes labels (comma-separated) without clobbering the rest.
|
|
1450
|
+
At least one of --add/--remove is required.
|
|
1451
|
+
|
|
1452
|
+
examples:
|
|
1453
|
+
tracker label 42 --add status::agent-blocked
|
|
1454
|
+
tracker label 42 --remove status::agent-blocked --add meta::human-only`,
|
|
1433
1455
|
attach: `usage: tracker attach <id> <file...> [-m <message>] [--json]
|
|
1434
1456
|
|
|
1435
1457
|
Uploads each file to the provider and posts ONE comment on the item containing
|
|
@@ -1472,14 +1494,19 @@ Lists the item's comments oldest-first (system notes are filtered out). Claim
|
|
|
1472
1494
|
notes (\uD83D\uDD12/\uD83D\uDD13) and memory entries (\uD83D\uDCCC) appear here too \u2014 useful for debugging.
|
|
1473
1495
|
|
|
1474
1496
|
example: tracker comments 42 --json`,
|
|
1475
|
-
spend: `usage: tracker spend <id> <duration>
|
|
1497
|
+
spend: `usage: tracker spend <id> <duration> | tracker spend <id> --since-claim
|
|
1476
1498
|
|
|
1477
1499
|
Adds to the item's time spent. Durations use GitLab conventions:
|
|
1478
1500
|
units w/d/h/m/s with 1d = 8h and 1w = 5d. A leading "-" subtracts.
|
|
1479
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
|
+
|
|
1480
1506
|
examples:
|
|
1481
1507
|
tracker spend 42 1h30m
|
|
1482
|
-
tracker spend 42 -30m
|
|
1508
|
+
tracker spend 42 -30m # logged too much, take 30m back
|
|
1509
|
+
tracker spend 42 --since-claim`,
|
|
1483
1510
|
estimate: `usage: tracker estimate <id> <duration>
|
|
1484
1511
|
|
|
1485
1512
|
Sets the item's time estimate (same duration format as spend). 0 clears it.
|
|
@@ -1794,9 +1821,21 @@ async function cmdSpend(ctx, args) {
|
|
|
1794
1821
|
requireTimeTracking(ctx);
|
|
1795
1822
|
const [idArg, durationArg] = args.positionals;
|
|
1796
1823
|
const id = normalizeId(idArg);
|
|
1797
|
-
|
|
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)
|
|
1798
1829
|
throw new UsageError(commandHelp("spend"));
|
|
1799
|
-
|
|
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
|
+
}
|
|
1800
1839
|
if (seconds === 0)
|
|
1801
1840
|
throw new UsageError("spend needs a non-zero duration (e.g. 1h30m or -30m)");
|
|
1802
1841
|
await ctx.adapter.addTimeSpent(id, seconds);
|
|
@@ -1826,6 +1865,25 @@ async function cmdComment(ctx, args) {
|
|
|
1826
1865
|
await ctx.adapter.comment(id, body);
|
|
1827
1866
|
console.log(`commented on #${id}`);
|
|
1828
1867
|
}
|
|
1868
|
+
async function cmdLabel(ctx, args) {
|
|
1869
|
+
const id = normalizeId(args.positionals[0]);
|
|
1870
|
+
const csv = (name) => (str(args, name) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
1871
|
+
const addLabels = csv("--add");
|
|
1872
|
+
const removeLabels = csv("--remove");
|
|
1873
|
+
if (addLabels.length === 0 && removeLabels.length === 0) {
|
|
1874
|
+
throw new UsageError(commandHelp("label"));
|
|
1875
|
+
}
|
|
1876
|
+
await ctx.adapter.update(id, {
|
|
1877
|
+
...addLabels.length ? { addLabels } : {},
|
|
1878
|
+
...removeLabels.length ? { removeLabels } : {}
|
|
1879
|
+
});
|
|
1880
|
+
invalidate(ctx);
|
|
1881
|
+
const parts = [
|
|
1882
|
+
...addLabels.length ? [`+${addLabels.join(" +")}`] : [],
|
|
1883
|
+
...removeLabels.length ? [`-${removeLabels.join(" -")}`] : []
|
|
1884
|
+
];
|
|
1885
|
+
console.log(`#${id} labels: ${parts.join(" ")}`);
|
|
1886
|
+
}
|
|
1829
1887
|
async function cmdAttach(ctx, args) {
|
|
1830
1888
|
const [idArg, ...paths] = args.positionals;
|
|
1831
1889
|
const id = normalizeId(idArg);
|
|
@@ -2164,6 +2222,7 @@ var VALUE_FLAGS = {
|
|
|
2164
2222
|
comment: {},
|
|
2165
2223
|
comments: { "--json": "bool" },
|
|
2166
2224
|
attach: { "--message": "value", "--json": "bool" },
|
|
2225
|
+
label: { "--add": "value", "--remove": "value" },
|
|
2167
2226
|
pr: {
|
|
2168
2227
|
"--title": "value",
|
|
2169
2228
|
"--description": "value",
|
|
@@ -2175,7 +2234,7 @@ var VALUE_FLAGS = {
|
|
|
2175
2234
|
"--message": "value",
|
|
2176
2235
|
"--json": "bool"
|
|
2177
2236
|
},
|
|
2178
|
-
spend: {},
|
|
2237
|
+
spend: { "--since-claim": "bool" },
|
|
2179
2238
|
estimate: {},
|
|
2180
2239
|
sync: {},
|
|
2181
2240
|
claim: {},
|
|
@@ -2240,6 +2299,7 @@ ${HELP}`);
|
|
|
2240
2299
|
comment: cmdComment,
|
|
2241
2300
|
comments: cmdComments,
|
|
2242
2301
|
attach: cmdAttach,
|
|
2302
|
+
label: cmdLabel,
|
|
2243
2303
|
pr: cmdPr,
|
|
2244
2304
|
spend: cmdSpend,
|
|
2245
2305
|
estimate: cmdEstimate,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trackerctl",
|
|
3
|
-
"version": "0.4.
|
|
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",
|