logwork-cli 0.0.0-stage → 1.0.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/LICENSE +11 -0
- package/README.md +287 -2
- package/RELEASE.md +89 -0
- package/bin/logwork.mjs +101 -0
- package/commands/auth.mjs +227 -0
- package/commands/delete.mjs +69 -0
- package/commands/doctor.mjs +24 -0
- package/commands/edit.mjs +88 -0
- package/commands/history.mjs +62 -0
- package/commands/query.mjs +52 -0
- package/commands/quick.mjs +163 -0
- package/commands/reconcile.mjs +55 -0
- package/commands/release.mjs +77 -0
- package/commands/reminder.mjs +172 -0
- package/commands/setup.mjs +504 -0
- package/commands/tui.mjs +50 -0
- package/commands/update.mjs +161 -0
- package/docs/advanced.md +334 -0
- package/docs/mcp-setup.md +347 -0
- package/docs/operations-guide.md +587 -0
- package/docs/recipes.md +259 -0
- package/docs/security.md +151 -0
- package/examples/mcp/antigravity.mcp_config.json +8 -0
- package/examples/mcp/codex.config.toml +5 -0
- package/examples/mcp/copilot.mcp.json +9 -0
- package/lib/api-auth.mjs +1259 -0
- package/lib/api.mjs +1422 -0
- package/lib/apply-ledger.mjs +227 -0
- package/lib/atomic-file.mjs +24 -0
- package/lib/auth-diagnostics.mjs +113 -0
- package/lib/auth-errors.mjs +22 -0
- package/lib/auth-redaction.mjs +78 -0
- package/lib/auth-terminal.mjs +97 -0
- package/lib/auth.mjs +323 -0
- package/lib/batch-parser.mjs +145 -0
- package/lib/batch-workflow.mjs +842 -0
- package/lib/config.mjs +191 -0
- package/lib/credential-store.mjs +130 -0
- package/lib/diagnostics.mjs +307 -0
- package/lib/entrypoint.mjs +14 -0
- package/lib/file-lock.mjs +44 -0
- package/lib/http.mjs +125 -0
- package/lib/jira-api.mjs +258 -0
- package/lib/jira-auth.mjs +203 -0
- package/lib/jira-workflow.mjs +523 -0
- package/lib/keychain.mjs +105 -0
- package/lib/legacy-migration.mjs +66 -0
- package/lib/list-navigation.mjs +19 -0
- package/lib/logwork-config.mjs +199 -0
- package/lib/logwork-f03-enrich.mjs +41 -0
- package/lib/macos.mjs +33 -0
- package/lib/manual-apply-state.mjs +35 -0
- package/lib/manual-commands.mjs +294 -0
- package/lib/manual-drafts.mjs +154 -0
- package/lib/manual-ink-app.mjs +1654 -0
- package/lib/manual-ink-auth.mjs +349 -0
- package/lib/manual-ink-ui.mjs +675 -0
- package/lib/manual-input.mjs +21 -0
- package/lib/manual-logwork-wizard.mjs +310 -0
- package/lib/manual-mcp.mjs +187 -0
- package/lib/manual-repl.mjs +1037 -0
- package/lib/manual-targets.mjs +78 -0
- package/lib/mcp-server.mjs +793 -0
- package/lib/os-notification.mjs +105 -0
- package/lib/package-info.mjs +17 -0
- package/lib/paths.mjs +68 -0
- package/lib/project-identity.mjs +66 -0
- package/lib/project-mapping-workflow.mjs +309 -0
- package/lib/project-resolver.mjs +373 -0
- package/lib/query-workflow.mjs +553 -0
- package/lib/reconciliation-workflow.mjs +446 -0
- package/lib/release-doctor.mjs +448 -0
- package/lib/reminder-config.mjs +71 -0
- package/lib/reminder-scheduler.mjs +301 -0
- package/lib/reminder-service.mjs +118 -0
- package/lib/reminder-state.mjs +38 -0
- package/lib/reminder-workflow.mjs +299 -0
- package/lib/ro-delete-args.mjs +38 -0
- package/lib/ro-delete-workflow.mjs +115 -0
- package/lib/ro-edit-args.mjs +142 -0
- package/lib/ro-edit-workflow.mjs +632 -0
- package/lib/ro-entry-reader.mjs +56 -0
- package/lib/ro-resubmit-workflow.mjs +134 -0
- package/lib/terminal-auth-prompts.mjs +120 -0
- package/lib/ui.mjs +133 -0
- package/lib/update-service.mjs +350 -0
- package/lib/util.mjs +66 -0
- package/lib/windows-credential-manager.mjs +260 -0
- package/lib/worklog-task-resolver.mjs +113 -0
- package/package.json +72 -4
- package/setup.sh +22 -0
|
@@ -0,0 +1,587 @@
|
|
|
1
|
+
# Integrated Operations Guide
|
|
2
|
+
|
|
3
|
+
This guide describes the complete Resource Optimiser and Jira workflow available through the terminal CLI and MCP server. It also covers project mapping, reconciliation, apply history, native reminders, self-update, and release checks.
|
|
4
|
+
|
|
5
|
+
## Initial Setup
|
|
6
|
+
|
|
7
|
+
Requirements:
|
|
8
|
+
|
|
9
|
+
- macOS or Windows 10/11.
|
|
10
|
+
- Node.js 22 or newer.
|
|
11
|
+
- npm.
|
|
12
|
+
- A Resource Optimiser account.
|
|
13
|
+
- A Jira Personal Access Token when Jira features are used.
|
|
14
|
+
|
|
15
|
+
Install and prepare the stable local runtime:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g logwork-cli
|
|
19
|
+
logwork setup
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Authenticate each target from Terminal:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
logwork login
|
|
26
|
+
logwork login jira
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Check both sessions without printing credentials:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
logwork status
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Upgrading from `logwork-helper`: see [Upgrading from logwork-helper](../README.md#upgrading-from-logwork-helper).
|
|
36
|
+
|
|
37
|
+
Resource Optimiser credentials and Jira PATs are never accepted by MCP tools. The final sessions are stored in macOS Keychain or Windows Credential Manager.
|
|
38
|
+
|
|
39
|
+
## Capability Map
|
|
40
|
+
|
|
41
|
+
| Operation | Terminal CLI | `logwork` UI | MCP tool | Writes external data |
|
|
42
|
+
| --- | --- | --- | --- | --- |
|
|
43
|
+
| Query RO | `logwork query` | `/query <period>` | `get_logwork` | No |
|
|
44
|
+
| Log RO | `logwork quick` (one entry) | `/logwork ro` | `log_work` | Apply call only |
|
|
45
|
+
| Edit existing RO entry | `logwork edit` | `/edit-logwork` | `edit_entry` | Apply call only |
|
|
46
|
+
| Resubmit rejected RO | - | - | `resubmit_entry` | Apply call only |
|
|
47
|
+
| Delete RO entry | `logwork delete` | - | `delete_entry` | Apply call only |
|
|
48
|
+
| Log Jira | - | `/logwork jira` | `log_jira_work` | Apply call only |
|
|
49
|
+
| Log Both | - | `/logwork both` | `log_work` + `log_jira_work` separately | Apply calls only |
|
|
50
|
+
| Project mapping | - | `/projects`, `/map` | `list_projects`, `map_project` | Local config only |
|
|
51
|
+
| RO worklog task catalog | - | - | `list_tasks` | No |
|
|
52
|
+
| Reconcile RO/Jira | `logwork reconcile` | `/reconcile` | `reconcile` | No |
|
|
53
|
+
| Apply history | `logwork history` | `/history` | `get_history` | No |
|
|
54
|
+
| Reminder | `logwork reminder` | - | `reminder` (`action`) | OS schedule only |
|
|
55
|
+
| Update | `logwork update` | Startup notice | `update` (`action`) | Local runtime only |
|
|
56
|
+
| Login | `logwork login\|logout\|status` | `/auth`, `/status` | `login` (explains terminal login) | OS credential store |
|
|
57
|
+
| Diagnostics | `logwork doctor` | `/diagnostics` | - | Local file only |
|
|
58
|
+
| Release preflight | `logwork release doctor` | - | - | No |
|
|
59
|
+
|
|
60
|
+
MCP writes are two calls to the same tool. The first call, without `confirm`, returns a preview with a `batchId` or `previewId`. The second call passes that id with `confirm: true`. An apply call that also carries content fields is rejected.
|
|
61
|
+
|
|
62
|
+
All apply, mapping, reminder configuration, reminder test, and update operations require explicit confirmation. Query, preview, reconciliation, history, status, and update check operations are read-only.
|
|
63
|
+
|
|
64
|
+
## Target Routing
|
|
65
|
+
|
|
66
|
+
### Resource Optimiser
|
|
67
|
+
|
|
68
|
+
Use the RO flow when the intent is Resource Optimiser logwork:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
/logwork ro
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
MCP uses:
|
|
75
|
+
|
|
76
|
+
1. `list_projects` and `list_tasks`, to choose a valid worklog task.
|
|
77
|
+
2. `log_work` with `text`, which returns the preview.
|
|
78
|
+
3. `log_work` with `batchId` and `confirm: true`, after approval.
|
|
79
|
+
|
|
80
|
+
RO resolves each task to a project using the approved preview override, local ticket/keyword mappings, booked projects, and available project memberships. Jira is not written by this flow.
|
|
81
|
+
|
|
82
|
+
Creating new RO logwork uses `POST /logwork/entries`. Every RO entry has two text parts:
|
|
83
|
+
|
|
84
|
+
- **Worklog task**: a catalog item from `GET /logwork/tasks` and `/logwork/tasks/defaults` for the matched project (for example `Feature Development`, `Code Review & Refactoring`). Sent as `worklog_task_id`.
|
|
85
|
+
- **Description**: free text describing the actual work (for example `Implement maintenance mode UI (SCB-213)`). Sent as `description`.
|
|
86
|
+
|
|
87
|
+
Write each line as `+<hours> <worklog task> | <description>`. The worklog task must match the RO catalog name exactly (case-insensitive) or be written as `#<id>`. A line without `|` is treated as a catalog task name when it matches one (no description is written and the preview warns); otherwise it becomes the description under MCP `defaultWorklogTask`, or the entry stays unresolved with reason `worklog_task_required` and `availableTaskNames`. **Worklog task** (catalog) is not the same as **type of work** (`create`, `correct`, `improve`, `other`) on the log entry.
|
|
88
|
+
|
|
89
|
+
New entries default to `type_of_work: other` when the matched catalog task has no `type_of_work`. When the RO task row defines `type_of_work`, preview copies it onto the entry unless MCP `typeOfWork` overrides the whole batch.
|
|
90
|
+
|
|
91
|
+
The optional `log_work` preview input `typeOfWork` applies to every line in the batch and overrides per-task catalog defaults.
|
|
92
|
+
|
|
93
|
+
The optional `log_work` preview input `defaultWorklogTask` (name or `#<id>`) supplies the worklog task for lines without `|` that are not catalog task names. The `batchId` includes this value and every description, so approval always covers the exact payload.
|
|
94
|
+
|
|
95
|
+
### Staff API surface (F03 vs legacy)
|
|
96
|
+
|
|
97
|
+
| Intent | HTTP | Used by helper |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| Create entry (approved) | `POST /logwork/entries` | `log_work`, `logwork quick` |
|
|
100
|
+
| List worklog tasks | `GET /logwork/tasks`, `/logwork/tasks/defaults` | Batch preview task resolution |
|
|
101
|
+
| Day view (status, lock) | `GET /logwork/day` | `get_logwork` entry enrichment, edit reads |
|
|
102
|
+
| Weekly summary | `GET /logwork/weekly` | Available in API client; booked hours still come from legacy timesheet |
|
|
103
|
+
| Rejected list | `GET /logwork/rejected` | Optional query enrichment (`includeRejected` when wired) |
|
|
104
|
+
| Resubmit rejected | `PATCH /logwork/entries/:id/resubmit` | `resubmit_entry` |
|
|
105
|
+
| Delete submitted/approved | `DELETE /logwork/entries/:id` | `delete_entry`, `logwork delete` |
|
|
106
|
+
| Booked + logged range | `GET /member-logtime/timesheet` | `get_logwork`, batch booked-project resolution |
|
|
107
|
+
| Day task detail | `GET /member-logtime` | `get_logwork` entry lines |
|
|
108
|
+
| Edit hours/task/type/description | `POST /logwork/entries` then `DELETE /logwork/entries/:id` (replace) | `edit_entry`, `logwork edit` |
|
|
109
|
+
|
|
110
|
+
RO F03 has no staff edit endpoint. `PATCH /logwork/pm/entries/:id/edit-approve` is PM-only, so the helper edits by replacing the entry. The legacy `PATCH /member-logtime` `update_data` is no longer used by the edit flow. It only changed the `task_name` text and never remapped `worklog_task_id` or `description`.
|
|
111
|
+
|
|
112
|
+
### Edit Existing Resource Optimiser Logwork
|
|
113
|
+
|
|
114
|
+
Use the logwork entry ID returned by an RO query:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
logwork edit 304032 --hours 0.5
|
|
118
|
+
logwork edit 304032 --task "Bug Fix" --desc "Fix date picker timezone (SAP-42)"
|
|
119
|
+
logwork edit 304032 --type improve
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The long forms `--task-name` and `--description` are also accepted. The terminal UI equivalent is:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
/edit-logwork 304032 --hours 0.5 --task Bug Fix --desc Fix date picker timezone (SAP-42)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
MCP uses two calls to `edit_entry`:
|
|
129
|
+
|
|
130
|
+
1. A preview call with `logworkId` and at least one of `hours`, `taskName` (catalog name or `#<id>`), `description`, or `typeOfWork`.
|
|
131
|
+
2. An apply call with the returned `previewId` and `confirm: true`.
|
|
132
|
+
|
|
133
|
+
How the edit is processed:
|
|
134
|
+
|
|
135
|
+
1. **Read.** The legacy `GET /member-logtime/:id` returns the date, owner, and Jira link. `GET /logwork/day?date=` returns the F03 fields: status, `worklog_task_id`, `type_of_work`, and `description`. The project-member list maps `project_member_id` to `project_id`.
|
|
136
|
+
2. **Resolve.** The worklog task is resolved against `GET /logwork/tasks` plus `/logwork/tasks/defaults` for the project. When the task changes and `typeOfWork` is omitted, the new task's catalog `type_of_work` is used. Otherwise the current type is kept.
|
|
137
|
+
3. **Apply.** It re-checks the original revision, then:
|
|
138
|
+
- creates the corrected entry with `POST /logwork/entries`;
|
|
139
|
+
- deletes the original with `DELETE /logwork/entries/:id`;
|
|
140
|
+
- verifies the new entry.
|
|
141
|
+
|
|
142
|
+
If the create fails, nothing changed. If the delete fails, the new entry is deleted again (rollback). If that rollback also fails, the error names both ids.
|
|
143
|
+
|
|
144
|
+
If the create response has no id, the new entry is looked up in `/logwork/day`. If it still can't be found, the original is **not** deleted.
|
|
145
|
+
|
|
146
|
+
Deleting needs no PM approval and the new entry is approved immediately, so the edit takes effect at once. The `is_locked: true` flag RO puts on approved entries does not block the delete. Only a locked day (`isLocked` from `/logwork/day`) blocks an edit. The result returns `originalLogworkId` and `newLogworkId`. Project and date never change.
|
|
147
|
+
|
|
148
|
+
These entries are blocked:
|
|
149
|
+
- rejected entries (use resubmit),
|
|
150
|
+
- entries on locked days,
|
|
151
|
+
- entries owned by another user,
|
|
152
|
+
- entries created by Jira.
|
|
153
|
+
|
|
154
|
+
In dry run (`LOGWORK_DRY_RUN=1`), apply returns both requests without writing.
|
|
155
|
+
|
|
156
|
+
### Delete mistaken Resource Optimiser logwork
|
|
157
|
+
|
|
158
|
+
Use the entry ID from `logwork query`, `get_logwork`, or the RO UI. Only **submitted** or **approved** entries can be soft-deleted. **Rejected** entries must be resubmitted instead (`resubmit_entry`). Deleting needs no PM approval.
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
logwork delete 290364
|
|
162
|
+
logwork delete 290364 --yes --json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
MCP uses two calls to `delete_entry`:
|
|
166
|
+
|
|
167
|
+
1. A preview call with `logworkId`.
|
|
168
|
+
2. An apply call with the returned `previewId` and `confirm: true`.
|
|
169
|
+
|
|
170
|
+
The apply call re-checks the entry revision before sending `DELETE`.
|
|
171
|
+
|
|
172
|
+
The API call is `DELETE /logwork/entries/:id` (soft-delete via `deleted_date`).
|
|
173
|
+
|
|
174
|
+
### Jira
|
|
175
|
+
|
|
176
|
+
Use the Jira flow when the intent is a Jira worklog:
|
|
177
|
+
|
|
178
|
+
```text
|
|
179
|
+
/logwork jira
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
MCP uses:
|
|
183
|
+
|
|
184
|
+
1. `log_jira_work` with `text`, which returns the preview.
|
|
185
|
+
2. `log_jira_work` with `batchId` and `confirm: true`, after approval.
|
|
186
|
+
|
|
187
|
+
Every entry must contain exactly one Jira issue key. RO is not written by this flow.
|
|
188
|
+
|
|
189
|
+
### Both
|
|
190
|
+
|
|
191
|
+
Use the combined terminal flow when the same date/tasks should be sent to both systems:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
/logwork both
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The flow creates two independent previews and requests two approvals:
|
|
198
|
+
|
|
199
|
+
1. Preview and optionally apply Resource Optimiser.
|
|
200
|
+
2. Preview and optionally apply Jira.
|
|
201
|
+
|
|
202
|
+
The operation is not atomic. If RO succeeds and Jira fails, RO is not rolled back. Apply history records the result of each target with `flowTarget: both` so partial outcomes remain visible.
|
|
203
|
+
|
|
204
|
+
MCP has no unified Both tool. The assistant previews with both `log_work` and `log_jira_work`, presents both summaries, and requests approval for each apply separately.
|
|
205
|
+
|
|
206
|
+
## Input Format
|
|
207
|
+
|
|
208
|
+
MCP and pasted weekly text use date headings followed by one task per line:
|
|
209
|
+
|
|
210
|
+
```text
|
|
211
|
+
Monday, 13 Jul 2026
|
|
212
|
+
+2 Feature Development | Maintenance mode management (SCB-213)
|
|
213
|
+
+1 Feature Development | Update system page (SCB-214)
|
|
214
|
+
Tuesday, 14 Jul 2026
|
|
215
|
+
+1.5 Bug Fix | Fix password reset regression (SCB-215)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Rules:
|
|
219
|
+
|
|
220
|
+
- A date heading uses `Weekday, DD Mon YYYY`.
|
|
221
|
+
- A task uses `+<hours> <worklog task> | <description>`. Only the first `|` splits the line.
|
|
222
|
+
- For RO, `<worklog task>` must be an RO catalog task (`list_tasks`) and `<description>` is stored as the entry description.
|
|
223
|
+
- For Jira, `<worklog task>` is ignored and `<description>` becomes the worklog comment. Lines without `|` use the whole text.
|
|
224
|
+
- Hours must be greater than zero and may be decimal.
|
|
225
|
+
- RO can accept entries without a Jira issue key when a project can still be resolved.
|
|
226
|
+
- Jira requires exactly one key such as `SCB-213` in every entry.
|
|
227
|
+
- Jira blocks entries with no key or multiple keys.
|
|
228
|
+
|
|
229
|
+
The terminal wizard selects one date for the current session. It accepts the same task line format without requiring a pasted date heading.
|
|
230
|
+
|
|
231
|
+
## Resource Optimiser Processing Example
|
|
232
|
+
|
|
233
|
+
Input:
|
|
234
|
+
|
|
235
|
+
```text
|
|
236
|
+
Monday, 13 Jul 2026
|
|
237
|
+
+2 Feature Development | Maintenance mode management (SCB-213)
|
|
238
|
+
+1 Feature Development | Update system page (SCB-214)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Processing:
|
|
242
|
+
|
|
243
|
+
1. Parse the date, hours, worklog task, description, and issue keys.
|
|
244
|
+
2. Load booked RO projects and project memberships for the date.
|
|
245
|
+
3. Apply user/project ticket and keyword mappings (matched against the whole line).
|
|
246
|
+
4. Resolve the worklog task in the project catalog and attach `worklogTaskId` and `description`.
|
|
247
|
+
5. Mark each entry as resolved, resolved but unbooked, or unresolved.
|
|
248
|
+
6. Return an approval summary. No work is submitted during preview.
|
|
249
|
+
|
|
250
|
+
Illustrative ready preview:
|
|
251
|
+
|
|
252
|
+
```text
|
|
253
|
+
Logwork preview:
|
|
254
|
+
- 2026-07-13: +2h 2621A-SIT-HTML BUILDER-PRJ - Feature Development | Maintenance mode management (SCB-213) (via config_ticket, confidence 1)
|
|
255
|
+
- 2026-07-13: +1h 2621A-SIT-HTML BUILDER-PRJ - Feature Development | Update system page (SCB-214) (via config_ticket, confidence 1)
|
|
256
|
+
Approval checklist: 2 entries, 3h total, 2026-07-13.
|
|
257
|
+
Projects: 2621A-SIT-HTML BUILDER-PRJ: 3h.
|
|
258
|
+
Ready to apply.
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
After explicit approval, the apply result is similar to:
|
|
262
|
+
|
|
263
|
+
```text
|
|
264
|
+
Logwork submitted:
|
|
265
|
+
Submitted 2 entries, 3h total.
|
|
266
|
+
- 2026-07-13: +2h 2621A-SIT-HTML BUILDER-PRJ - Feature Development | Maintenance mode management (SCB-213)
|
|
267
|
+
- 2026-07-13: +1h 2621A-SIT-HTML BUILDER-PRJ - Feature Development | Update system page (SCB-214)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
If a valid membership is not booked for the selected date, preview prefixes the entry with `UNBOOKED`. Applying it requires a second decision through `allowUnbooked: true`. An unresolved project always blocks apply.
|
|
271
|
+
|
|
272
|
+
## Jira Processing Example
|
|
273
|
+
|
|
274
|
+
For each entry, Jira preview:
|
|
275
|
+
|
|
276
|
+
1. Extracts exactly one issue key.
|
|
277
|
+
2. Calls Jira to validate issue existence and access.
|
|
278
|
+
3. Loads existing issue worklogs.
|
|
279
|
+
4. Blocks duplicates by helper marker or by matching issue, date, duration, and normalized task comment.
|
|
280
|
+
5. Builds and stores the exact approved payload.
|
|
281
|
+
|
|
282
|
+
Illustrative ready preview:
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
Jira worklog preview: ready. 2 entries, 3h total.
|
|
286
|
+
Counts: ready 2, duplicate 0, missing ticket 0, multiple tickets 0, lookup failed 0.
|
|
287
|
+
- 2026-07-13: +2h SCB-213 - Maintenance mode management (SCB-213) -> ready
|
|
288
|
+
Issue: Maintenance mode management [In Progress]
|
|
289
|
+
Started: 2026-07-13T09:00:00.000+0700
|
|
290
|
+
Comment: Maintenance mode management (SCB-213) | #lh:8f3a91c0
|
|
291
|
+
- 2026-07-13: +1h SCB-214 - Update system page (SCB-214) -> ready
|
|
292
|
+
Issue: System page update [To Do]
|
|
293
|
+
Started: 2026-07-13T09:00:00.000+0700
|
|
294
|
+
Comment: Update system page (SCB-214) | #lh:9b18d721
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The marker hashes above are examples. The real hash is generated from the approved batch and entry identifiers.
|
|
298
|
+
|
|
299
|
+
The Jira REST payload for the first entry is equivalent to:
|
|
300
|
+
|
|
301
|
+
```json
|
|
302
|
+
{
|
|
303
|
+
"started": "2026-07-13T09:00:00.000+0700",
|
|
304
|
+
"timeSpentSeconds": 7200,
|
|
305
|
+
"comment": "Maintenance mode management (SCB-213)\n\n#lh:8f3a91c0"
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The request uses `adjustEstimate=leave`, so Jira remaining estimate is not changed. The default started time is 09:00 in `Asia/Ho_Chi_Minh`; it can be configured with `LOGWORK_JIRA_STARTED_TIME` and `LOGWORK_TIMEZONE`.
|
|
310
|
+
|
|
311
|
+
After approval, Jira reports each entry independently:
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
Jira worklog apply: submitted 2, failed 0.
|
|
315
|
+
- 2026-07-13: SCB-213 +2h -> submitted
|
|
316
|
+
- 2026-07-13: SCB-214 +1h -> submitted
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
In Jira, the issue worklog displays the current Jira user, logged duration, started date/time, and the comment on two lines:
|
|
320
|
+
|
|
321
|
+
```text
|
|
322
|
+
Maintenance mode management (SCB-213)
|
|
323
|
+
|
|
324
|
+
#lh:8f3a91c0
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
The shorter `#lh:<hash>` marker replaces the old visible `[logwork-helper:...]` format from earlier versions. Existing worklogs with the legacy marker are still recognized during duplicate checks.
|
|
328
|
+
|
|
329
|
+
## Duplicate And Preview Safety
|
|
330
|
+
|
|
331
|
+
RO and Jira MCP previews are cached for one hour, with at most 100 previews per target, and are lost when the server restarts. Apply requires the cached `batchId` or `previewId`. A missing, expired, consumed, or modified preview must be generated again.
|
|
332
|
+
|
|
333
|
+
Jira duplicate detection is blocking and has no override. Apply rechecks worklogs immediately before the first write. If a duplicate appears after preview, the Jira batch is blocked before submission.
|
|
334
|
+
|
|
335
|
+
If a Jira API write fails after earlier entries were submitted, processing stops and the result identifies the submitted entries and the failed entry. Remaining entries are not attempted. The helper never reports a partial batch as fully successful.
|
|
336
|
+
|
|
337
|
+
## Project Mapping And Similar Content
|
|
338
|
+
|
|
339
|
+
RO project mapping can use:
|
|
340
|
+
|
|
341
|
+
- Jira ticket prefixes, for example `SCB`.
|
|
342
|
+
- Task keywords, for example `maintenance mode`.
|
|
343
|
+
- Explicit project selection during preview.
|
|
344
|
+
- Jira project key/name metadata in the terminal Both flow to rank RO memberships.
|
|
345
|
+
|
|
346
|
+
Example MCP sequence:
|
|
347
|
+
|
|
348
|
+
1. `get_jira_issue` reads `SCB-213` metadata.
|
|
349
|
+
2. `list_projects` lists valid RO memberships.
|
|
350
|
+
3. The assistant compares Jira project metadata and task wording with RO project names/mappings.
|
|
351
|
+
4. The assistant shows the proposed project and asks for approval.
|
|
352
|
+
5. `map_project` stores the selected ticket/keyword mapping with `confirm: true`.
|
|
353
|
+
6. The assistant reruns RO preview.
|
|
354
|
+
|
|
355
|
+
Example mapping:
|
|
356
|
+
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"projectMappings": [
|
|
360
|
+
{
|
|
361
|
+
"projectName": "2621A-SIT-HTML BUILDER-PRJ",
|
|
362
|
+
"projectMemberId": 5234,
|
|
363
|
+
"tickets": ["SCB"],
|
|
364
|
+
"keywords": ["maintenance mode", "system page"]
|
|
365
|
+
}
|
|
366
|
+
]
|
|
367
|
+
}
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
Content similarity is a suggestion, not an automatic write. The built-in Both flow ranks exact/contained Jira project names, Jira project keys, and meaningful name-token overlap. An MCP assistant can also reason over issue/task text, but it must choose from real RO memberships and obtain confirmation before saving a mapping.
|
|
371
|
+
|
|
372
|
+
## Reconciliation
|
|
373
|
+
|
|
374
|
+
Reconciliation compares RO and Jira without writing either system:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
logwork reconcile this-week
|
|
378
|
+
logwork reconcile last-month --json
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
Supported periods are `today`, `yesterday`, `this-week`, `last-week`, `this-month`, and `last-month`. Custom date inputs are intentionally not supported. The displayed `to` date is the exclusive end of the queried range.
|
|
382
|
+
|
|
383
|
+
Example summary:
|
|
384
|
+
|
|
385
|
+
```text
|
|
386
|
+
RO / Jira reconciliation: this week (2026-07-13 to 2026-07-20).
|
|
387
|
+
|
|
388
|
+
Date Booked RO Jira Diff Status
|
|
389
|
+
2026-07-13 8h 7h 6h -1h Task mismatch
|
|
390
|
+
2026-07-14 8h 8h 8h 0h Matched
|
|
391
|
+
|
|
392
|
+
Total: booked 16h, RO 15h, Jira 14h, difference -1h.
|
|
393
|
+
Days: matched 1, mismatched 1, incomplete 0, unverified 0.
|
|
394
|
+
|
|
395
|
+
High-confidence correction suggestions:
|
|
396
|
+
- 2026-07-13: JIRA +1h SCB-214 - Update system page (SCB-214)
|
|
397
|
+
Create a normal target-specific preview before applying any suggestion.
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
A correction suggestion is generated only when task-level evidence is strong, including exactly one Jira issue key. It is never applied directly. Use the normal target preview and approval flow.
|
|
401
|
+
|
|
402
|
+
## Apply History
|
|
403
|
+
|
|
404
|
+
RO and Jira workflow apply outcomes, including submitted, partial, failed, and preview-blocked batches, record a sanitized local result:
|
|
405
|
+
|
|
406
|
+
```bash
|
|
407
|
+
logwork history
|
|
408
|
+
logwork history --target jira --limit 10
|
|
409
|
+
logwork history --target both --json
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
|
|
414
|
+
```text
|
|
415
|
+
Apply history: 2 records.
|
|
416
|
+
- 2026-07-15T13:10:00.000Z: jira via both submitted, batch jira_abcd, submitted 2, failed 0, blocked 0, 3h.
|
|
417
|
+
- 2026-07-15T13:09:00.000Z: ro via both submitted, batch batch_efgh, submitted 2, failed 0, blocked 0, 3h.
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
The ledger stores sanitized task/project/issue/result metadata. It does not store tokens, cookies, raw API responses, passwords, or OTPs.
|
|
421
|
+
|
|
422
|
+
## Native OS Reminder
|
|
423
|
+
|
|
424
|
+
Enable the default Both reminder at 17:00, Monday-Friday:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
logwork reminder enable
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Other operations:
|
|
431
|
+
|
|
432
|
+
```bash
|
|
433
|
+
logwork reminder enable --time 18:00 --target ro
|
|
434
|
+
logwork reminder status
|
|
435
|
+
logwork reminder test
|
|
436
|
+
logwork reminder disable
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Behavior:
|
|
440
|
+
|
|
441
|
+
- RO compares today's logged hours with booked hours.
|
|
442
|
+
- Jira checks whether the current Jira user has any worklog today.
|
|
443
|
+
- A complete day stays silent.
|
|
444
|
+
- At most one notification is sent per configured workday.
|
|
445
|
+
- Missing auth produces an actionable notification without exposing API details.
|
|
446
|
+
- macOS uses a user `launchd` agent (`sg.vinova.logwork-cli.reminder`).
|
|
447
|
+
- Windows uses an interactive user Task Scheduler task (`Logwork Reminder`).
|
|
448
|
+
- The scheduler runs `node ~/.logwork-cli/bin/logwork.mjs reminder run --home ~/.logwork-cli`.
|
|
449
|
+
- Enabling or disabling the reminder also removes a leftover `logwork-helper` schedule.
|
|
450
|
+
|
|
451
|
+
Example Both notification:
|
|
452
|
+
|
|
453
|
+
```text
|
|
454
|
+
Logwork hôm nay chưa hoàn tất
|
|
455
|
+
RO: 6/8h, còn thiếu 2h
|
|
456
|
+
Jira: chưa có worklog hôm nay
|
|
457
|
+
|
|
458
|
+
Mở Terminal và chạy: logwork
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The notification text is localized in Vietnamese. The OS schedule stores only fixed Node/script paths and reads credentials from the OS credential store when it runs.
|
|
462
|
+
|
|
463
|
+
## End-User Updates
|
|
464
|
+
|
|
465
|
+
Check the running version against npm latest:
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
logwork update check
|
|
469
|
+
logwork update check --force
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Install after confirmation:
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
logwork update install
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
For a non-interactive terminal, approve the exact published version:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
logwork update install --version 0.1.11 --yes
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
The updater:
|
|
485
|
+
|
|
486
|
+
- Uses npm's official registry.
|
|
487
|
+
- Accepts only the package's current `latest` SemVer.
|
|
488
|
+
- Rechecks npm immediately before installation.
|
|
489
|
+
- Copies and verifies the stable local MCP runtime.
|
|
490
|
+
- Preserves credentials, mappings, drafts, history, and reminder config.
|
|
491
|
+
|
|
492
|
+
Restart the terminal and reconnect MCP after a successful update. MCP exposes the same process through `update` with `action: "check"`, then `action: "install"` with `confirm: true`.
|
|
493
|
+
|
|
494
|
+
## Maintainer Release Flow
|
|
495
|
+
|
|
496
|
+
Update both `package.json` and `package-lock.json` with npm:
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
npm version patch --no-git-tag-version
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Use `minor` or `major` instead of `patch` when required by SemVer. Then run:
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
npm run release:check
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Commit and sync the version change so the release doctor can verify a clean `main`:
|
|
509
|
+
|
|
510
|
+
```bash
|
|
511
|
+
git add package.json package-lock.json
|
|
512
|
+
git commit -m "bump version to <version>"
|
|
513
|
+
git push origin main
|
|
514
|
+
logwork release doctor --full
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
After the release doctor passes:
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
npm publish --access public
|
|
521
|
+
git tag v<version>
|
|
522
|
+
git push origin v<version>
|
|
523
|
+
gh release create v<version> --generate-notes --title "v<version>"
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
The release doctor checks package version consistency, self-dependencies, clean/synced `main`, npm registry/auth/latest, GitHub auth, tag/release state, tarball artifacts, tests, production audit, package dry run, and whitespace.
|
|
527
|
+
|
|
528
|
+
## Local State And Credentials
|
|
529
|
+
|
|
530
|
+
| State | macOS/Windows helper-home filename | Sensitive credentials |
|
|
531
|
+
| --- | --- | --- |
|
|
532
|
+
| Installed runtime | `.logwork-cli/` | No |
|
|
533
|
+
| User project mappings | `.logwork-cli/.logwork.json` | No |
|
|
534
|
+
| Manual drafts | `.logwork-cli/manual-drafts.json` | No |
|
|
535
|
+
| Apply history | `.logwork-cli/apply-ledger.json` | No |
|
|
536
|
+
| Update cache | `.logwork-cli/update-state.json` | No |
|
|
537
|
+
| Reminder config/state | `.logwork-cli/reminder.json`, `.logwork-cli/reminder-state.json` | No |
|
|
538
|
+
| RO/Jira sessions | OS credential store, service `logwork-cli` | Yes |
|
|
539
|
+
|
|
540
|
+
The helper home is `~/.logwork-cli` on macOS and `%USERPROFILE%\.logwork-cli` on Windows. `LOGWORK_HOME` overrides it; the older `LOGWORK_HELPER_HOME` is still honored.
|
|
541
|
+
|
|
542
|
+
Migration from `logwork-helper` happens on the first run, unless `LOGWORK_HOME` (or `LOGWORK_HELPER_HOME`) is set:
|
|
543
|
+
- State files are copied once from `~/.logwork-helper`, and `.logwork-helper.json` is renamed to `.logwork.json` on the way. The old directory is left in place. A marker file (`.migrated-from-logwork-helper`) records the copy.
|
|
544
|
+
- Credentials still stored under the old service name (`logwork-helper`) are read once and copied to `logwork-cli`.
|
|
545
|
+
- Logging out clears both credential entries.
|
|
546
|
+
|
|
547
|
+
## Validation
|
|
548
|
+
|
|
549
|
+
Run the cross-platform suite:
|
|
550
|
+
|
|
551
|
+
```bash
|
|
552
|
+
npm test
|
|
553
|
+
git diff --check
|
|
554
|
+
npm pack --dry-run
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
Windows CI additionally runs a real Credential Manager lifecycle test:
|
|
558
|
+
|
|
559
|
+
```powershell
|
|
560
|
+
npm run test:windows-credential
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
That integration test stores, reads, and deletes a dedicated test credential. On non-Windows systems it is skipped by design.
|
|
564
|
+
|
|
565
|
+
Recommended end-user checks after installation:
|
|
566
|
+
|
|
567
|
+
1. Run `logwork --version` and `logwork update check --force`.
|
|
568
|
+
2. Run `logwork status`.
|
|
569
|
+
3. Open `logwork` and preview one RO task without applying.
|
|
570
|
+
4. Preview one Jira task with exactly one issue key without applying.
|
|
571
|
+
5. Run `logwork reconcile this-week`.
|
|
572
|
+
6. Run `logwork reminder test`, verify the native notification, then inspect `reminder status`.
|
|
573
|
+
7. Connect MCP and verify the tool list before testing read-only queries.
|
|
574
|
+
|
|
575
|
+
## Recovery Rules
|
|
576
|
+
|
|
577
|
+
- Missing RO auth: run `logwork login`.
|
|
578
|
+
- Missing Jira auth: run `logwork login jira`.
|
|
579
|
+
- Unresolved RO project: list memberships, confirm a mapping, and preview again.
|
|
580
|
+
- Jira duplicate: inspect the existing worklog; there is no override.
|
|
581
|
+
- Expired or consumed preview: preview again and request approval again.
|
|
582
|
+
- Partial Both result: inspect `/history both`, then preview only the missing target.
|
|
583
|
+
- npm `E401`: refresh npm login with `npm login --registry=https://registry.npmjs.org/`.
|
|
584
|
+
- Reminder config/scheduler mismatch: rerun `reminder enable` or `reminder disable`.
|
|
585
|
+
- MCP after update: restart or reload the MCP connection.
|
|
586
|
+
|
|
587
|
+
For client configuration details, see [MCP setup](mcp-setup.md). For security boundaries and stored-data details, see [Security and auth](security.md). For copy-ready task recipes, see [Quick recipes](recipes.md).
|