dsh-power-after-task 1.0.0 → 1.0.1

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +11 -1
  2. package/README.md +46 -98
  3. package/package.json +13 -4
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  All notable changes to `dsh-power-after-task` are documented here.
4
4
 
5
+ ## 1.0.1
6
+
7
+ - Search metadata: npm `description` and `keywords` rewritten to cover DeepSeek
8
+ Harness / DSH / cordis / Windows power vocabulary, so the package is findable
9
+ on npm and the ecosystem index. No runtime change.
10
+ - Bundled README rewritten for the published package (badges, tighter sections).
11
+ - Repository only (not in the tarball): CI check workflow, issue/PR templates,
12
+ security policy, contributing guide, dependabot, editorconfig; the inert
13
+ `publish.yml` workflow removed (releases go through npm staged publishing).
14
+
5
15
  ## 1.0.0
6
16
 
7
17
  Initial release.
@@ -19,4 +29,4 @@ Initial release.
19
29
  - `GET /power-task/debug` reports sessions, origin, and the headers of the last read and mutating request, so a rejected Arm is diagnosable without a browser console.
20
30
  - `power_after_task` agent tool: `status`, `arm`, `cancel`, `execute`.
21
31
  - English and Persian locale dictionaries plus Plugin Manager title, description, and icon.
22
- - Local publish helper: `npm run publish:local` reads `NPM_TOKEN` from a gitignored `.env`, publishes through a throwaway owner-only npmrc, and deletes it afterwards.
32
+ - Local release helper: `npm run stage` publishes through npm staged publishing with `NPM_TOKEN` from a gitignored `.env`, via a throwaway owner-only npmrc and a pinned npm 11 under `.npm-tools/`; `stage:list`, `stage:view`, `stage:approve`, and `stage:reject` manage what is waiting.
package/README.md CHANGED
@@ -1,145 +1,93 @@
1
1
  # dsh-power-after-task
2
2
 
3
- A DeepSeek Harness (DSH) plugin that puts the host Windows PC to **Sleep**, **Shuts it down**, or **Restarts** it once the current agent task finishes — with a cancellable grace countdown, controlled from one small button in the composer dock.
3
+ [![npm](https://img.shields.io/npm/v/dsh-power-after-task?logo=npm&logoColor=white&color=CB3837)](https://www.npmjs.com/package/dsh-power-after-task)
4
+ [![license](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)
5
+ [![CI](https://github.com/white-sparrow/dsh-power-after-task/actions/workflows/ci.yml/badge.svg)](https://github.com/white-sparrow/dsh-power-after-task/actions/workflows/ci.yml)
4
6
 
5
- It never acts on its own. Nothing happens until you press **Arm**, and the power command only runs after the session's agent has actually stopped working *and* the grace countdown has run out.
7
+ Windows **Sleep / Shut down / Restart** after the current agent task finishes — a compact, disabled-by-default DeepSeek Harness plugin.
6
8
 
7
- **Repository:** <https://github.com/white-sparrow/dsh-power-after-task>
9
+ Nothing happens on its own: the power command only runs after you press **Arm**, the agent has actually stopped working, and the grace countdown expires. **Cancel** at any point returns it to off.
8
10
 
9
- ## What counts as "the task finished"
10
-
11
- The task is the span of work between your prompt and the moment the agent stops producing work — however many steps (tool calls), turns, continuations, or subagents it took. It ends on any turn stop:
12
-
13
- | Situation | Treated as finished |
14
- | --- | --- |
15
- | The agent answered and stopped | yes |
16
- | The agent stopped with an error and showed no result | yes |
17
- | You cancelled the run | yes |
18
- | A goal driver or auto-continuation is still running the session | no |
19
- | You send another message while the countdown is running | no — the countdown goes back to waiting |
20
- | The session is archived or removed while armed | yes |
21
-
22
- The plugin watches the Harness session-status signal (`api-session/status`), so it follows the real agent lifecycle rather than a guess about "the answer being visible".
11
+ ## Requirements
23
12
 
24
- ## Arm and Grace
13
+ - **Windows** host — power commands are Windows-specific; other platforms are rejected with an error.
14
+ - **Web composition** (`dsh web`): the dock control talks to the Host over this plugin's own HTTP route; a Desktop page has no web server, so no control appears there.
15
+ - Node 20+ for the Harness Host. No build step, no dependencies.
25
16
 
26
- - **Arm** — registers the request for one session: "when this session's task finishes, run the chosen power action". Until you Arm, the plugin is inert.
27
- - **Grace** — a cancellable delay between "the task finished" and "the command runs" (default 45 seconds). It exists so a mis-click, a late follow-up message, or unsaved work can still be rescued. Choices: 15s, 30s, 1m, 2m, 5m.
28
- - **Cancel** — stops the arm at any time, while waiting or while counting.
17
+ ## Install and enable
29
18
 
30
19
  ```
31
- Arm → waiting for the task to finish → agent goes idle → grace countdown → power command
32
- ↑ any new activity returns here │ Cancel → off
20
+ Plugin Manager → Install bundle → dsh-power-after-task
33
21
  ```
34
22
 
35
- Commands actually run: `shutdown.exe /s /t 0` (Shut down), `shutdown.exe /r /t 0` (Restart), or `kernel32!ApplicationSuspend` via PowerShell with a `rundll32 powrprof.dll,SetSuspendState 0,0,0` fallback (Sleep). Sleep uses `ApplicationSuspend` deliberately: the `rundll32` form hibernates whenever hibernation is enabled.
36
-
37
- ## The control in the UI
23
+ The bundle's patch inserts the plugin row with `disabled: true`, so installing changes nothing else. Enable when you need it via **Settings → Plugins → Power after task**; the dock entry appears within about two seconds, and disabling the row (which also clears every pending arm) removes it again — no page refresh needed.
38
24
 
39
- ### Composer-dock control
25
+ ## UI
40
26
 
41
- One entry in the composer dock, beside the shipped Activity and Usage entries:
27
+ One entry in the composer dock, beside Activity and Usage:
42
28
 
43
- - **Idle** — a single power icon. Nothing else.
29
+ - **Idle** — just a small power icon.
44
30
  - **Click** — expands inline into two drop-downs (Action, Grace) and an **Arm** button.
45
- - **Armed** — the icon shrinks, lights up (brand colour while waiting, amber while counting or failed), and a **Cancel** button appears. No status text is printed; hovering the icon shows the action and the remaining countdown.
46
- - **Disabled row** — the entry removes itself within a couple of seconds, whether you enable or disable it, because the widget probes the plugin route.
47
-
48
- ### Countdown ribbon
49
-
50
- While a countdown is running, a wide semi-transparent ribbon sits across the middle of the frame (registered in `shell.overlay`):
51
-
52
- - A large `m:ss.mmm` timer — minutes, seconds, milliseconds — updated on animation frames.
53
- - A tiny line under it naming the target: `Until sleep`, `Until shut down`, `Until restart`.
54
- - A **Cancel** button, because the arm stays visible until the countdown finishes or you cancel it.
55
-
56
- The layer itself is click-through: only the Cancel button takes pointer events, so the ribbon never blocks the work you are still doing. A failed power command keeps the ribbon visible with the error instead of silently returning to normal.
57
-
58
- Every colour is a `--dsw-alias-*` theme token (`bg-overlay`, `brand-primary`, `state-warn-primary`, `state-error-primary`, `label-*`, `border-*`), mixed with `transparent` for the semi-transparent surfaces, so the plugin follows the Harness light/dark setting automatically.
59
-
60
- ## Requirements
61
-
62
- - **Windows** host (the power commands are Windows-specific). On other platforms the action is rejected with an error.
63
- - **Web composition** (`dsh web`): the dock widget talks to the Host through this plugin's own HTTP route. A Desktop/Electron page has no `ctx.webServer`, so the control does not appear there.
64
- - Node 20+ for the Harness Host.
31
+ - **Armed** — icon shrinks and lights up (brand while waiting, amber while counting), a **Cancel** button appears; hover shows action + remaining time. No status text by design.
65
32
 
66
- ## Install
33
+ While a countdown runs, a wide semi-transparent ribbon (registered in `shell.overlay`) shows a large `m:ss.mmm` timer, a tiny `Until sleep / Until shut down / Until restart` caption, and a **Cancel** button. The layer is click-through — only Cancel takes pointer events — and a failed power command keeps the ribbon visible with the error.
67
34
 
68
- Publish or unpack the package, then install the bundle in the Harness profile:
35
+ All colours are `--dsw-alias-*` theme tokens, so dark/light follows the Harness theme automatically.
69
36
 
70
- - **Plugin Manager UI** → Install bundle → `dsh-power-after-task`.
71
- - Or from an agent session, ask it to install the bundle with the `plugin_manager` tool.
72
- - Or from a checkout: `plugin_manager` install target pointing at the directory (pnpm links it, no build step — the package ships plain JavaScript).
37
+ ## When the task counts as finished
73
38
 
74
- The bundle ships a composition patch (`dsh.bundle.patch`) that inserts the plugin row. Installing does **not** turn it on.
39
+ The task is the whole span between your prompt and the agent's turn stop — across steps, continuations, and subagents. It counts as finished when the agent answers, errors out without a result, or you cancel; also if the session is archived/removed while armed. It does **not** fire while a goal driver or continuation is still running, and any new message puts the countdown back to waiting. Detection uses the session-status signal (`api-session/status`), not a guess.
75
40
 
76
- ## Enable it when you need it
41
+ ```
42
+ Arm → waiting → agent goes idle → grace countdown → power command
43
+ ↑ new activity returns here Cancel → off
44
+ ```
77
45
 
78
- The row ships `disabled: true`, so after install nothing runs and the dock entry does not appear:
46
+ **Grace** (default 45 s, choices 15 s / 30 s / 1 m / 2 m / 5 m, cap 3600 s) is the cancellable gap between "finished" and "fires" — long enough to rescue a mis-click or unsaved work.
79
47
 
80
- 1. Settings → Plugins → **Power after task** → enable. The entry appears within a couple of seconds, and disabling the row removes it again — no page refresh needed either way.
48
+ Commands run: `shutdown.exe /s /t 0`, `shutdown.exe /r /t 0`, or Sleep via `kernel32!ApplicationSuspend` (deliberately not `rundll32 SetSuspendState`, which hibernates when hibernation is enabled; `rundll32` is only the fallback).
81
49
 
82
- Arm and Cancel are mutating, so they refuse a request that *proves* it is not this page: a non-loopback `Host` (DNS rebinding or a foreign vhost), a browser-reported cross-site request (`Sec-Fetch-Site`), or a non-loopback `Origin`. A request carrying none of that evidence is accepted — that is the Harness page through its own transport, which forwards `Cookie` but not `Sec-Fetch-*` or `Origin` — and a local process, which could run `shutdown.exe` directly anyway. A foreign web page cannot reach this port under its own name, and a DNS-rebinding attack arrives with the foreign `Host`, so both are refused. Turning the row off clears every pending arm and countdown.
50
+ ## Agent tool
83
51
 
84
- `GET /power-task/debug` reports the running and armed sessions, the server origin, and the headers of the last read plus the last mutating request (`accepted` says whether the guard passed), so a rejected Arm is diagnosable without a browser console.
52
+ `power_after_task` — `action: status | arm | cancel | execute`, `session`, `power: sleep | shutdown | restart`, `grace_seconds`. `execute` fires immediately and is not reachable from the HTTP route; the page can only Arm and Cancel.
85
53
 
86
54
  ## Configuration
87
55
 
88
- The row's `config` lives in `cordis.patch.yml` inside the package; override it with your own patch if you want different defaults.
56
+ Set in `cordis.patch.yml` (override with your own patch):
89
57
 
90
- | Field | Default | Meaning |
58
+ | Key | Default | Meaning |
91
59
  | --- | --- | --- |
92
- | `defaultAction` | `shutdown` | Action the control preselects: `sleep`, `shutdown`, `restart` |
93
- | `graceSeconds` | `45` | Countdown length after the task finishes; capped at 3600 |
60
+ | `defaultAction` | `shutdown` | Preselected action: `sleep` · `shutdown` · `restart` |
61
+ | `graceSeconds` | `45` | Countdown after finish; capped at 3600 |
94
62
 
95
- ## Agent tool
63
+ ## Security
96
64
 
97
- The plugin also registers one tool, so you can ask your agent to do the same thing:
98
-
99
- `power_after_task` — `action: status | arm | cancel | execute`, `session`, `power: sleep | shutdown | restart`, `grace_seconds`.
100
-
101
- `execute` runs the action immediately and is deliberately **not** reachable from the HTTP route: the page can only Arm and Cancel.
65
+ Arm/Cancel refuse requests that *prove* they are not this page: non-loopback `Host` (DNS rebinding), browser-reported cross-site `Sec-Fetch-Site`, or non-loopback `Origin`. Requests carrying none of that evidence pass — that is the Harness page transport (it forwards `Cookie` but not fetch metadata) or a local process, which could run `shutdown.exe` directly anyway. Route: `POST /power-task/arm`, `POST /power-task/cancel`, `GET /power-task/state`, `GET /power-task/debug`. See [SECURITY.md](SECURITY.md).
102
66
 
103
67
  ## Files
104
68
 
105
69
  | File | Role |
106
70
  | --- | --- |
107
- | `index.js` | Host half: `/power-task` route, session-status watcher, countdown, Windows power commands, `power_after_task` tool |
108
- | `client.js` | Web UI half: the composer-dock control and the `shell.overlay` countdown ribbon |
109
- | `cordis.patch.yml` | The plugin row, disabled by default, with its `config` |
110
- | `locale/en.json`, `locale/fa.json` | Plugin Manager title and description (`meta.title`, `meta.description`) |
71
+ | `index.js` | Host half: `/power-task` route, session watcher, countdown, Windows power commands, tool |
72
+ | `client.js` | UI half: composer-dock control + `shell.overlay` countdown ribbon |
73
+ | `cordis.patch.yml` | Plugin row, disabled by default, with `config` |
74
+ | `locale/en.json`, `locale/fa.json` | Plugin Manager title/description |
111
75
  | `icon.svg` | Plugin Manager artwork |
112
76
 
113
- No build step, no dependencies.
114
-
115
77
  ## Troubleshooting
116
78
 
117
79
  | Symptom | Fix |
118
80
  | --- | --- |
119
- | No dock entry | The row is disabled — enable it in Settings → Plugins; the entry appears within a couple of seconds |
120
- | Arm answers `answered 403` | Open `http://127.0.0.1:<port>/power-task/debug` and read `lastPost`: it shows the `host`, `secFetchSite`, `origin` and `accepted` of your click. A non-loopback `host` means the page is being served through a proxy or a foreign hostname |
121
- | Ribbon does not appear after upgrading the plugin | Refresh the page once so the browser loads the new client bundle |
122
- | Ribbon keeps counting after the task should be protected | That is the design: it counts until the command runs, you Cancel it, or new activity pauses it back to waiting |
123
- | `… failed` in the ribbon | The Host could not run the command — check power settings, hibernation/fast-startup, or shutdown privileges; Cancel clears the state |
124
- | Nothing happens when the task ends | The session is still running (a goal continuation, a subagent, or a queued message keeps it `running`) |
125
- | Control missing on the Desktop app | Expected: that composition has no web server |
81
+ | No dock entry | Row is disabled — enable it in Settings → Plugins |
82
+ | Arm answers `403` | Read `GET /power-task/debug` → `lastPost`: `host`, `secFetchSite`, `origin`, `accepted`. A non-loopback `host` means a proxy or foreign hostname |
83
+ | Ribbon missing after upgrade | Refresh the page once to load the new client bundle |
84
+ | `… failed` in the ribbon | Command rejected — power settings, hibernation/fast-startup, shutdown privileges; Cancel clears state |
85
+ | Nothing fires | Session is still running (goal continuation, subagent, queued message) |
126
86
 
127
- ## Publish to npm
128
-
129
- Publishing needs an npm credential, and `.env` — gitignored and excluded from the tarball — is where it lives on your machine:
130
-
131
- ```
132
- NPM_TOKEN=<your npm access token>
133
- ```
134
-
135
- Create it at npmjs.com → Account settings → Access tokens → **Granular Access Token**, scoped to `dsh-power-after-task` only, type **Automation**, no read access to private packages, short expiry (`.env.example` documents the format).
136
-
137
- ```sh
138
- npm run publish:local
139
- ```
87
+ ## Development and releases
140
88
 
141
- `scripts/publish.mjs` reads `NPM_TOKEN` from `.env` (or the environment), writes it into a throwaway `.npmrc` under your temp directory with owner-only access, runs `npm publish --access public` — which still runs `prepublishOnly` → `npm run check` first — and deletes that file when the publish returns. npm 10 ignores `${VAR}` interpolation inside `--userconfig`, so the value has to be written literally there. The token appears in no command line, no npm output, no commit, and no tarball; nothing publishes without it.
89
+ See [CONTRIBUTING.md](CONTRIBUTING.md) — checks (`npm run check`), local debugging, and the staged npm release flow.
142
90
 
143
91
  ## License
144
92
 
145
- MIT — see `LICENSE`.
93
+ MIT — see [LICENSE](LICENSE).
package/package.json CHANGED
@@ -1,18 +1,27 @@
1
1
  {
2
2
  "name": "dsh-power-after-task",
3
- "version": "1.0.0",
4
- "description": "DeepSeek Harness plugin: sleep, shut down, or restart this Windows PC after the current agent task finishes, with a cancellable grace countdown in the composer dock.",
3
+ "version": "1.0.1",
4
+ "description": "DeepSeek Harness (DSH) plugin for Windows: sleep, shut down, or restart the PC once the current agent task finishes. Ships disabled; arm it from a compact composer-dock control, watch a frame-wide countdown ribbon you can cancel any time. No dependencies, no build step.",
5
5
  "keywords": [
6
6
  "deepseek-harness",
7
+ "deepseek",
8
+ "harness",
7
9
  "dsh",
8
10
  "cordis",
11
+ "cordis-plugin",
9
12
  "plugin",
10
13
  "bundle",
14
+ "web-plugin",
11
15
  "windows",
12
16
  "power",
13
- "sleep",
17
+ "power-management",
14
18
  "shutdown",
15
- "restart"
19
+ "restart",
20
+ "sleep",
21
+ "hibernate",
22
+ "suspend",
23
+ "agent-task",
24
+ "countdown"
16
25
  ],
17
26
  "license": "MIT",
18
27
  "author": "Mori",