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
package/LICENSE
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Truc Tran and contributors.
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
This project is proprietary and is not open source. Use, copying,
|
|
7
|
+
modification, distribution, publication, sublicensing, or sale of this
|
|
8
|
+
software or its documentation is permitted only with prior written permission
|
|
9
|
+
from the copyright holder or under a separate written agreement.
|
|
10
|
+
|
|
11
|
+
No license is granted by implication, estoppel, or otherwise.
|
package/README.md
CHANGED
|
@@ -1,3 +1,288 @@
|
|
|
1
|
-
#
|
|
1
|
+
# logwork-cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[npm version](https://www.npmjs.com/package/logwork-cli)
|
|
4
|
+
[license](LICENSE)
|
|
5
|
+
|
|
6
|
+
Log work to Resource Optimiser (RO) and self-hosted Jira from the terminal, from an MCP server for AI IDEs, or from a terminal UI.
|
|
7
|
+
|
|
8
|
+
One command, `logwork`, covers everything:
|
|
9
|
+
|
|
10
|
+
- `logwork`: the terminal UI.
|
|
11
|
+
- `logwork <command>`: one-shot commands such as `logwork query this-week` or `logwork edit 304032 --task "Bug Fix"`.
|
|
12
|
+
- `logwork mcp`: the MCP server that Cursor, Codex, Google Antigravity, GitHub Copilot / VS Code and Claude Code connect to.
|
|
13
|
+
|
|
14
|
+
Credentials stay local. Resource Optimiser passwords and 2FA codes, and Jira Personal Access Tokens, are entered in the terminal only. They never go into MCP config or AI chat.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
Requirements: macOS or Windows 10/11, Node.js 22+, npm.
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install -g logwork-cli
|
|
22
|
+
logwork setup
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`logwork setup` does the following:
|
|
26
|
+
- installs the runtime to `~/.logwork-cli` (`%USERPROFILE%\.logwork-cli` on Windows),
|
|
27
|
+
- links the `logwork` command,
|
|
28
|
+
- offers to log in,
|
|
29
|
+
- prints copy-ready MCP configs that use your real local path.
|
|
30
|
+
|
|
31
|
+
## Upgrading from logwork-helper
|
|
32
|
+
|
|
33
|
+
The package was renamed from `logwork-helper` to `logwork-cli`, and the `logwork-helper` command no longer exists. To upgrade:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install -g logwork-cli
|
|
37
|
+
logwork setup
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Most of the move is automatic:
|
|
41
|
+
|
|
42
|
+
- **Old global package:** `logwork setup` removes the global `logwork-helper` package, so its `logwork` command does not conflict with the new one.
|
|
43
|
+
- **Local state:** on the first run, settings, project mappings, drafts, apply history and the reminder config are copied from `~/.logwork-helper` to `~/.logwork-cli`. The old directory is left in place.
|
|
44
|
+
- **Login sessions:** your RO and Jira sessions are copied from the old Keychain / Credential Manager entry (`logwork-helper`) to the new one (`logwork-cli`), so you do not need to log in again.
|
|
45
|
+
- **Repo mappings:** a repo that has `.logwork-helper.json` keeps using it until a `.logwork.json` exists.
|
|
46
|
+
- **Reminder:** an enabled reminder is re-registered by `logwork setup`, and the old OS schedule is removed.
|
|
47
|
+
|
|
48
|
+
Two things you need to do yourself:
|
|
49
|
+
|
|
50
|
+
- **IDE config:** replace the old `logwork-helper` MCP entry with the new `logwork` entry printed by `logwork setup` or `/mcp`.
|
|
51
|
+
- **MCP tool names:** the tool names changed. See the [old → new tool name table](docs/mcp-setup.md#tool-name-changes-from-logwork-helper).
|
|
52
|
+
|
|
53
|
+
## Log In
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
logwork login # Resource Optimiser: email, password, 2FA in this terminal
|
|
57
|
+
logwork login jira # Jira Personal Access Token
|
|
58
|
+
logwork login jira --base-url https://jira.example.com
|
|
59
|
+
logwork status # RO and Jira status, never prints tokens
|
|
60
|
+
logwork logout [ro|jira]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Sessions are stored in macOS Keychain or Windows Credential Manager. The default Jira URL is `https://jira-vnv.vinova.sg`.
|
|
64
|
+
|
|
65
|
+
## Commands
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
logwork Open the terminal UI
|
|
69
|
+
logwork query [period] Booked vs logged hours with entry ids (today, yesterday, this-week, last-week, this-month, last-month)
|
|
70
|
+
logwork quick [-m text] Log one entry for today with guided prompts
|
|
71
|
+
logwork edit <id> ... Change an existing RO entry (replaces it)
|
|
72
|
+
logwork delete <id> Delete a submitted or approved RO entry
|
|
73
|
+
logwork reconcile Compare RO and Jira hours by day (read-only)
|
|
74
|
+
logwork history Local apply history
|
|
75
|
+
logwork login|logout|status [ro|jira]
|
|
76
|
+
logwork setup Install the runtime and print MCP configs
|
|
77
|
+
logwork mcp Run the MCP stdio server (used by IDE configs)
|
|
78
|
+
logwork reminder ... Weekday logwork reminder
|
|
79
|
+
logwork update ... Check for or install a new version
|
|
80
|
+
logwork doctor Write a sanitized diagnostics report
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Add `--help` to any command for its options.
|
|
84
|
+
|
|
85
|
+
## Logwork Line Format
|
|
86
|
+
|
|
87
|
+
Every Resource Optimiser entry has a **worklog task** and a free-text **description**. The worklog task is an RO catalog item such as `Feature Development` or `Code Review & Refactoring`. Write each line as:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
Monday, 01 Jun 2026
|
|
91
|
+
+2 Feature Development | Implement maintenance mode management and status UI (SCB-213)
|
|
92
|
+
+1 Code Review & Refactoring | Review system page PR (SCB-214)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- **Before `|`:** the RO worklog task name, or `#<id>`. MCP clients can list valid names with `list_tasks`.
|
|
96
|
+
- **After `|`:** the description saved on the RO entry. Jira uses it as the worklog comment.
|
|
97
|
+
- **Lines without `|`:** these still work in two cases. If the whole text is a catalog task name, the entry is saved with no description and a warning. If the assistant passes `defaultWorklogTask`, that task is used and the text becomes the description.
|
|
98
|
+
|
|
99
|
+
The default tasks shared by all projects are:
|
|
100
|
+
|
|
101
|
+
| id | Task | type_of_work |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| 71 | Feature Development | create |
|
|
104
|
+
| 74 | Bug Fix | correct |
|
|
105
|
+
| 182 | Code Review & Refactoring | improve |
|
|
106
|
+
| 79 | Deployment & Release | create |
|
|
107
|
+
| 181 | Requirements & Design | create |
|
|
108
|
+
| 183 | Testing Activities | create |
|
|
109
|
+
| 111 | Other Activities | other |
|
|
110
|
+
|
|
111
|
+
## API Notes
|
|
112
|
+
|
|
113
|
+
- Read bookings: `GET /member-logtime/timesheet`
|
|
114
|
+
- Read worklog tasks: `GET /logwork/tasks?project_id=<id>` and `GET /logwork/tasks/defaults?project_id=<id>`
|
|
115
|
+
- Write an entry: `POST /logwork/entries`
|
|
116
|
+
- Delete an entry: `DELETE /logwork/entries/:id`
|
|
117
|
+
- Resubmit a rejected entry: `PATCH /logwork/entries/:id/resubmit`
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"worklog_task_id": 71,
|
|
122
|
+
"type_of_work": "create",
|
|
123
|
+
"effort_hours": 2,
|
|
124
|
+
"logdate": "2026-06-01",
|
|
125
|
+
"project_id": 720,
|
|
126
|
+
"description": "Implement maintenance mode management and status UI (SCB-213)"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`project_id` is sent only when the worklog task is a shared default task.
|
|
131
|
+
|
|
132
|
+
## Set Up MCP
|
|
133
|
+
|
|
134
|
+
`logwork setup` prints the configs. You can also open the terminal UI with `logwork` and type `/mcp` (or `/mcp cursor`, `/mcp antigravity`, `/mcp copilot`, `/mcp claude-code`, `/mcp codex`).
|
|
135
|
+
|
|
136
|
+
Every client runs the same thing, `node ~/.logwork-cli/bin/logwork.mjs mcp`, under the server name `logwork`:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"mcpServers": {
|
|
141
|
+
"logwork": {
|
|
142
|
+
"command": "node",
|
|
143
|
+
"args": ["/Users/you/.logwork-cli/bin/logwork.mjs", "mcp"]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For Claude Code, run:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
claude mcp add --transport stdio logwork -- node ~/.logwork-cli/bin/logwork.mjs mcp
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Restart or reload the IDE's MCP tools after saving.
|
|
156
|
+
|
|
157
|
+
The server exposes 15 tools. It also sends `instructions` covering the approval rules, the line format and the recommended call order. Every write is **two calls to the same tool**:
|
|
158
|
+
1. Call the tool without `confirm`. It returns a preview with a `batchId` or `previewId` and a summary.
|
|
159
|
+
2. After the user approves, call the same tool again with only that id and `confirm: true`.
|
|
160
|
+
|
|
161
|
+
See [docs/mcp-setup.md](docs/mcp-setup.md#exposed-tools) for the tool table.
|
|
162
|
+
|
|
163
|
+
Verify from your assistant:
|
|
164
|
+
|
|
165
|
+
```text
|
|
166
|
+
Check my logwork for this week.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Edit Existing RO Logwork
|
|
170
|
+
|
|
171
|
+
Get the entry id from `logwork query` (or `get_logwork` in MCP), then:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
logwork edit 304032 --hours 0.5
|
|
175
|
+
logwork edit 304032 --desc "Fix date picker timezone (SAP-42)"
|
|
176
|
+
logwork edit 304032 --task "Bug Fix" --desc "Fix date picker timezone (SAP-42)"
|
|
177
|
+
logwork edit 304032 --task "#74" --type correct
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Options:
|
|
181
|
+
- `--hours`
|
|
182
|
+
- `--task`: a worklog task from the project catalog, or `#<id>`.
|
|
183
|
+
- `--desc`
|
|
184
|
+
- `--type`: `create`, `correct`, `improve` or `other`. When the task changes and `--type` is omitted, the new task's catalog type is used.
|
|
185
|
+
|
|
186
|
+
The long forms `--task-name` and `--description` also work. Project and date are always preserved.
|
|
187
|
+
|
|
188
|
+
Resource Optimiser has no staff API for editing an entry; the edit endpoint is PM-only. So apply **replaces** the entry:
|
|
189
|
+
|
|
190
|
+
1. It re-reads the entry and stops if the entry changed after the preview.
|
|
191
|
+
2. It creates the corrected entry with `POST /logwork/entries`.
|
|
192
|
+
3. It deletes the original with `DELETE /logwork/entries/:id`.
|
|
193
|
+
4. It verifies the new entry.
|
|
194
|
+
|
|
195
|
+
If the create fails, the original is untouched. If the delete fails, the new entry is deleted again, so nothing changes.
|
|
196
|
+
|
|
197
|
+
Deleting on RO needs no approval, and a correctly formatted new entry is approved immediately, so the edit takes effect at once. The new entry gets a **new logwork id**.
|
|
198
|
+
|
|
199
|
+
Some entries cannot be edited this way:
|
|
200
|
+
- Only `submitted` or `approved` entries can be edited.
|
|
201
|
+
- Rejected entries are fixed with `resubmit_entry`.
|
|
202
|
+
- Entries on locked days, entries created by Jira, and entries owned by another user are blocked.
|
|
203
|
+
|
|
204
|
+
The CLI previews the diff and asks for confirmation. Use `--yes` for an already reviewed non-interactive command.
|
|
205
|
+
|
|
206
|
+
In the terminal UI: `/edit-logwork 304032 --task Bug Fix --desc Fix date picker timezone (SAP-42)`.
|
|
207
|
+
|
|
208
|
+
In MCP, call `edit_entry` with `logworkId` and the changes, show the summary, then call `edit_entry` with `previewId` and `confirm: true`. The result returns `originalLogworkId` and `newLogworkId`.
|
|
209
|
+
|
|
210
|
+
## Daily Use
|
|
211
|
+
|
|
212
|
+
Ask your assistant:
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
Check whether I have logged anything today.
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
Preview this logwork and ask for my approval before submitting:
|
|
220
|
+
Monday, 01 Jun 2026
|
|
221
|
+
+2 Feature Development | Maintenance mode management and status UI (SCB-213)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
```text
|
|
225
|
+
Set up the SCB ticket mapping to project 2621A-SIT-HTML BUILDER-PRJ.
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
From the terminal:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
logwork quick -m "Fix login bug (SCB-12)" # one entry for today
|
|
232
|
+
logwork # terminal UI
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
In the terminal UI, `/logwork` opens a target picker. `/logwork ro` writes Resource Optimiser entries, `/logwork jira` writes Jira worklogs, and `/logwork both` previews and applies both with separate approvals. Type `/` to see every command, for example:
|
|
236
|
+
- `/query this-week`
|
|
237
|
+
- `/reconcile`
|
|
238
|
+
- `/projects`
|
|
239
|
+
- `/map SCB 5234`
|
|
240
|
+
- `/history`
|
|
241
|
+
- `/diagnostics`
|
|
242
|
+
|
|
243
|
+
## Reminder
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
logwork reminder enable # 17:00 Monday-Friday, RO and Jira
|
|
247
|
+
logwork reminder enable --time 18:00 --target ro
|
|
248
|
+
logwork reminder test
|
|
249
|
+
logwork reminder status
|
|
250
|
+
logwork reminder disable
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
For Resource Optimiser, the reminder compares today's logged and booked hours. For Jira, it checks whether you have any worklog today. Complete days stay silent.
|
|
254
|
+
|
|
255
|
+
macOS uses a user `launchd` agent (`sg.vinova.logwork-cli.reminder`) and Windows uses Task Scheduler (`Logwork Reminder`). Neither schedule stores credentials.
|
|
256
|
+
|
|
257
|
+
## Reconcile RO And Jira
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
logwork reconcile this-week
|
|
261
|
+
logwork reconcile last-month --json
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
This is read-only. It shows booked, RO and Jira hours by day and flags mismatches. A correction suggestion is included only when an RO entry contains exactly one Jira issue key. Applying a suggestion still goes through the normal preview and approval flow. MCP clients use the `reconcile` tool.
|
|
265
|
+
|
|
266
|
+
## Update
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
logwork update check
|
|
270
|
+
logwork update install
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
The terminal UI shows a short notice when a newer release is available. Checks are cached for 24 hours, and network errors never block logwork.
|
|
274
|
+
|
|
275
|
+
Updating keeps OS credentials, project mappings, drafts and apply history. Reconnect MCP clients after an update.
|
|
276
|
+
|
|
277
|
+
## More Docs
|
|
278
|
+
|
|
279
|
+
- [Operations guide](docs/operations-guide.md): CLI/MCP feature map, RO/Jira/Both processing, mapping, reconciliation, history, reminders, updates and OS validation.
|
|
280
|
+
- [MCP setup](docs/mcp-setup.md): client configs, the tool table, the old → new tool names, and common workflows.
|
|
281
|
+
- [Security and auth](docs/security.md): Keycloak flow, Jira PAT flow, OS credential storage, stored files and the safety model.
|
|
282
|
+
- [Advanced usage](docs/advanced.md): environment overrides, terminal UI details, troubleshooting and release checks.
|
|
283
|
+
- [Quick recipes](docs/recipes.md): copy-ready workflows.
|
|
284
|
+
- [Release checklist](RELEASE.md).
|
|
285
|
+
|
|
286
|
+
## License
|
|
287
|
+
|
|
288
|
+
This project is proprietary and not open source. See [LICENSE](LICENSE).
|
package/RELEASE.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Release Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist before publishing or tagging a production release.
|
|
4
|
+
|
|
5
|
+
The complete end-user update and maintainer publish flows are documented in the [integrated operations guide](docs/operations-guide.md).
|
|
6
|
+
|
|
7
|
+
## Version And Publish Sequence
|
|
8
|
+
|
|
9
|
+
Publishing is automated. Pushing a version bump to `main` is the release:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# 1. Add "## [<version>] - <date>" with a ### Summary to CHANGELOG.md
|
|
13
|
+
npm version <version> --no-git-tag-version
|
|
14
|
+
npm run release:check
|
|
15
|
+
git add -A
|
|
16
|
+
git commit -m "release v<version>"
|
|
17
|
+
git push origin main
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
After CI passes on `main`, `.github/workflows/release.yml`:
|
|
21
|
+
|
|
22
|
+
1. reads the version from `package.json`;
|
|
23
|
+
2. publishes `logwork-cli@<version>` to npm with provenance, using the `NPM_TOKEN` repository secret (skipped if already published);
|
|
24
|
+
3. creates tag `v<version>` and a GitHub Release whose description is the `CHANGELOG.md` section (skipped if the tag exists).
|
|
25
|
+
|
|
26
|
+
Check the result:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gh run list --workflow Release --limit 3
|
|
30
|
+
npm view logwork-cli version
|
|
31
|
+
gh release view v<version>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
To retry a failed release, re-run the Release workflow (or `gh workflow run Release`). Use `minor` or `major` instead of `patch` when required by SemVer. Never reuse an already published version.
|
|
35
|
+
|
|
36
|
+
### npm token
|
|
37
|
+
|
|
38
|
+
The workflow uses the `NPM_TOKEN` repository secret (an npm automation or granular token with publish rights to `logwork-cli`). Set or rotate it with `gh secret set NPM_TOKEN --repo malcohelper/logwork-cli` and paste the token at the prompt. Never put the token in files, commits or command arguments. Preferred long term: configure npm Trusted Publishing for this repo and workflow on npmjs.com, then delete the secret; `npm publish --provenance` in the workflow already runs with `id-token: write`.
|
|
39
|
+
|
|
40
|
+
## Required Gates
|
|
41
|
+
|
|
42
|
+
Run the local release gate:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run release:check
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Before publishing, run the release preflight doctor:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
logwork release doctor --full
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This checks version consistency, git cleanliness, npm auth, npm latest version, GitHub auth, tag/release state, local tarball artifacts, tests, audit, pack dry-run, and diff whitespace.
|
|
55
|
+
|
|
56
|
+
The gate must pass all of the following:
|
|
57
|
+
|
|
58
|
+
- `npm test`
|
|
59
|
+
- `npm audit --omit=dev --audit-level=moderate`
|
|
60
|
+
- `npm pack --dry-run`
|
|
61
|
+
- `git diff --check`
|
|
62
|
+
|
|
63
|
+
## Manual Verification
|
|
64
|
+
|
|
65
|
+
- Install from the packed tarball in a temporary directory.
|
|
66
|
+
- Run `logwork setup --no-login`.
|
|
67
|
+
- Confirm the printed MCP config uses server name `logwork` and `node ~/.logwork-cli/bin/logwork.mjs mcp`.
|
|
68
|
+
- Run `logwork --help` and `logwork --version`.
|
|
69
|
+
- Run `logwork update check --force` against the published npm version.
|
|
70
|
+
- Run `logwork mcp` through an MCP client smoke test and confirm it lists the 15 tools (`get_logwork`, `list_projects`, `list_tasks`, `log_work`, `edit_entry`, `resubmit_entry`, `delete_entry`, `log_jira_work`, `get_jira_issue`, `reconcile`, `get_history`, `map_project`, `login`, `reminder`, `update`).
|
|
71
|
+
- Confirm the `update` tool requires `confirm: true` for `action: "install"`, and `reconcile` takes preset periods only with no credential or confirmation fields.
|
|
72
|
+
- Run `logwork reconcile this-week` and confirm it reports RO/Jira daily totals without writing either system.
|
|
73
|
+
- On a machine with an older `logwork-helper` install, confirm the first run copies state to `~/.logwork-cli` and `logwork status` shows the existing session without a new login.
|
|
74
|
+
- Confirm the Windows CI job passes the dedicated `Verify Windows Credential Manager integration` step.
|
|
75
|
+
- Run `logwork reminder test`, confirm a native notification appears, then verify `logwork reminder status` and clean up with `logwork reminder disable`.
|
|
76
|
+
- Run `logwork status` and confirm no token is printed.
|
|
77
|
+
|
|
78
|
+
## Safety Checks
|
|
79
|
+
|
|
80
|
+
- Do not include Resource Optimiser tokens, `.env` files, diagnostics reports, or machine-specific MCP configs in the package.
|
|
81
|
+
- Confirm `logwork --version` and the MCP server version match `package.json`.
|
|
82
|
+
- Confirm `README.md` and onboarding output describe the same primary setup flow.
|
|
83
|
+
- Confirm no untracked release artifacts are included except intentional documentation.
|
|
84
|
+
|
|
85
|
+
## Rollback
|
|
86
|
+
|
|
87
|
+
- Keep the previous npm package version available.
|
|
88
|
+
- If a release introduces auth, MCP, or apply-path regressions, roll back by instructing users to install the previous known-good npm version.
|
|
89
|
+
- Do not publish a replacement with the same version; publish a new patch version after the fix is verified.
|
package/bin/logwork.mjs
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { isMainModule } from '../lib/entrypoint.mjs';
|
|
4
|
+
import { migrateLegacyHome } from '../lib/legacy-migration.mjs';
|
|
5
|
+
import { readPackageVersion } from '../lib/package-info.mjs';
|
|
6
|
+
|
|
7
|
+
// One entry point for every surface:
|
|
8
|
+
// logwork -> terminal UI
|
|
9
|
+
// logwork <command> ... -> CLI command (loaded on demand, run in-process)
|
|
10
|
+
// logwork mcp -> MCP stdio server for IDEs and agent CLIs
|
|
11
|
+
export const COMMANDS = [
|
|
12
|
+
{ name: 'query', usage: 'query [today|yesterday|this-week|last-week|this-month|last-month] [--json]', summary: 'Show booked vs logged hours with entry ids', load: () => import('../commands/query.mjs'), fn: 'run' },
|
|
13
|
+
{ name: 'quick', usage: 'quick [-m "what you did"]', summary: 'Log one entry for today with guided prompts', load: () => import('../commands/quick.mjs'), fn: 'run' },
|
|
14
|
+
{ name: 'edit', usage: 'edit <id> [--hours h] [--task name|#id] [--desc text] [--type type]', summary: 'Change an existing RO entry (replaces it)', load: () => import('../commands/edit.mjs'), fn: 'runRoEditCommand' },
|
|
15
|
+
{ name: 'delete', usage: 'delete <id>', summary: 'Delete a submitted or approved RO entry', load: () => import('../commands/delete.mjs'), fn: 'runRoDeleteCommand' },
|
|
16
|
+
{ name: 'reconcile', usage: 'reconcile [period] [--json]', summary: 'Compare RO and Jira hours by day', load: () => import('../commands/reconcile.mjs'), fn: 'runReconcileCommand' },
|
|
17
|
+
{ name: 'history', usage: 'history [--target ro|jira|both] [--limit n] [--json]', summary: 'Show the local apply history', load: () => import('../commands/history.mjs'), fn: 'runHistoryCommand' },
|
|
18
|
+
{ name: 'login', usage: 'login [ro|jira] [--base-url url]', summary: 'Log in to Resource Optimiser (default) or Jira', load: () => import('../commands/auth.mjs'), fn: 'runLogin' },
|
|
19
|
+
{ name: 'logout', usage: 'logout [ro|jira]', summary: 'Remove the stored RO (default) or Jira session', load: () => import('../commands/auth.mjs'), fn: 'runLogout' },
|
|
20
|
+
{ name: 'status', usage: 'status', summary: 'Show RO and Jira login status', load: () => import('../commands/auth.mjs'), fn: 'runStatus' },
|
|
21
|
+
{ name: 'setup', usage: 'setup [--login|--no-login]', summary: 'Install the runtime and print MCP configs', load: () => import('../commands/setup.mjs'), fn: 'run' },
|
|
22
|
+
{ name: 'mcp', usage: 'mcp', summary: 'Run the MCP stdio server (used by IDE configs)', load: () => import('../lib/mcp-server.mjs'), fn: 'startMcpServer' },
|
|
23
|
+
{ name: 'reminder', usage: 'reminder enable|disable|status|test', summary: 'Manage the weekday logwork reminder', load: () => import('../commands/reminder.mjs'), fn: 'runReminderCli' },
|
|
24
|
+
{ name: 'update', usage: 'update [check|install]', summary: 'Check for or install a new version', load: () => import('../commands/update.mjs'), fn: 'runUpdateCli' },
|
|
25
|
+
{ name: 'doctor', usage: 'doctor', summary: 'Write a sanitized diagnostics report', load: () => import('../commands/doctor.mjs'), fn: 'run' },
|
|
26
|
+
{ name: 'release', usage: 'release doctor [--full]', summary: 'Maintainers: check release readiness', load: () => import('../commands/release.mjs'), fn: 'run' }
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export async function run(argv = process.argv.slice(2)) {
|
|
30
|
+
const [first, ...rest] = argv;
|
|
31
|
+
|
|
32
|
+
if (first === '--version' || first === '-v') {
|
|
33
|
+
console.log(readPackageVersion());
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (first === '--help' || first === '-h' || first === 'help') {
|
|
37
|
+
console.log(formatHelp());
|
|
38
|
+
return 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (first !== 'mcp') {
|
|
42
|
+
reportMigration(migrateLegacyHome());
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!first || first.startsWith('-')) {
|
|
46
|
+
const tui = await import('../commands/tui.mjs');
|
|
47
|
+
return tui.run(argv);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const command = COMMANDS.find((item) => item.name === first);
|
|
51
|
+
if (!command) {
|
|
52
|
+
console.error(`Unknown command: ${first}\n`);
|
|
53
|
+
console.error(formatHelp());
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (command.name === 'mcp') {
|
|
58
|
+
migrateLegacyHome();
|
|
59
|
+
}
|
|
60
|
+
const module = await command.load();
|
|
61
|
+
const result = await module[command.fn](rest);
|
|
62
|
+
return typeof result === 'number' ? result : undefined;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function formatHelp() {
|
|
66
|
+
const width = Math.max(...COMMANDS.map((command) => command.name.length));
|
|
67
|
+
return `Usage:
|
|
68
|
+
logwork Open the terminal UI
|
|
69
|
+
logwork <command> Run one command (add --help for its options)
|
|
70
|
+
|
|
71
|
+
Commands:
|
|
72
|
+
${COMMANDS.map((command) => ` ${command.name.padEnd(width)} ${command.summary}`).join('\n')}
|
|
73
|
+
|
|
74
|
+
Examples:
|
|
75
|
+
logwork setup
|
|
76
|
+
logwork login
|
|
77
|
+
logwork query this-week
|
|
78
|
+
logwork quick -m "Fix login bug (SCB-12)"
|
|
79
|
+
logwork edit 304032 --task "Bug Fix" --desc "Fix date picker timezone (SAP-42)"
|
|
80
|
+
|
|
81
|
+
Options:
|
|
82
|
+
-h, --help Show help
|
|
83
|
+
-v, --version Show version`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function reportMigration(result) {
|
|
87
|
+
if (result?.migrated) {
|
|
88
|
+
console.error(`Moved local settings from ${result.from} to ${result.to}.`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (isMainModule(import.meta.url)) {
|
|
93
|
+
run().then((code) => {
|
|
94
|
+
if (typeof code === 'number') {
|
|
95
|
+
process.exitCode = code;
|
|
96
|
+
}
|
|
97
|
+
}).catch((error) => {
|
|
98
|
+
console.error(error.message);
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
});
|
|
101
|
+
}
|