workday-daemon 0.20.0 → 0.21.0
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 +2 -0
- package/dist/cli.js +55 -0
- package/dist/cli.js.map +1 -1
- package/dist/core/constants.d.ts +1 -1
- package/dist/core/constants.js +1 -1
- package/dist/core/daily-log.d.ts +12 -0
- package/dist/core/daily-log.js +33 -0
- package/dist/core/daily-log.js.map +1 -1
- package/dist/core/day-edit.d.ts +14 -0
- package/dist/core/day-edit.js +12 -1
- package/dist/core/day-edit.js.map +1 -1
- package/dist/core/session-tracker.d.ts +11 -0
- package/dist/core/session-tracker.js +11 -1
- package/dist/core/session-tracker.js.map +1 -1
- package/dist/core/types.d.ts +16 -0
- package/dist/http-server.d.ts +7 -0
- package/dist/http-server.js +62 -0
- package/dist/http-server.js.map +1 -1
- package/dist/push/month-report.js +1 -0
- package/dist/push/month-report.js.map +1 -1
- package/dist/push/tempo-import.d.ts +26 -0
- package/dist/push/tempo-import.js +123 -0
- package/dist/push/tempo-import.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// Mirror import: adopt foreign Tempo worklogs (unowned, not tombstoned) as
|
|
2
|
+
// local manual entries plus a push-log ownership record whose baseline is
|
|
3
|
+
// the current remote state — so an imported entry lands in verified parity
|
|
4
|
+
// and becomes a first-class mirror citizen (editable, deletable, pushable).
|
|
5
|
+
import { importEntryOnDate } from '../core/day-edit.js';
|
|
6
|
+
import { loadPushLog, savePushLog, loadTombstones, pushLogKey } from './push-log.js';
|
|
7
|
+
import { fetchMonthSnapshot } from './tempo-snapshot.js';
|
|
8
|
+
// Strip the Tempo auto-placeholder — locally an empty description IS empty.
|
|
9
|
+
function importDescription(wl, task) {
|
|
10
|
+
const desc = wl.description ?? '';
|
|
11
|
+
return desc === `Working on work item ${task}` ? '' : desc;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Adopt foreign worklogs from an already-loaded snapshot. Per-worklog
|
|
15
|
+
* failures (unresolved key, day window, future date) land as item errors —
|
|
16
|
+
* the rest still import. Ownership is persisted after every adopted entry.
|
|
17
|
+
*/
|
|
18
|
+
export function importFromSnapshot(snapshot, options) {
|
|
19
|
+
const { config, today } = options;
|
|
20
|
+
const pushLog = loadPushLog();
|
|
21
|
+
const ownedIds = new Set(Object.values(pushLog).map(e => e.tempoWorklogId));
|
|
22
|
+
const tombstoneIds = new Set(loadTombstones().map(t => t.tempoWorklogId));
|
|
23
|
+
const snapById = new Map(snapshot.worklogs.map(w => [w.tempoWorklogId, w]));
|
|
24
|
+
// Explicit ids get per-id feedback (absent / owned / tombstoned); the
|
|
25
|
+
// no-ids form silently targets whatever is foreign right now.
|
|
26
|
+
const items = [];
|
|
27
|
+
let targets;
|
|
28
|
+
if (options.worklogIds !== undefined) {
|
|
29
|
+
targets = [];
|
|
30
|
+
for (const id of options.worklogIds) {
|
|
31
|
+
const wl = snapById.get(id);
|
|
32
|
+
if (!wl) {
|
|
33
|
+
items.push({ tempoWorklogId: id, date: '', task: '', seconds: 0, error: 'Not in the Tempo snapshot — re-sync and retry' });
|
|
34
|
+
}
|
|
35
|
+
else if (ownedIds.has(id)) {
|
|
36
|
+
items.push(itemOf(wl, snapshot, 'Already imported (owned locally)'));
|
|
37
|
+
}
|
|
38
|
+
else if (tombstoneIds.has(id)) {
|
|
39
|
+
items.push(itemOf(wl, snapshot, 'Pending local delete — push first'));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
targets.push(wl);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
targets = snapshot.worklogs.filter(w => !ownedIds.has(w.tempoWorklogId) && !tombstoneIds.has(w.tempoWorklogId));
|
|
48
|
+
}
|
|
49
|
+
if (options.date) {
|
|
50
|
+
for (const wl of targets.filter(w => w.startDate !== options.date)) {
|
|
51
|
+
if (options.worklogIds !== undefined)
|
|
52
|
+
items.push(itemOf(wl, snapshot, `Not on ${options.date}`));
|
|
53
|
+
}
|
|
54
|
+
targets = targets.filter(w => w.startDate === options.date);
|
|
55
|
+
}
|
|
56
|
+
targets.sort((a, b) => a.startDate.localeCompare(b.startDate) || a.tempoWorklogId - b.tempoWorklogId);
|
|
57
|
+
for (const wl of targets) {
|
|
58
|
+
const task = snapshot.issueKeys?.[String(wl.issueId)];
|
|
59
|
+
if (!task) {
|
|
60
|
+
items.push(itemOf(wl, snapshot, 'Ticket key unresolved — check Jira access, re-sync'));
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (wl.startDate > today) {
|
|
64
|
+
items.push(itemOf(wl, snapshot, 'Future-dated in Tempo — import once the day arrives'));
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const input = {
|
|
68
|
+
task,
|
|
69
|
+
// Nearest minute stays within TEMPO_TOLERANCE_SECONDS — no drift.
|
|
70
|
+
minutes: Math.max(1, Math.round(wl.timeSpentSeconds / 60)),
|
|
71
|
+
description: importDescription(wl, task),
|
|
72
|
+
activity: wl.activity ?? '',
|
|
73
|
+
};
|
|
74
|
+
let entry;
|
|
75
|
+
try {
|
|
76
|
+
entry = wl.startDate === today && options.addEntryToday
|
|
77
|
+
? options.addEntryToday(input)
|
|
78
|
+
: importEntryOnDate(wl.startDate, input, config).entry;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
items.push(itemOf(wl, snapshot, err instanceof Error ? err.message : String(err)));
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// Baseline = raw remote fields: the diff sees parity, remoteChanged sees
|
|
85
|
+
// exactly what we adopted. Saved per entry — a mid-batch crash leaves an
|
|
86
|
+
// unowned twin that the next push re-adopts by content match.
|
|
87
|
+
pushLog[pushLogKey(wl.startDate, task, entry.id)] = {
|
|
88
|
+
tempoWorklogId: wl.tempoWorklogId,
|
|
89
|
+
timeSpentSeconds: wl.timeSpentSeconds,
|
|
90
|
+
pushedAt: new Date().toISOString(),
|
|
91
|
+
...(wl.description !== undefined ? { description: wl.description } : {}),
|
|
92
|
+
...(wl.activity !== undefined ? { activity: wl.activity } : {}),
|
|
93
|
+
};
|
|
94
|
+
savePushLog(pushLog);
|
|
95
|
+
items.push({ ...itemOf(wl, snapshot), task, entryId: entry.id });
|
|
96
|
+
}
|
|
97
|
+
items.sort((a, b) => a.date.localeCompare(b.date) || a.tempoWorklogId - b.tempoWorklogId);
|
|
98
|
+
return {
|
|
99
|
+
month: snapshot.month,
|
|
100
|
+
imported: items.filter(i => !i.error).length,
|
|
101
|
+
failed: items.filter(i => i.error).length,
|
|
102
|
+
items,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function itemOf(wl, snapshot, error) {
|
|
106
|
+
return {
|
|
107
|
+
tempoWorklogId: wl.tempoWorklogId,
|
|
108
|
+
date: wl.startDate,
|
|
109
|
+
task: snapshot.issueKeys?.[String(wl.issueId)] ?? `issue #${wl.issueId}`,
|
|
110
|
+
seconds: wl.timeSpentSeconds,
|
|
111
|
+
...(error !== undefined ? { error } : {}),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Full import pipeline: refetch the month snapshot (adopting from a stale
|
|
116
|
+
* mirror could resurrect a worklog just edited or deleted in Tempo), then
|
|
117
|
+
* adopt. Throws when the fetch itself fails — import is an online operation.
|
|
118
|
+
*/
|
|
119
|
+
export async function importTempoWorklogs(year, month, secrets, options) {
|
|
120
|
+
const snapshot = await fetchMonthSnapshot(year, month, secrets);
|
|
121
|
+
return { ...importFromSnapshot(snapshot, options), syncedAt: snapshot.fetchedAt };
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tempo-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tempo-import.js","sourceRoot":"","sources":["../../src/push/tempo-import.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workday-daemon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Lightweight activity tracker & timesheet tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"start": "node dist/daemon.js",
|
|
19
19
|
"cli": "tsx src/cli.ts",
|
|
20
|
-
"test": "tsx tests/unit/stamina-evidence.test.ts && tsx tests/unit/candidate-lifecycle.test.ts && tsx tests/unit/honest-session-end.test.ts && tsx tests/unit/gap-detection.test.ts && tsx tests/unit/janitor.test.ts && tsx tests/unit/stop-marker.test.ts && tsx tests/unit/report-clamp.test.ts && tsx tests/unit/update-manager.test.ts && tsx tests/unit/manual-entries.test.ts && tsx tests/unit/favorites.test.ts && tsx tests/unit/jira-search.test.ts && tsx tests/unit/day-start.test.ts && tsx tests/unit/push-plan.test.ts && tsx tests/unit/push-log.test.ts && tsx tests/unit/tempo-client.test.ts && tsx tests/unit/tempo-snapshot.test.ts && tsx tests/unit/month-report.test.ts && tsx tests/unit/day-edit.test.ts && tsx tests/integration/evidence-rebase.test.ts && tsx tests/integration/commit-ledger.test.ts",
|
|
20
|
+
"test": "tsx tests/unit/stamina-evidence.test.ts && tsx tests/unit/candidate-lifecycle.test.ts && tsx tests/unit/honest-session-end.test.ts && tsx tests/unit/gap-detection.test.ts && tsx tests/unit/janitor.test.ts && tsx tests/unit/stop-marker.test.ts && tsx tests/unit/report-clamp.test.ts && tsx tests/unit/update-manager.test.ts && tsx tests/unit/manual-entries.test.ts && tsx tests/unit/favorites.test.ts && tsx tests/unit/jira-search.test.ts && tsx tests/unit/day-start.test.ts && tsx tests/unit/push-plan.test.ts && tsx tests/unit/push-log.test.ts && tsx tests/unit/tempo-client.test.ts && tsx tests/unit/tempo-snapshot.test.ts && tsx tests/unit/tempo-import.test.ts && tsx tests/unit/month-report.test.ts && tsx tests/unit/day-edit.test.ts && tsx tests/integration/evidence-rebase.test.ts && tsx tests/integration/commit-ledger.test.ts",
|
|
21
21
|
"prepublishOnly": "npm run build"
|
|
22
22
|
},
|
|
23
23
|
"keywords": [
|