dsh-super-kanban 0.3.0 → 0.4.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/CHANGELOG.md +30 -1
- package/README.en.md +287 -0
- package/README.md +20 -14
- package/client.js +168 -51
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.4.0] - 2026-11-05
|
|
11
|
+
|
|
12
|
+
UI refinement release: put the frequently used toolbar actions back on the
|
|
13
|
+
toolbar and bring back restrained emphasis and status marks without returning
|
|
14
|
+
to the earlier visual clutter.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **Toolbar actions are visible**: Settings and "open in right sidebar" are
|
|
19
|
+
now persistent icon buttons in the board header and the compact right-panel
|
|
20
|
+
header. The overflow menu keeps only **Export JSON**.
|
|
21
|
+
- **Restrained emphasis and status marks**: cards show a small status dot and a
|
|
22
|
+
state-tinted progress line (backlog neutral, in progress brand, blocked
|
|
23
|
+
amber, done green), colored priority text (P0 error, P1 amber), issue count,
|
|
24
|
+
artifact count, subtask progress and a low-key AI/rules marker. Column
|
|
25
|
+
headers and the summary line carry matching status dots.
|
|
26
|
+
- **Task drawer depth**: colored status/priority text, type icons for key
|
|
27
|
+
facts, severity-colored issues, and a brand-colored session link, while the
|
|
28
|
+
primary button and DSH typography stay neutral.
|
|
29
|
+
- **English README** (`README.en.md`) alongside the Chinese README.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- Color is now limited to dots, thin progress lines, small icons and short
|
|
34
|
+
labels; there are no colored blocks, gradients or glow effects. Light and
|
|
35
|
+
dark themes, the full board, the compact sidebar and narrow windows were all
|
|
36
|
+
checked against the DSH type scale and spacing.
|
|
37
|
+
|
|
10
38
|
## [0.3.0] - 2026-11-05
|
|
11
39
|
|
|
12
40
|
First public release. Super Kanban turns the sessions of a DeepSeek Harness
|
|
@@ -55,5 +83,6 @@ workspace into a maintainable task board.
|
|
|
55
83
|
with the local DSH account token; tokens are never logged or persisted by the
|
|
56
84
|
plugin. See [SECURITY.md](./SECURITY.md).
|
|
57
85
|
|
|
58
|
-
[Unreleased]: https://github.com/topmindspace/dsh-super-kanban/compare/v0.
|
|
86
|
+
[Unreleased]: https://github.com/topmindspace/dsh-super-kanban/compare/v0.4.0...HEAD
|
|
59
87
|
[0.3.0]: https://github.com/topmindspace/dsh-super-kanban/releases/tag/v0.3.0
|
|
88
|
+
[0.4.0]: https://github.com/topmindspace/dsh-super-kanban/releases/tag/v0.4.0
|
package/README.en.md
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Super Kanban · AI Task Command Center
|
|
2
|
+
|
|
3
|
+
[](https://github.com/topmindspace/dsh-super-kanban/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/dsh-super-kanban)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
An AI task board that **lives inside the DeepSeek Harness UI**. It reads the real DSH sessions across your workspaces and infers each task's goal, progress, completion state and open issues — and you can also maintain the board entirely by hand. Every card can be traced back to a specific session and a specific sentence.
|
|
8
|
+
|
|
9
|
+
- **Where it lives**: "任务看板" (Task board) in the DSH sidebar, or the compact form in the right sidebar of a conversation.
|
|
10
|
+
- **Data**: sessions are scanned read-only on your machine; board data stays on your machine.
|
|
11
|
+
- **Intelligence**: reuses the model quota of the DSH account already signed in on this machine — zero configuration. Turn AI off and it falls back to local rule-based analysis.
|
|
12
|
+
|
|
13
|
+
**English** | [简体中文](README.md)
|
|
14
|
+
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
## Contents
|
|
20
|
+
|
|
21
|
+
- [Why Super Kanban](#why-super-kanban)
|
|
22
|
+
- [Features](#features)
|
|
23
|
+
- [Two layouts](#two-layouts)
|
|
24
|
+
- [Installation](#installation)
|
|
25
|
+
- [Usage](#usage)
|
|
26
|
+
- [AI and privacy](#ai-and-privacy)
|
|
27
|
+
- [Screenshots](#screenshots)
|
|
28
|
+
- [Compatibility](#compatibility)
|
|
29
|
+
- [FAQ](#faq)
|
|
30
|
+
- [Development and contributing](#development-and-contributing)
|
|
31
|
+
- [License](#license)
|
|
32
|
+
|
|
33
|
+
## Why Super Kanban
|
|
34
|
+
|
|
35
|
+
You keep several workspaces and many sessions going in DSH at the same time, and task state is scattered across conversations: how far did this get? Where is it stuck? Was anything delivered? Did it quietly die?
|
|
36
|
+
|
|
37
|
+
Super Kanban turns those conversations into a maintainable board:
|
|
38
|
+
|
|
39
|
+
| Capability | Description |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| 🎯 Goal extraction | Derives the task title and goal from the real request in a session instead of using the whole prompt as a title |
|
|
42
|
+
| 📈 Progress estimation | Prefers todo completion inside the session, combined with deliverables and turn state |
|
|
43
|
+
| ✅ Completion detection | Combines the last assistant reply, deliverables (present / file writes) and whether the user asked for more changes |
|
|
44
|
+
| ⚠️ Issue detection | Tool errors, user corrections and unresolved questions are attached to the card as "issues" |
|
|
45
|
+
| 🔗 Traceability | Every card carries its source workspace / session / evidence timeline, with a jump back to the session |
|
|
46
|
+
| 🤝 Session hand-off | "Continue this task" builds a structured prompt and (after your confirmation) puts it in the original or a new session input — never sends automatically |
|
|
47
|
+
| ✅ Subtasks and goals | Subtask checklists (importable from session todos, writes back progress), task goal, and DSH Session Goal tracking |
|
|
48
|
+
| 📦 Artifact tracking | Collects deliverables and written files; click to open them in the DSH document preview |
|
|
49
|
+
| 🧾 Key facts first | Cards show a one-line goal summary; the drawer leads with 3–6 key facts and keeps raw evidence collapsed |
|
|
50
|
+
| ✍️ Manual control | Create, edit, drag between columns, archive, delete, lock fields — AI never overwrites what you locked |
|
|
51
|
+
| 🔄 Continuous maintenance | First scan in seconds, then incremental scans; new sessions join automatically and old tasks keep updating |
|
|
52
|
+
| 🧠 Explainable | Every inference carries a confidence and a one-line reason — no black-box status changes |
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
### Two analysis engines: better with AI, always usable offline
|
|
57
|
+
|
|
58
|
+
1. **Collect (local)**: reads `workspace.json` and each session's `session.v4.jsonl.zstd`, parsing user requests, assistant replies, tool calls, todo snapshots, deliverables, errors and turn-end reasons.
|
|
59
|
+
2. **Rules engine (always available, zero tokens)**: local heuristics derive status, progress, issues and evidence. When you are signed out, offline, or AI is disabled, the board keeps working.
|
|
60
|
+
3. **LLM analysis (optional, online)**: sends a compressed session digest to the DeepSeek inference API and receives structured JSON (tasks, status, progress, issues, evidence, confidence, reason).
|
|
61
|
+
4. **Merge (local)**: merges results back by session anchor; locked fields are never overwritten; every change is recorded in task history.
|
|
62
|
+
|
|
63
|
+
### Token efficiency
|
|
64
|
+
|
|
65
|
+
- Session digests sent to the model are capped at **≤1.5KB per session**, containing only recent changes and key signals.
|
|
66
|
+
- Structured output is bounded: ≤6 key facts, ≤8 evidence items, `max_tokens` ≤ 2200, with per-session limits.
|
|
67
|
+
- **Incremental gating**: the model is called only when user messages increase, a turn ends, the session is new, or you explicitly re-analyze. Live turns are never re-analyzed, and there is a minimum interval per session.
|
|
68
|
+
- **Controllable budget**: per-scan and daily AI call limits are configurable; exceeding them automatically falls back to the rules engine. The settings page shows today's calls and tokens.
|
|
69
|
+
- Re-scanning already analyzed sessions results in **zero AI calls**.
|
|
70
|
+
|
|
71
|
+
### Data and privacy
|
|
72
|
+
|
|
73
|
+
- Board data is written only to `~/.dsh/storages/super-kanban/` on your machine. No third-party servers, no telemetry.
|
|
74
|
+
- Online analysis sends **compressed digests only**: never full session text, never file contents, never account credentials.
|
|
75
|
+
- All AI features can be disabled in settings and take effect immediately, falling back to local rules.
|
|
76
|
+
|
|
77
|
+
## Two layouts
|
|
78
|
+
|
|
79
|
+
The same board can be opened in two ways:
|
|
80
|
+
|
|
81
|
+
| Layout | How to open | Characteristics |
|
|
82
|
+
| --- | --- | --- |
|
|
83
|
+
| **Full-page panel** | "任务看板" in the left sidebar | Full four-column board + filters + stats line, best for focused review |
|
|
84
|
+
| **Right sidebar** | Board icon in the conversation header, or "任务看板" in the right sidebar's "+" tools list | Board next to the chat; width-adaptive: narrow (single column + status segments) / medium / wide (four columns) |
|
|
85
|
+
|
|
86
|
+
- **Right sidebar fullscreen**: the fullscreen control on the right sidebar header expands the board to the whole viewport; you can leave it at any time.
|
|
87
|
+
- **Switching**: the "open in right sidebar" icon in the full-page header, or the "open as full page" icon in the right sidebar board.
|
|
88
|
+
- **Entry preferences**: board settings → "Display and entry" offers "Both (default) / Full page only / Right sidebar only"; refresh the window after changing.
|
|
89
|
+
|
|
90
|
+
## Installation
|
|
91
|
+
|
|
92
|
+
> Prerequisites: DSH desktop installed and opened at least once (`~/.dsh/profiles/desktop` exists); DSH version `>= 0.2.1-rc.5 < 0.3.0`.
|
|
93
|
+
|
|
94
|
+
### Option A: Plugin market index (recommended)
|
|
95
|
+
|
|
96
|
+
> "Discover" comes from DSH's experimental plugin market capability: first enable **Plugin market** under **Plugins → Experimental plugins** and reload DSH as prompted. If your DSH build does not offer it, use Option B/C/D.
|
|
97
|
+
|
|
98
|
+
1. DSH → **Plugins** → **Discover**
|
|
99
|
+
2. **Add index source** and paste:
|
|
100
|
+
`https://topmindspace.github.io/dsh-super-kanban/index.json`
|
|
101
|
+
3. Find **Super Kanban** in the list → **Install** → enable
|
|
102
|
+
4. Press `Cmd+R` in the DSH window (restart DSH if needed)
|
|
103
|
+
|
|
104
|
+
> The market index becomes available after the first release is published to GitHub Pages; its content comes from this repository's `docs/`.
|
|
105
|
+
|
|
106
|
+
### Option B: npm package
|
|
107
|
+
|
|
108
|
+
DSH → Plugins → Add plugin → enter the package name `dsh-super-kanban` (optionally with a version, e.g. `dsh-super-kanban@<version>`) → install → enable → reload the window.
|
|
109
|
+
|
|
110
|
+
> The npm package is published: `dsh-super-kanban` (https://www.npmjs.com/package/dsh-super-kanban). See [docs/MARKET.md](docs/MARKET.md) for the release and index-refresh flow.
|
|
111
|
+
|
|
112
|
+
### Option C: Git repository
|
|
113
|
+
|
|
114
|
+
Plugins → Add plugin → paste `https://github.com/topmindspace/dsh-super-kanban` → install (DSH pins the source to a commit) → enable → reload the window.
|
|
115
|
+
|
|
116
|
+
### Option D: Local directory / source install
|
|
117
|
+
|
|
118
|
+
For developers and users who want to track the source:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
git clone https://github.com/topmindspace/dsh-super-kanban.git
|
|
122
|
+
cd dsh-super-kanban
|
|
123
|
+
./install.sh -y # link into the default desktop profile and register the plugin
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Or choose "local directory" in the DSH plugin page and point it at this repository root. After installing, reload the window and "任务看板" appears in the left sidebar.
|
|
127
|
+
|
|
128
|
+
### Upgrade and uninstall
|
|
129
|
+
|
|
130
|
+
- **Upgrade**: market / npm / Git installs update from the plugin page; source installs run `git pull` and reload the window.
|
|
131
|
+
- **Uninstall**: remove it from the plugin page, or run `./uninstall.sh -y` in the source directory.
|
|
132
|
+
- Uninstalling **does not delete** board data; to wipe it, delete `~/.dsh/storages/super-kanban/`.
|
|
133
|
+
|
|
134
|
+
Detailed installation, upgrade and troubleshooting steps are in [docs/INSTALL.md](docs/INSTALL.md).
|
|
135
|
+
|
|
136
|
+
## Usage
|
|
137
|
+
|
|
138
|
+
1. Click **任务看板** in the left sidebar (or the board icon in a conversation header for the right-sidebar form).
|
|
139
|
+
2. **Board**: four columns — Backlog / In progress / Blocked / Done; column headers show counts and status colors.
|
|
140
|
+
3. **Cards**: status dot, title with an AI/rules marker, a one-line goal summary, source workspace and last-activity time, plus restrained priority, issue count, artifact count, subtask progress and a progress line.
|
|
141
|
+
4. **Detail drawer** (click a card):
|
|
142
|
+
- One-line status summary (click "Edit" to change fields)
|
|
143
|
+
- **Key facts** (3–6 items: key progress / decisions / issues from the session)
|
|
144
|
+
- **Subtasks**: check / add / delete; "import todos from session"; progress writes back automatically
|
|
145
|
+
- **Issues / next steps**
|
|
146
|
+
- **Session linkage**: continue this task / open session
|
|
147
|
+
- **Artifacts**: click to open in the DSH right-sidebar document preview
|
|
148
|
+
- Evidence and history (collapsed by default)
|
|
149
|
+
5. **Filters**: workspace, priority, origin, tags, keyword search, show archived.
|
|
150
|
+
6. **Toolbar** (persistent in the header): search, scan, settings gear, open in right sidebar, new task; the "⋯" menu only contains "Export JSON".
|
|
151
|
+
7. **Scan**: click the scan button to trigger an incremental scan immediately; progress is shown live.
|
|
152
|
+
8. **Settings** (gear icon): AI toggle, auto-scan, scan interval, initial scan range, AI budget, display and entry, excluded workspaces.
|
|
153
|
+
|
|
154
|
+
### How "Continue this task" works
|
|
155
|
+
|
|
156
|
+
1. Open any card → click **"继续此任务"** in the drawer;
|
|
157
|
+
2. The dialog contains a structured prompt (task goal / progress / key facts / issues / next steps / source session) that you can edit;
|
|
158
|
+
3. Choose **original session** or **new session in the same workspace**;
|
|
159
|
+
4. Click **"放入会话"**: DSH switches to the target session and puts the prompt into the input box — **it is never sent automatically**; review or edit it and press send yourself. You can also "copy only" or "polish with AI".
|
|
160
|
+
|
|
161
|
+
> The prompt is assembled locally from a template — **0 tokens by default**. Only "Polish with AI" spends one model call.
|
|
162
|
+
|
|
163
|
+
### Manual and automatic side by side
|
|
164
|
+
|
|
165
|
+
- Automatic tasks are anchored to their source session; repeated scans update the same card instead of creating duplicates.
|
|
166
|
+
- Fields you edit and lock (editing locks by default) are never overwritten by AI; unlock them in the drawer to hand them back.
|
|
167
|
+
- Manual tasks (origin = manual) are never changed by automatic scans.
|
|
168
|
+
- New cards do not need a session; once linked, AI fills in the analysis on the next scan.
|
|
169
|
+
|
|
170
|
+
### Shortcuts
|
|
171
|
+
|
|
172
|
+
| Key | Action |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `/` | Focus search |
|
|
175
|
+
| `n` | New task |
|
|
176
|
+
| `Esc` | Close the topmost overlay / drawer |
|
|
177
|
+
| `Cmd+R` | Reload the DSH window (needed after plugin updates) |
|
|
178
|
+
|
|
179
|
+
## AI and privacy
|
|
180
|
+
|
|
181
|
+
### Data flow
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
DSH sessions (local, read-only)
|
|
185
|
+
│ local parsing / rules engine
|
|
186
|
+
▼
|
|
187
|
+
local board storage ──(optional)digest ≤1.5KB ──► DeepSeek inference API
|
|
188
|
+
│ │
|
|
189
|
+
└──────────── structured JSON ◄────────────────────┘
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### What is never uploaded
|
|
193
|
+
|
|
194
|
+
- Full session transcripts, file contents, attachments
|
|
195
|
+
- Account credentials / tokens (read locally for the request header only, never included in the payload)
|
|
196
|
+
- Anything to third-party servers (no telemetry, no usage reporting)
|
|
197
|
+
|
|
198
|
+
### Turning AI off
|
|
199
|
+
|
|
200
|
+
Settings gear in the board header → turn off "AI 联网研判" (online AI analysis); it takes effect immediately. The board keeps running on the local rules engine — no missing features, just coarser inference.
|
|
201
|
+
|
|
202
|
+
### Cost
|
|
203
|
+
|
|
204
|
+
By default incremental scans only analyze **changed sessions**; the per-scan AI call limit defaults to 40 and the default model is `deepseek-flash`. On days without new conversations the cost is close to zero. You can lower the daily limit or disable AI entirely in settings.
|
|
205
|
+
|
|
206
|
+
## Screenshots
|
|
207
|
+
|
|
208
|
+
| Board (light) | Board (dark) |
|
|
209
|
+
| --- | --- |
|
|
210
|
+
|  |  |
|
|
211
|
+
|
|
212
|
+
| Task details (light) | Task details (dark) |
|
|
213
|
+
| --- | --- |
|
|
214
|
+
|  |  |
|
|
215
|
+
|
|
216
|
+
| Continue-task dialog | Prompt placed into the session input |
|
|
217
|
+
| --- | --- |
|
|
218
|
+
|  |  |
|
|
219
|
+
|
|
220
|
+
| Right sidebar (narrow) | Right sidebar fullscreen |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
|  |  |
|
|
223
|
+
|
|
224
|
+
| Artifact preview entries | Settings (persistent gear) |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
|  |  |
|
|
227
|
+
|
|
228
|
+
| "⋯" menu (export JSON only) | 1280px window |
|
|
229
|
+
| --- | --- |
|
|
230
|
+
|  |  |
|
|
231
|
+
|
|
232
|
+
> All screenshots above use a fully fictional demo dataset (invented workspaces / sessions / tasks) and contain no real user or workspace information.
|
|
233
|
+
|
|
234
|
+
## Compatibility
|
|
235
|
+
|
|
236
|
+
| Item | Requirement |
|
|
237
|
+
| --- | --- |
|
|
238
|
+
| DeepSeek Harness | `>= 0.2.1-rc.5 < 0.3.0` (verified on 0.2.1-rc.5 desktop) |
|
|
239
|
+
| Node.js | `>= 22.19.0` (uses the built-in `node:zlib` zstd API) |
|
|
240
|
+
| Platform | Verified on macOS desktop; other desktop platforms should work but are not individually verified |
|
|
241
|
+
| Third-party dependencies | None (plugin and tooling scripts are dependency-free) |
|
|
242
|
+
|
|
243
|
+
> The plugin relies on DSH's third-party plugin interfaces; major DSH upgrades may break compatibility. If the entry disappears after upgrading DSH, reinstall the plugin first — board data will not be lost.
|
|
244
|
+
|
|
245
|
+
## FAQ
|
|
246
|
+
|
|
247
|
+
**Q: There is no "任务看板" in the left sidebar.**
|
|
248
|
+
A: Press `Cmd+R` to reload the window; restart DSH if it is still missing. If it remains missing, check the diagnostics on the DSH plugin page (a failed plugin load usually reports a reason).
|
|
249
|
+
|
|
250
|
+
**Q: Cards are not updating / still show an old status.**
|
|
251
|
+
A: Click the scan button in the header to trigger a manual scan, or check that "Auto scan" is enabled in settings.
|
|
252
|
+
|
|
253
|
+
**Q: The AI judgment is wrong.**
|
|
254
|
+
A: Open the card and edit the fields directly (editing locks them), or use "re-analyze" in the card menu to let AI look at the source session again.
|
|
255
|
+
|
|
256
|
+
**Q: I don't want certain workspaces on the board.**
|
|
257
|
+
A: Settings gear in the board header → Excluded workspaces (multi-select).
|
|
258
|
+
|
|
259
|
+
**Q: How much quota will this use?**
|
|
260
|
+
A: An incremental scan calls `deepseek-flash` once per **changed** session; the settings page shows today's calls and tokens. With AI disabled the cost is zero.
|
|
261
|
+
|
|
262
|
+
**Q: Where is the data? Is it lost after uninstalling?**
|
|
263
|
+
A: `~/.dsh/storages/super-kanban/` (`state.json` / `sessions-cache.json` / `backups/`). Uninstalling the plugin does not delete it.
|
|
264
|
+
|
|
265
|
+
**Q: Can I export the board?**
|
|
266
|
+
A: "⋯" in the board header → Export JSON, which downloads `super-kanban-YYYYMMDD.json`.
|
|
267
|
+
|
|
268
|
+
## Development and contributing
|
|
269
|
+
|
|
270
|
+
- Zero third-party dependencies; tests run with `node --test`; `scripts/` contains validators, the privacy scanner and the market index generator.
|
|
271
|
+
- Common commands:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
npm test # unit tests
|
|
275
|
+
npm run validate # manifest, cordis patch, files and market index checks
|
|
276
|
+
npm run check:privacy # scan for personal paths / credentials / session ids
|
|
277
|
+
npm run market:index # regenerate docs/index.json
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
- For the development setup, repository layout and debugging, see [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
|
|
281
|
+
- Architecture: [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). Interface contract: [docs/CONTRACT.md](docs/CONTRACT.md). Visual spec: [docs/DESIGN.md](docs/DESIGN.md).
|
|
282
|
+
- Release and distribution flow (market index, npm, Git): [docs/MARKET.md](docs/MARKET.md).
|
|
283
|
+
- For security issues, please follow [SECURITY.md](SECURITY.md) and report privately instead of opening a public issue.
|
|
284
|
+
|
|
285
|
+
## License
|
|
286
|
+
|
|
287
|
+
[MIT](LICENSE) © topmindspace
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Super Kanban · 智能任务指挥台
|
|
2
2
|
|
|
3
3
|
[](https://github.com/topmindspace/dsh-super-kanban/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/dsh-super-kanban)
|
|
4
5
|
[](LICENSE)
|
|
5
6
|
|
|
6
7
|
一个**生长在 DeepSeek Harness 界面里**的 AI 任务看板:它读取你各个工作区的真实 DSH 会话,自动研判任务的目标、进度、完成情况与问题,也可以完全手动管理。每张任务卡都能追溯到具体会话与具体一句话。
|
|
@@ -9,8 +10,12 @@
|
|
|
9
10
|
- **数据**:只读扫描本机 DSH 会话;看板数据保存在本机,不出本机
|
|
10
11
|
- **智能**:复用本机 DSH 已登录账号的模型额度,零配置;关闭后自动降级为本地规则分析
|
|
11
12
|
|
|
13
|
+
**简体中文** | [English](README.en.md)
|
|
14
|
+
|
|
12
15
|

|
|
13
16
|
|
|
17
|
+

|
|
18
|
+
|
|
14
19
|
## 目录
|
|
15
20
|
|
|
16
21
|
- [它解决什么](#它解决什么)
|
|
@@ -41,7 +46,7 @@ Super Kanban 把这些对话转成一张可持续维护的看板:
|
|
|
41
46
|
| 🤝 会话联动 | 「继续此任务」生成结构化提示词,确认后放入原会话或同工作区新会话输入框,不自动发送 |
|
|
42
47
|
| ✅ 子任务与目标 | 子任务清单(可从会话待办导入、勾选自动回写进度)、任务目标、DSH Session Goal 追踪 |
|
|
43
48
|
| 📦 产物跟踪 | 自动收集会话交付物与写出的文件,点击在 DSH 文档预览中打开 |
|
|
44
|
-
| 🧾 关键事实优先 |
|
|
49
|
+
| 🧾 关键事实优先 | 卡片先给一句话目标摘要;抽屉先看 3–6 条关键事实,完整证据默认折叠 |
|
|
45
50
|
| ✍️ 手动维护 | 新建 / 编辑 / 拖拽换列 / 归档 / 删除 / 锁定字段;你改过的字段 AI 不再覆盖 |
|
|
46
51
|
| 🔄 持续维护 | 首次约数秒完成扫描,之后按间隔增量扫描;新会话自动纳入,旧任务自动更新 |
|
|
47
52
|
| 🧠 解释得清 | 每条研判带置信度与一句话理由,避免「黑箱改状态」 |
|
|
@@ -79,7 +84,7 @@ Super Kanban 把这些对话转成一张可持续维护的看板:
|
|
|
79
84
|
| **右侧侧边栏** | 会话右上角看板图标,或会话右侧栏「+」工具列表里的「任务看板」 | 边聊边看板;宽度自适应:窄(单列 + 状态分段)/ 中 / 宽(四列) |
|
|
80
85
|
|
|
81
86
|
- **右侧栏全屏**:右侧栏顶部的全屏按钮,面板铺满视口,仍可随时退出。
|
|
82
|
-
-
|
|
87
|
+
- **互相切换**:全页看板页头的「在右侧栏打开」图标;右侧栏看板的「在全页面板打开」图标。
|
|
83
88
|
- **入口偏好**:看板「设置 → 显示与入口」可选「两者(默认)/ 仅全局面板 / 仅会话右侧栏」,修改后刷新窗口生效。
|
|
84
89
|
|
|
85
90
|
## 安装
|
|
@@ -100,9 +105,9 @@ Super Kanban 把这些对话转成一张可持续维护的看板:
|
|
|
100
105
|
|
|
101
106
|
### 方式 B:npm 包名
|
|
102
107
|
|
|
103
|
-
DSH → 插件 → 添加插件 → 输入包名 `dsh-super-kanban
|
|
108
|
+
DSH → 插件 → 添加插件 → 输入包名 `dsh-super-kanban`(可附加版本号,如 `dsh-super-kanban@<version>`)→ 安装 → 启用 → 刷新窗口。
|
|
104
109
|
|
|
105
|
-
> npm
|
|
110
|
+
> npm 包已发布:`dsh-super-kanban`(https://www.npmjs.com/package/dsh-super-kanban)。发布与索引更新流程见 [docs/MARKET.md](docs/MARKET.md)。
|
|
106
111
|
|
|
107
112
|
### 方式 C:Git 仓库
|
|
108
113
|
|
|
@@ -132,7 +137,7 @@ cd dsh-super-kanban
|
|
|
132
137
|
|
|
133
138
|
1. 左侧栏点 **任务看板**(或会话右上角看板图标走右侧栏形态)。
|
|
134
139
|
2. **看板**:四列——待办 / 进行中 / 受阻 / 已完成;列头显示数量与状态色。
|
|
135
|
-
3.
|
|
140
|
+
3. **卡片**:状态点、标题与 AI/规则标记、一句话目标摘要、来源工作区与最近活动时间,以及克制的优先级、问题数、产物数、子任务进度与进度线。
|
|
136
141
|
4. **详情抽屉**(点卡片打开):
|
|
137
142
|
- 一句话状态摘要(点「编辑」可改字段)
|
|
138
143
|
- **关键事实**(3–6 条,来自会话的关键进展 / 决策 / 问题)
|
|
@@ -142,8 +147,9 @@ cd dsh-super-kanban
|
|
|
142
147
|
- **产物**:点击在 DSH 右侧栏文档预览中打开
|
|
143
148
|
- 证据与历史(默认折叠)
|
|
144
149
|
5. **筛选**:工作区、优先级、来源、标签、关键词搜索、显示归档。
|
|
145
|
-
6.
|
|
146
|
-
7.
|
|
150
|
+
6. **工具栏**(页头常驻):搜索、扫描、设置齿轮、在右侧栏打开、新建;「⋯」只保留「导出 JSON」。
|
|
151
|
+
7. **扫描**:点扫描按钮立即增量扫描;扫描进度实时显示。
|
|
152
|
+
8. **设置**(齿轮图标):AI 开关、自动扫描、扫描间隔、初始扫描天数、AI 预算、显示与入口、排除工作区。
|
|
147
153
|
|
|
148
154
|
### 「继续此任务」怎么用
|
|
149
155
|
|
|
@@ -191,7 +197,7 @@ DSH 会话(本机只读)
|
|
|
191
197
|
|
|
192
198
|
### 关闭 AI
|
|
193
199
|
|
|
194
|
-
|
|
200
|
+
看板页头的设置齿轮 → 关闭「AI 联网研判」,立即生效。关闭后看板继续用本地规则引擎运行,功能不缺失,只是研判颗粒度更粗。
|
|
195
201
|
|
|
196
202
|
### 成本
|
|
197
203
|
|
|
@@ -215,13 +221,13 @@ DSH 会话(本机只读)
|
|
|
215
221
|
| --- | --- |
|
|
216
222
|
|  |  |
|
|
217
223
|
|
|
218
|
-
| 产物预览入口 |
|
|
224
|
+
| 产物预览入口 | 设置(齿轮常驻) |
|
|
219
225
|
| --- | --- |
|
|
220
226
|
|  |  |
|
|
221
227
|
|
|
222
|
-
| 1280 宽窗口 |
|
|
228
|
+
| 「⋯」菜单(仅导出 JSON) | 1280 宽窗口 |
|
|
223
229
|
| --- | --- |
|
|
224
|
-
|  |
|
|
230
|
+
|  |  |
|
|
225
231
|
|
|
226
232
|
> 以上截图来自一套完全虚构的演示数据(虚构工作区 / 会话 / 任务),不含任何真实用户或工作区信息。
|
|
227
233
|
|
|
@@ -248,16 +254,16 @@ A:点右上角扫描按钮手动触发;或检查设置中的「自动扫描
|
|
|
248
254
|
A:点开卡片直接改字段(编辑即锁定);也可以在卡片菜单里「重新研判」,让 AI 重新分析该任务的来源会话。
|
|
249
255
|
|
|
250
256
|
**Q:不想让某些工作区进看板?**
|
|
251
|
-
A
|
|
257
|
+
A:看板页头设置齿轮 → 排除工作区(可多选)。
|
|
252
258
|
|
|
253
259
|
**Q:会消耗我多少额度?**
|
|
254
|
-
A:扫描时对**有变化的**会话各调用一次 `deepseek-flash
|
|
260
|
+
A:扫描时对**有变化的**会话各调用一次 `deepseek-flash`;设置页可查看今日调用数与 tokens。关闭 AI 后完全零额度。
|
|
255
261
|
|
|
256
262
|
**Q:数据在哪里?卸载会丢吗?**
|
|
257
263
|
A:`~/.dsh/storages/super-kanban/`(`state.json` / `sessions-cache.json` / `backups/`)。卸载插件不删除数据。
|
|
258
264
|
|
|
259
265
|
**Q:能导出吗?**
|
|
260
|
-
A
|
|
266
|
+
A:看板页头「⋯」→ 导出 JSON,下载 `super-kanban-YYYYMMDD.json`。
|
|
261
267
|
|
|
262
268
|
## 开发与贡献
|
|
263
269
|
|
package/client.js
CHANGED
|
@@ -1265,6 +1265,73 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
1265
1265
|
.sk-page.is-side.sk-tier-narrow .sk-narrow-list{padding-top:10px}
|
|
1266
1266
|
.sk-page.is-side .sk-slimbar{padding-bottom:10px}
|
|
1267
1267
|
|
|
1268
|
+
|
|
1269
|
+
/* ======================= v0.4:克制的强调色 ======================= */
|
|
1270
|
+
.sk-page{--sk-brand-accent:var(--dsw-alias-state-business-primary,#4176e6)}
|
|
1271
|
+
.sk-dot{width:6px;height:6px;border-radius:50%;flex:none;display:inline-block}
|
|
1272
|
+
.sk-dot.is-total{background:color-mix(in srgb,var(--sk-ink) 45%,transparent)}
|
|
1273
|
+
.sk-dot.is-backlog{background:color-mix(in srgb,var(--sk-ink) 40%,transparent)}
|
|
1274
|
+
.sk-dot.is-in_progress{background:var(--sk-brand-accent)}
|
|
1275
|
+
.sk-dot.is-blocked{background:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1276
|
+
.sk-dot.is-done{background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 55%,transparent)}
|
|
1277
|
+
.sk-stats-group{display:inline-flex;align-items:center;gap:5px}
|
|
1278
|
+
.sk-stats-v3 .sk-status-dot{background:color-mix(in srgb,var(--sk-ink) 40%,transparent);box-shadow:none;width:6px;height:6px;opacity:1}
|
|
1279
|
+
.sk-stats-v3 .sk-status-dot.is-running{background:var(--sk-brand-accent);animation:skPulse 1.6s ease-in-out infinite}
|
|
1280
|
+
.sk-stats-v3 .sk-status-dot.is-error{background:var(--sk-red)}
|
|
1281
|
+
.sk-header-actions .sk-iconbtn-v3{width:28px;height:28px;border-radius:8px;color:color-mix(in srgb,var(--sk-ink) 62%,transparent)}
|
|
1282
|
+
.sk-header-actions .sk-iconbtn-v3:hover{background:color-mix(in srgb,var(--sk-ink) 6%,transparent);color:var(--sk-ink)}
|
|
1283
|
+
.sk-header-actions .sk-iconbtn-v3.is-primary{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground);border:1px solid transparent}
|
|
1284
|
+
.sk-header-actions .sk-iconbtn-v3.is-primary:hover{background:var(--dsw-alias-button-primary-hover);color:var(--dsw-alias-label-primary-foreground)}
|
|
1285
|
+
.sk-card-v3{padding:11px 14px 10px}
|
|
1286
|
+
.sk-card-v3.is-done{opacity:.7}
|
|
1287
|
+
.sk-card-v3.is-done .sk-card-title-v3{font-weight:500}
|
|
1288
|
+
.sk-card-v3-head{display:flex;align-items:flex-start;gap:7px;min-width:0}
|
|
1289
|
+
.sk-card-v3-head .sk-dot{margin-top:6px}
|
|
1290
|
+
.sk-card-v3-head .sk-card-title-v3{flex:1;min-width:0}
|
|
1291
|
+
.sk-ai-mark{font-size:11px;line-height:1;font-weight:500;letter-spacing:.02em;flex:none;white-space:nowrap;margin-top:4px}
|
|
1292
|
+
.sk-ai-mark.is-ai{color:color-mix(in srgb,var(--sk-brand-accent) 65%,transparent)}
|
|
1293
|
+
.sk-ai-mark.is-rules{color:color-mix(in srgb,var(--sk-ink) 45%,transparent)}
|
|
1294
|
+
.sk-card-meta-v3 .sk-card-metrics{gap:7px}
|
|
1295
|
+
.sk-card-metric{display:inline-flex;align-items:center;gap:3px;white-space:nowrap;color:color-mix(in srgb,var(--sk-ink) 45%,transparent);font-size:11px}
|
|
1296
|
+
.sk-card-metric .sk-icon{opacity:.9}
|
|
1297
|
+
.sk-card-metric.is-warn{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1298
|
+
.sk-card-metric.is-error{color:var(--sk-red)}
|
|
1299
|
+
.sk-card-metric.is-done{color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 75%,transparent)}
|
|
1300
|
+
.sk-card-metrics .sk-prio-text{font-size:11px;font-weight:500}
|
|
1301
|
+
.sk-prio-text.is-p0{color:var(--sk-red)}
|
|
1302
|
+
.sk-prio-text.is-p1{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1303
|
+
.sk-prio-text.is-rest{color:color-mix(in srgb,var(--sk-ink) 45%,transparent);font-weight:400}
|
|
1304
|
+
.sk-card-progress-v3{height:3px;border-radius:1.5px;background:color-mix(in srgb,var(--sk-ink) 10%,transparent)}
|
|
1305
|
+
.sk-card-progress-v3 i{background:color-mix(in srgb,var(--sk-ink) 20%,transparent);border-radius:1.5px}
|
|
1306
|
+
.sk-card-v3.is-in_progress .sk-card-progress-v3 i{background:color-mix(in srgb,var(--sk-brand-accent) 75%,transparent)}
|
|
1307
|
+
.sk-card-v3.is-blocked .sk-card-progress-v3 i{background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 75%,transparent)}
|
|
1308
|
+
.sk-card-v3.is-done .sk-card-progress-v3{display:block}
|
|
1309
|
+
.sk-card-v3.is-done .sk-card-progress-v3 i{background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 55%,transparent)}
|
|
1310
|
+
.sk-col-dot{width:6px;height:6px;border-radius:50%;flex:none;margin-right:2px}
|
|
1311
|
+
.sk-col-head .sk-dot{margin-right:2px}
|
|
1312
|
+
.sk-summary-status{font-weight:600}
|
|
1313
|
+
.sk-summary-status.is-in_progress{color:var(--sk-brand-accent)}
|
|
1314
|
+
.sk-summary-status.is-blocked{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1315
|
+
.sk-summary-status.is-done{color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 72%,transparent)}
|
|
1316
|
+
.sk-summary-prio{font-weight:500}
|
|
1317
|
+
.sk-summary-prio.is-p0{color:var(--sk-red)}
|
|
1318
|
+
.sk-summary-prio.is-p1{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1319
|
+
.sk-summary-prio.is-rest{color:color-mix(in srgb,var(--sk-ink) 55%,transparent);font-weight:400}
|
|
1320
|
+
.sk-fact{display:flex;align-items:flex-start;gap:8px;font-size:13px;line-height:1.5;color:color-mix(in srgb,var(--sk-ink) 78%,transparent);min-width:0}
|
|
1321
|
+
.sk-fact-icon{width:14px;height:14px;flex:none;display:grid;place-items:center;margin-top:2px;color:var(--fact-tone,color-mix(in srgb,var(--sk-ink) 45%,transparent))}
|
|
1322
|
+
.sk-fact-text{flex:1;min-width:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;overflow-wrap:anywhere}
|
|
1323
|
+
.sk-link-text{color:var(--sk-brand-accent)!important;text-decoration:none}
|
|
1324
|
+
.sk-link-text:hover{color:var(--sk-brand-accent);text-decoration:underline;text-underline-offset:2px}
|
|
1325
|
+
.sk-session-line .sk-session-icon{flex:none;color:color-mix(in srgb,var(--sk-ink) 55%,transparent);margin-top:1px}
|
|
1326
|
+
.sk-duo-item{display:flex;align-items:flex-start;gap:5px;font-size:12px;line-height:1.55;color:color-mix(in srgb,var(--sk-ink) 78%,transparent);overflow-wrap:anywhere}
|
|
1327
|
+
.sk-duo-item .sk-icon{flex:none;margin-top:2px;color:color-mix(in srgb,var(--sk-ink) 40%,transparent)}
|
|
1328
|
+
.sk-duo-item.is-warn{color:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#f59e0b) 85%,var(--sk-ink))}
|
|
1329
|
+
.sk-duo-item.is-warn .sk-icon{color:var(--dsw-alias-state-warn-primary,#f59e0b)}
|
|
1330
|
+
.sk-duo-item.is-error{color:var(--sk-red)}
|
|
1331
|
+
.sk-duo-item.is-error .sk-icon{color:var(--sk-red)}
|
|
1332
|
+
.sk-page.is-side.sk-tier-narrow .sk-card-v3-head .sk-dot{margin-top:5px}
|
|
1333
|
+
.sk-page.is-side.sk-tier-narrow .sk-ai-mark{display:none}
|
|
1334
|
+
|
|
1268
1335
|
`;
|
|
1269
1336
|
|
|
1270
1337
|
function ensureStyle() {
|
|
@@ -1417,25 +1484,22 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
1417
1484
|
function TaskCard({ task, onOpen, onDragStart, onDragEnd, dragging }) {
|
|
1418
1485
|
const progress = progressOf(task);
|
|
1419
1486
|
const subtasks = subtasksOf(task);
|
|
1420
|
-
const
|
|
1487
|
+
const issueList = Array.isArray(task.issues) ? task.issues : [];
|
|
1488
|
+
const issues = issueList.length;
|
|
1421
1489
|
const artifacts = artifactsOf(task);
|
|
1422
1490
|
const priority = task.priority || "P2";
|
|
1423
1491
|
const taskStatus = statusOf(task);
|
|
1424
1492
|
const done = taskStatus === "done";
|
|
1425
|
-
const
|
|
1426
|
-
const highIssue = (Array.isArray(task.issues) ? task.issues : []).some((issue) => issue && issue.severity === "high");
|
|
1493
|
+
const highIssue = issueList.some((issue) => issue && issue.severity === "high");
|
|
1427
1494
|
const subtaskDone = subtasks.filter((item) => item.done).length;
|
|
1428
|
-
const
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
: artifacts.length
|
|
1433
|
-
? `${artifacts.length} 产物`
|
|
1434
|
-
: "";
|
|
1495
|
+
const allSubtasksDone = subtasks.length > 0 && subtaskDone === subtasks.length;
|
|
1496
|
+
const engine = task.ai && task.ai.engine === "llm" ? "AI" : "规则";
|
|
1497
|
+
const showEngine = Boolean(task.ai) || task.origin === "auto" || task.origin === "auto+edited";
|
|
1498
|
+
const prioClass = priority === "P0" ? "is-p0" : priority === "P1" ? "is-p1" : "is-rest";
|
|
1435
1499
|
return h(
|
|
1436
1500
|
"article",
|
|
1437
1501
|
{
|
|
1438
|
-
className: cx("sk-card", "sk-card-v3", done && "is-done", dragging && "dragging"),
|
|
1502
|
+
className: cx("sk-card", "sk-card-v3", "is-" + taskStatus, done && "is-done", dragging && "dragging"),
|
|
1439
1503
|
draggable: true,
|
|
1440
1504
|
tabIndex: 0,
|
|
1441
1505
|
onDragStart: (event) => {
|
|
@@ -1456,13 +1520,11 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
1456
1520
|
h(
|
|
1457
1521
|
"div",
|
|
1458
1522
|
{ className: "sk-card-v3-head" },
|
|
1459
|
-
|
|
1460
|
-
? h("span", {
|
|
1461
|
-
className: cx("sk-card-warn-dot", highIssue && !blocked && "is-error"),
|
|
1462
|
-
title: blocked ? "受阻" : "存在高优先级问题",
|
|
1463
|
-
})
|
|
1464
|
-
: null,
|
|
1523
|
+
h("span", { className: cx("sk-dot", "is-" + taskStatus), title: STATUS_META[taskStatus].label }),
|
|
1465
1524
|
h("h3", { className: "sk-card-title-v3" }, task.title),
|
|
1525
|
+
showEngine
|
|
1526
|
+
? h("span", { className: cx("sk-ai-mark", engine === "AI" ? "is-ai" : "is-rules"), title: engine === "AI" ? "AI 研判" : "规则推断" }, engine)
|
|
1527
|
+
: null,
|
|
1466
1528
|
),
|
|
1467
1529
|
h(
|
|
1468
1530
|
"div",
|
|
@@ -1473,11 +1535,19 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
1473
1535
|
h(
|
|
1474
1536
|
"span",
|
|
1475
1537
|
{ className: "sk-card-metrics" },
|
|
1476
|
-
h("span", { className: cx("sk-prio-text",
|
|
1477
|
-
|
|
1538
|
+
h("span", { className: cx("sk-prio-text", prioClass), title: "优先级" }, priority),
|
|
1539
|
+
issues > 0
|
|
1540
|
+
? h("span", { className: cx("sk-card-metric", "is-warn", highIssue && "is-error"), title: `${issues} 个问题${highIssue ? "(含高优先级)" : ""}` }, h(Icon, { name: "alert", size: 10 }), issues)
|
|
1541
|
+
: null,
|
|
1542
|
+
artifacts.length > 0
|
|
1543
|
+
? h("span", { className: "sk-card-metric", title: `${artifacts.length} 个产物` }, h(Icon, { name: "file", size: 10 }), artifacts.length)
|
|
1544
|
+
: null,
|
|
1545
|
+
subtasks.length > 0
|
|
1546
|
+
? h("span", { className: cx("sk-card-metric", allSubtasksDone && "is-done"), title: `${subtaskDone}/${subtasks.length} 子任务` }, h(Icon, { name: "check", size: 10 }), `${subtaskDone}/${subtasks.length}`)
|
|
1547
|
+
: null,
|
|
1478
1548
|
),
|
|
1479
1549
|
),
|
|
1480
|
-
|
|
1550
|
+
h("div", { className: "sk-card-progress-v3" }, h("i", { style: { width: `${progress}%` } })),
|
|
1481
1551
|
);
|
|
1482
1552
|
}
|
|
1483
1553
|
|
|
@@ -1506,6 +1576,7 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
1506
1576
|
h(
|
|
1507
1577
|
"header",
|
|
1508
1578
|
{ className: "sk-col-head" },
|
|
1579
|
+
h("span", { className: cx("sk-dot", "is-" + status) }),
|
|
1509
1580
|
h("span", { className: "sk-col-title" }, meta.label),
|
|
1510
1581
|
h("span", { className: "sk-col-count" }, tasks.length),
|
|
1511
1582
|
h("span", { className: "sk-col-head-spacer" }),
|
|
@@ -2128,9 +2199,10 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2128
2199
|
: h(
|
|
2129
2200
|
"div",
|
|
2130
2201
|
{ className: "sk-summary-line" },
|
|
2131
|
-
h("span",
|
|
2202
|
+
h("span", { className: cx("sk-dot", "is-" + statusOf(task)) }),
|
|
2203
|
+
h("span", { className: cx("sk-summary-status", "is-" + statusOf(task)) }, STATUS_META[statusOf(task)].label),
|
|
2132
2204
|
h("span", { className: "sk-sep" }, "·"),
|
|
2133
|
-
h("span",
|
|
2205
|
+
h("span", { className: cx("sk-summary-prio", task.priority === "P0" ? "is-p0" : task.priority === "P1" ? "is-p1" : "is-rest") }, task.priority || "P2"),
|
|
2134
2206
|
h("span", { className: "sk-sep" }, "·"),
|
|
2135
2207
|
h("span", { className: "sk-muted" }, subtasks.length ? `${subtaskDone}/${subtasks.length} 子任务` : `进度 ${progress}%`),
|
|
2136
2208
|
goal && goal.text ? h("span", { className: "sk-goal-text" }, goal.text) : null,
|
|
@@ -2147,7 +2219,27 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2147
2219
|
facts.length > 3 ? h("button", { type: "button", className: "sk-text", onClick: () => setFactsExpanded((value) => !value) }, factsExpanded ? "收起" : `展开全部 ${facts.length} 条`) : null,
|
|
2148
2220
|
),
|
|
2149
2221
|
facts.length
|
|
2150
|
-
? h(
|
|
2222
|
+
? h(
|
|
2223
|
+
"div",
|
|
2224
|
+
{ className: "sk-facts" },
|
|
2225
|
+
(factsExpanded ? facts : facts.slice(0, 3)).map((fact) => {
|
|
2226
|
+
const meta = factMeta(fact.kind);
|
|
2227
|
+
const tone =
|
|
2228
|
+
fact.kind === "progress"
|
|
2229
|
+
? "var(--sk-brand-accent)"
|
|
2230
|
+
: fact.kind === "issue"
|
|
2231
|
+
? "var(--dsw-alias-state-warn-primary,#f59e0b)"
|
|
2232
|
+
: fact.kind === "artifact"
|
|
2233
|
+
? "color-mix(in srgb,var(--dsw-alias-state-success-primary,#22c55e) 80%,transparent)"
|
|
2234
|
+
: "color-mix(in srgb,var(--sk-ink) 45%,transparent)";
|
|
2235
|
+
return h(
|
|
2236
|
+
"div",
|
|
2237
|
+
{ key: fact.id, className: "sk-fact" },
|
|
2238
|
+
h("span", { className: "sk-fact-icon", style: { "--fact-tone": tone } }, h(Icon, { name: meta.icon, size: 14 })),
|
|
2239
|
+
h("span", { className: "sk-fact-text" }, fact.text),
|
|
2240
|
+
);
|
|
2241
|
+
}),
|
|
2242
|
+
)
|
|
2151
2243
|
: h("div", { className: "sk-note-tiny" }, "暂无关键事实"),
|
|
2152
2244
|
),
|
|
2153
2245
|
h(
|
|
@@ -2199,14 +2291,32 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2199
2291
|
"div",
|
|
2200
2292
|
{ className: "sk-duo-col" },
|
|
2201
2293
|
issues.length
|
|
2202
|
-
? issues.slice(0, 3).map((issue, index) =>
|
|
2294
|
+
? issues.slice(0, 3).map((issue, index) =>
|
|
2295
|
+
h(
|
|
2296
|
+
"div",
|
|
2297
|
+
{
|
|
2298
|
+
key: issue.id || index,
|
|
2299
|
+
className: cx("sk-duo-item", issue.severity === "high" ? "is-error" : issue.severity === "medium" ? "is-warn" : ""),
|
|
2300
|
+
title: issue.text,
|
|
2301
|
+
},
|
|
2302
|
+
h(Icon, { name: "alert", size: 11 }),
|
|
2303
|
+
h("span", null, issue.text),
|
|
2304
|
+
),
|
|
2305
|
+
)
|
|
2203
2306
|
: h("div", { className: "sk-note-tiny" }, "暂无"),
|
|
2204
2307
|
),
|
|
2205
2308
|
h(
|
|
2206
2309
|
"div",
|
|
2207
2310
|
{ className: "sk-duo-col" },
|
|
2208
2311
|
nextSteps.length
|
|
2209
|
-
? nextSteps.slice(0, 3).map((step, index) =>
|
|
2312
|
+
? nextSteps.slice(0, 3).map((step, index) =>
|
|
2313
|
+
h(
|
|
2314
|
+
"div",
|
|
2315
|
+
{ key: index, className: "sk-duo-item", title: step },
|
|
2316
|
+
h(Icon, { name: "arrow", size: 11 }),
|
|
2317
|
+
h("span", null, step),
|
|
2318
|
+
),
|
|
2319
|
+
)
|
|
2210
2320
|
: h("div", { className: "sk-note-tiny" }, "暂无"),
|
|
2211
2321
|
),
|
|
2212
2322
|
),
|
|
@@ -2220,11 +2330,12 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2220
2330
|
{ className: "sk-drawer-sec-head" },
|
|
2221
2331
|
h("span", { className: "sk-drawer-sec-title" }, "会话"),
|
|
2222
2332
|
h("span", { className: "sk-grow" }),
|
|
2223
|
-
h("button", { type: "button", className: "sk-text", onClick: openSession, disabled: !session.sessionId }, "打开"),
|
|
2333
|
+
h("button", { type: "button", className: "sk-text sk-link-text", onClick: openSession, disabled: !session.sessionId }, "打开"),
|
|
2224
2334
|
),
|
|
2225
2335
|
h(
|
|
2226
2336
|
"div",
|
|
2227
2337
|
{ className: "sk-session-line" },
|
|
2338
|
+
h(Icon, { name: "chat", size: 14, className: "sk-session-icon" }),
|
|
2228
2339
|
h("span", { className: cx("sk-live-dot", !session.isLive && "off") }),
|
|
2229
2340
|
h("span", { className: "sk-session-title", title: session.title }, session.title || "未关联会话"),
|
|
2230
2341
|
),
|
|
@@ -2944,13 +3055,13 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2944
3055
|
const statsLine = h(
|
|
2945
3056
|
React.Fragment,
|
|
2946
3057
|
null,
|
|
2947
|
-
`${stats.total || tasks.length}
|
|
3058
|
+
h("span", { className: "sk-stats-group" }, h("span", { className: "sk-dot is-total" }), `${stats.total || tasks.length} 项`),
|
|
2948
3059
|
h("span", { className: "sk-sep" }, "·"),
|
|
2949
|
-
`${(stats.byStatus && stats.byStatus.in_progress) || 0}
|
|
3060
|
+
h("span", { className: "sk-stats-group" }, h("span", { className: "sk-dot is-in_progress" }), `${(stats.byStatus && stats.byStatus.in_progress) || 0} 进行中`),
|
|
2950
3061
|
h("span", { className: "sk-sep" }, "·"),
|
|
2951
|
-
`${(stats.byStatus && stats.byStatus.blocked) || 0}
|
|
3062
|
+
h("span", { className: "sk-stats-group" }, h("span", { className: "sk-dot is-blocked" }), `${(stats.byStatus && stats.byStatus.blocked) || 0} 受阻`),
|
|
2952
3063
|
h("span", { className: "sk-sep" }, "·"),
|
|
2953
|
-
`${(stats.byStatus && stats.byStatus.done) || 0}
|
|
3064
|
+
h("span", { className: "sk-stats-group" }, h("span", { className: "sk-dot is-done" }), `${(stats.byStatus && stats.byStatus.done) || 0} 完成`),
|
|
2954
3065
|
h("span", { className: "sk-sep" }, "·"),
|
|
2955
3066
|
scanRunning
|
|
2956
3067
|
? h(
|
|
@@ -2997,19 +3108,7 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
2997
3108
|
if (!ok) pushToast("当前环境不支持全屏切换", "error");
|
|
2998
3109
|
};
|
|
2999
3110
|
|
|
3000
|
-
const
|
|
3001
|
-
{ label: "设置", icon: "settings", onClick: () => setSettingsOpen(true) },
|
|
3002
|
-
{ label: "在右侧栏打开", icon: "panelRight", onClick: openSideFromPage },
|
|
3003
|
-
{ label: "导出 JSON", icon: "file", onClick: exportJson },
|
|
3004
|
-
];
|
|
3005
|
-
const sideMenuItems = [
|
|
3006
|
-
{ label: "新建任务", icon: "plus", onClick: () => setNewTaskStatus("backlog") },
|
|
3007
|
-
{ label: "设置", icon: "settings", onClick: () => setSettingsOpen(true) },
|
|
3008
|
-
{ label: "在全页面板打开", icon: "layout", onClick: openPageFromSide },
|
|
3009
|
-
{ label: "全屏", icon: "maximize", onClick: goFullscreen },
|
|
3010
|
-
"divider",
|
|
3011
|
-
{ label: "导出 JSON", icon: "file", onClick: exportJson },
|
|
3012
|
-
];
|
|
3111
|
+
const exportMenuItems = [{ label: "导出 JSON", icon: "file", onClick: exportJson }];
|
|
3013
3112
|
|
|
3014
3113
|
const scanButton = h(
|
|
3015
3114
|
"button",
|
|
@@ -3022,16 +3121,28 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
3022
3121
|
},
|
|
3023
3122
|
h(Icon, { name: scanRunning ? "stop" : "refresh", size: 15 }),
|
|
3024
3123
|
);
|
|
3124
|
+
const actionIcon = (name, title, onClick, extraClass) =>
|
|
3125
|
+
h(
|
|
3126
|
+
"button",
|
|
3127
|
+
{ type: "button", className: cx("sk-iconbtn-v3", extraClass), title, "aria-label": title, onClick },
|
|
3128
|
+
h(Icon, { name, size: 15 }),
|
|
3129
|
+
);
|
|
3025
3130
|
const moreButton = (items) =>
|
|
3026
3131
|
h(
|
|
3027
3132
|
DropMenu,
|
|
3028
3133
|
{ open: moreOpen, onClose: () => setMoreOpen(false), items },
|
|
3029
3134
|
h(
|
|
3030
3135
|
"button",
|
|
3031
|
-
{ type: "button", className: "sk-iconbtn-v3", title: "
|
|
3136
|
+
{ type: "button", className: "sk-iconbtn-v3", title: "更多(导出)", onClick: () => setMoreOpen((value) => !value) },
|
|
3032
3137
|
h(Icon, { name: "more", size: 15 }),
|
|
3033
3138
|
),
|
|
3034
3139
|
);
|
|
3140
|
+
const settingsButton = actionIcon("settings", "设置", () => setSettingsOpen(true));
|
|
3141
|
+
const newTextButton = h(
|
|
3142
|
+
"button",
|
|
3143
|
+
{ type: "button", className: "sk-btn-primary-v3", onClick: () => setNewTaskStatus("backlog"), title: "新建任务(n)" },
|
|
3144
|
+
"新建",
|
|
3145
|
+
);
|
|
3035
3146
|
|
|
3036
3147
|
const headerNode =
|
|
3037
3148
|
surface === "side"
|
|
@@ -3039,7 +3150,15 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
3039
3150
|
"header",
|
|
3040
3151
|
{ className: "sk-header-v3" },
|
|
3041
3152
|
h("p", { className: "sk-stats-v3" }, statsLine),
|
|
3042
|
-
h(
|
|
3153
|
+
h(
|
|
3154
|
+
"div",
|
|
3155
|
+
{ className: "sk-header-actions" },
|
|
3156
|
+
scanButton,
|
|
3157
|
+
settingsButton,
|
|
3158
|
+
prefs.fullEntry ? actionIcon("layout", "在全页面板打开", openPageFromSide) : null,
|
|
3159
|
+
actionIcon("plus", "新建任务", () => setNewTaskStatus("backlog"), "is-primary"),
|
|
3160
|
+
moreButton(exportMenuItems),
|
|
3161
|
+
),
|
|
3043
3162
|
)
|
|
3044
3163
|
: h(
|
|
3045
3164
|
"header",
|
|
@@ -3065,12 +3184,10 @@ body[data-ds-dark-theme] .sk-btn-primary-v3:hover{background:var(--dsw-alias-but
|
|
|
3065
3184
|
}),
|
|
3066
3185
|
),
|
|
3067
3186
|
scanButton,
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
"新建",
|
|
3073
|
-
),
|
|
3187
|
+
settingsButton,
|
|
3188
|
+
prefs.sideEntry ? actionIcon("panelRight", "在右侧栏打开", openSideFromPage) : null,
|
|
3189
|
+
newTextButton,
|
|
3190
|
+
moreButton(exportMenuItems),
|
|
3074
3191
|
),
|
|
3075
3192
|
);
|
|
3076
3193
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-super-kanban",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "AI task kanban for DeepSeek Harness: derives task goals, progress, completion and issues from DSH sessions, with key facts, subtasks, artifacts, session hand-off and a dual full-page/right-sidebar UI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.mjs",
|