@gavinc-cn/touchstone-dsh 0.0.0-stage → 0.1.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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +336 -2
  3. package/README.zh.md +318 -0
  4. package/agents.py +247 -0
  5. package/auth.py +86 -0
  6. package/board.py +4551 -0
  7. package/builtin_assets.py +808 -0
  8. package/builtin_prompts/free_style/flow.md +301 -0
  9. package/builtin_prompts/free_style/load_test.md +114 -0
  10. package/builtin_prompts/free_style/templates/bug_report_template.md +41 -0
  11. package/builtin_prompts/free_style/templates/case_template.md +23 -0
  12. package/builtin_prompts/free_style/templates/index_template.md +41 -0
  13. package/builtin_prompts/free_style/templates/load_charts_template.md +104 -0
  14. package/builtin_prompts/free_style/templates/load_index_template.md +5 -0
  15. package/builtin_prompts/free_style/templates/load_plan_template.md +76 -0
  16. package/builtin_prompts/free_style/templates/load_scenario_template.md +49 -0
  17. package/builtin_prompts/free_style/templates/status_template.md +18 -0
  18. package/chat.py +616 -0
  19. package/db.py +1407 -0
  20. package/dsh-plugin/cordis.patch.yml +21 -0
  21. package/dsh-plugin/install.sh +79 -0
  22. package/dsh-plugin/lib/agent-driver.js +2036 -0
  23. package/dsh-plugin/lib/client.bundle.js +397 -0
  24. package/dsh-plugin/lib/index.js +443 -0
  25. package/dsh-plugin/scripts/build.mjs +37 -0
  26. package/dsh-plugin/scripts/prepack-check.mjs +61 -0
  27. package/dsh-plugin/scripts/select-bundle.mjs +51 -0
  28. package/dsh-plugin/src/client.js +384 -0
  29. package/dshdriver.py +702 -0
  30. package/dshevents.py +470 -0
  31. package/export_cases.py +160 -0
  32. package/extensions/dsh-autocommit/asset.json +18 -0
  33. package/extensions/dsh-autocommit/pkg/lib/index.mjs +361 -0
  34. package/extensions/dsh-autocommit/pkg/package.json +10 -0
  35. package/feishu.py +2160 -0
  36. package/lib.py +245 -0
  37. package/lifecycle.py +417 -0
  38. package/loadcase.py +558 -0
  39. package/loadgen.py +678 -0
  40. package/localbus.py +91 -0
  41. package/migrate_p7b.py +191 -0
  42. package/package.json +79 -4
  43. package/platcompat.py +272 -0
  44. package/prompts.py +666 -0
  45. package/rag.py +553 -0
  46. package/requirements.txt +9 -0
  47. package/runner.py +2482 -0
  48. package/server.py +5379 -0
  49. package/sessparse.py +732 -0
  50. package/touchstone.py +513 -0
  51. package/waitq.py +1319 -0
  52. package/webui/dist-plugin/assets/index-B0WoP1Qy.css +1 -0
  53. package/webui/dist-plugin/assets/index-DtwKoi1T.js +473 -0
  54. package/webui/dist-plugin/index.html +18 -0
  55. package/worktree.py +393 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Touchstone contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,337 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # Touchstone
4
+
5
+ **An AI-agent-driven automated testing platform.** Point it at a repository; it explores the code, writes and runs test cases, files what breaks, fixes it, and re-verifies the fix.
6
+
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
+ [![npm](https://img.shields.io/npm/v/@gavinc-cn/touchstone-dsh?logo=npm&color=cb3837)](https://www.npmjs.com/package/@gavinc-cn/touchstone-dsh)
9
+ [![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-3776AB.svg)](https://www.python.org/)
10
+ [![Node 22.19+ | 24+](https://img.shields.io/badge/Node-22.19%2B%20%7C%2024%2B-339933.svg)](https://nodejs.org/)
11
+ [![DeepSeek Harness plugin](https://img.shields.io/badge/DeepSeek%20Harness-plugin-4D6BFE.svg)](https://github.com/deepseek-ai/deepseek-harness)
12
+
13
+ English | [中文](README.zh.md)
14
+
15
+ <img src="docs/images/board.png" alt="Touchstone development board" width="920">
16
+
17
+ </div>
18
+
19
+ ## What is Touchstone?
20
+
21
+ Touchstone turns "we really should test more" into a running loop. You register a project — its source
22
+ directory, a working directory, an environment label, and the house rules the agent must follow — and
23
+ Touchstone drives an AI agent through [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
24
+ (`dsh`) to **generate test cases, execute them, report failures as bug reports, fix the code, and
25
+ re-verify the fix**. Every artifact lands on disk in a reviewable form: a case library of Markdown case
26
+ files, a `bug_report/` directory, and per-round logs.
27
+
28
+ It is not a one-shot "run my test suite" CLI. Touchstone is built around **long-lived, multi-round agent
29
+ sessions**: a task runs round after round in the same session with its context intact, so the agent
30
+ remembers what it already tried. A unified queue keeps exactly one writer per project (no two agents
31
+ editing the same checkout at once), and the whole thing is observable — live round logs, a rendered
32
+ session window, and an SSE-backed board.
33
+
34
+ Touchstone runs **locally**. It is a Python web site with a SQLite database and a file-system workspace;
35
+ no data leaves your machine except for the model calls your `dsh` host makes.
36
+
37
+ ## Highlights
38
+
39
+ - **Six task types** covering the whole QA loop — exploration, regression, stress, fix, retest, and case
40
+ revision — each following a seven-stage lifecycle (generate cases → execute → report → analyze → fix →
41
+ deploy → retest).
42
+ - **A case library, not a test log.** Cases are human-readable Markdown (`case.md` + `status.md` per
43
+ case, plus an `INDEX.md` per directory). Agents read and extend them across tasks; you can fix a bad
44
+ case by editing a file.
45
+ - **Bug reports as first-class artifacts.** Failures are written up as structured reports (severity,
46
+ reproduction steps, log evidence, related cases) and can be routed back into fix / retest / case-revision
47
+ tasks from the UI.
48
+ - **Unified per-project queue.** Tasks, board cards, and chat messages all take the same serial slot per
49
+ project; queue position, the current holder, and evidence are queryable rather than guessed.
50
+ - **A board for agent-driven development.** Kanban cards start, queue, block, and complete agent sessions;
51
+ cards can run in an isolated `git worktree` so exploratory work never touches your main checkout.
52
+ - **Observable sessions.** Render the full transcript of any agent session (messages, reasoning, tool
53
+ calls, results), reply to it, inject into the running turn, compact it, fork it, or rewind to an earlier
54
+ point through a fork.
55
+ - **Stress testing built in.** A stress task asks the agent for a scenario + script; the platform then
56
+ drives the load itself, N runs per task, with per-run metrics, charts, and Markdown/JSON reports.
57
+ - **Optional integrations.** Feishu (Lark) push notifications with two-way answering from chat cards, and
58
+ RAG-based semantic search over the case library.
59
+ - **Self-contained stack.** Backend: Python standard library plus four small dependencies. Frontend: React
60
+ + Vite. Storage: SQLite + plain files. Runs on Linux and Windows.
61
+
62
+ ## Screenshots
63
+
64
+ The development board — cards per column, task entries inline, per-project queue badges:
65
+
66
+ ![Development board](docs/images/board.png)
67
+
68
+ Test tasks — six task types, round counts, statuses, and per-task actions:
69
+
70
+ ![Test tasks](docs/images/tasks.png)
71
+
72
+ The session window — the full agent transcript rendered from the `dsh` session store, with reply,
73
+ approval, and model controls:
74
+
75
+ ![Session window](docs/images/session.png)
76
+
77
+ Card detail — description, scheduling, dependent cards, bound sessions, and comments:
78
+
79
+ ![Card detail](docs/images/card-detail.png)
80
+
81
+ ## How it works
82
+
83
+ ```mermaid
84
+ flowchart LR
85
+ U[Browser] -->|REST + SSE| S["Touchstone server<br/>Python stdlib · SQLite · files"]
86
+ S -->|"/touchstone-agent<br/>resident sessions"| D["dsh host<br/>DeepSeek Harness"]
87
+ D -->|"read / edit / bash"| R["Your repository"]
88
+ D --> C[("Case library<br/>free_style/")]
89
+ D --> B[("Bug reports<br/>bug_report/")]
90
+ S --- C
91
+ S --- B
92
+ ```
93
+
94
+ 1. **You create a project.** Touchstone stores the repository path, a work directory, the environment
95
+ label, optional project skills, and free-form guidance that is injected into every first-round prompt.
96
+ 2. **You create a task.** Pick a type (say, *Exploration*) and an end stage (say, *report*), and Touchstone
97
+ queues it for that project.
98
+ 3. **Rounds run in a resident agent session.** Touchstone asks the `dsh` plugin to create or resume a
99
+ session and sends the round prompt. Rounds stream back to the UI and to
100
+ `<work_dir>/.web/task_<id>_round_<n>.log` as they happen.
101
+ 4. **Artifacts land in your work directory.** New cases under `free_style/`, bug reports under
102
+ `bug_report/`, monitoring state under `.live/`. You review them like code.
103
+ 5. **Follow-up tasks close the loop.** A report can spawn a fix task, a fix can spawn a retest, and a
104
+ rejected report can spawn a case-revision task. When a task's end stage goes past "report", the
105
+ platform appends the downstream stages as a follow-up task automatically.
106
+
107
+ ### Task types
108
+
109
+ | Type | What the agent does | Typical end stage |
110
+ |------|---------------------|-------------------|
111
+ | Exploration | Reads the code and writes new test cases into the case library | Report |
112
+ | Regression | Re-runs existing cases (optionally limited to a commit date range) | Report |
113
+ | Stress | Produces a load scenario + driver script, then the platform runs the load | Report |
114
+ | Fix | Analyzes a bug report, patches the code, deploys, and re-tests | Fix / Deploy / Retest |
115
+ | Retest | Re-verifies one bug report (retest only, deploy + retest, or deploy only) | Retest |
116
+ | Case revision | Rejects a bug report as a bad case and rewrites the case instead | Revision |
117
+
118
+ ### Core concepts
119
+
120
+ | Concept | Meaning |
121
+ |---------|---------|
122
+ | Project | A repository plus its work directory, agent binding, environment label, and guidance |
123
+ | Task | One queued unit of work: a task type, a stage range, a stop condition, and a round history |
124
+ | Round | One prompt/response cycle in the task's agent session |
125
+ | Case library | `<work_dir>/free_style/` — Markdown cases, status files, and per-directory indexes |
126
+ | Bug report | `<work_dir>/bug_report/<timestamp>_FS_<title>/` — the failure dossier for a case |
127
+ | Card | A board item that can start, queue, and drive its own agent session |
128
+ | Queue | The per-project serial slot shared by tasks, cards, and chat messages |
129
+
130
+ ## Quick start
131
+
132
+ ### Prerequisites
133
+
134
+ | Requirement | Version | Needed for |
135
+ |-------------|---------|------------|
136
+ | Python | 3.12+ | The server (verified on 3.12) |
137
+ | Node.js | 22.19+ or 24+ | Running the `dsh` host (the front-end build alone needs Node 18+) |
138
+ | DeepSeek Harness (`dsh`) | current release | Agent execution — required for plugin mode |
139
+
140
+ ### 1. Clone and install
141
+
142
+ ```bash
143
+ git clone https://github.com/gavinc-cn/touchstone-dsh.git
144
+ cd touchstone-dsh
145
+ python3 -m pip install -r requirements.txt
146
+ ```
147
+
148
+ ### 2. Start the site (standalone mode)
149
+
150
+ ```bash
151
+ ./touchstone.sh start # builds the front end on first run, then serves 127.0.0.1:4601
152
+ ./touchstone.sh status # PID and the actual port
153
+ ./touchstone.sh stop
154
+ ```
155
+
156
+ Then open <http://127.0.0.1:4601>.
157
+
158
+ The first start seeds an `admin` account. If `TS_ADMIN_PASSWORD` is not set, a random one-time password
159
+ is generated and printed **once** in the startup banner:
160
+
161
+ ```bash
162
+ grep '一次性初始口令' .run/server.log # or: ./touchstone.sh status
163
+ ```
164
+
165
+ You will be asked to change it on first login. Set `TS_ADMIN_PASSWORD=<your-password>` before the first
166
+ start to skip the one-time password (and the forced change).
167
+
168
+ > Standalone mode gives you the full site — projects, case library, bug reports, board, queue, monitoring —
169
+ > but **agent execution needs plugin mode** (below), because the agent runs inside the `dsh` host process.
170
+
171
+ ### 3. Run as a `dsh` plugin (recommended: enables agent execution)
172
+
173
+ The plugin embeds Touchstone in the `dsh` Web UI as a sidebar entry and panel, and lets Touchstone drive
174
+ resident agent sessions in the host process.
175
+
176
+ **Option A — from npm (self-contained package: whole platform + prebuilt front end):**
177
+
178
+ ```bash
179
+ npx @deepseek-ai/dsh web # 1) start the dsh host once (creates ~/.dsh/profiles/web)
180
+ dsh plugin --profile web add @gavinc-cn/touchstone-dsh # 2) install the plugin package
181
+ # 3) select the bundle in the profile manifest (the Plugins panel toggle does the same thing):
182
+ node ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/dsh-plugin/scripts/select-bundle.mjs \
183
+ ~/.dsh/profiles/web/package.json
184
+ # 4) restart the dsh web UI, open http://127.0.0.1:3080, use the Touchstone entry (Alt+T toggles the panel)
185
+ ```
186
+
187
+ The platform's own Python dependencies are installed with pip, not npm:
188
+
189
+ ```bash
190
+ pip install -r ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/requirements.txt
191
+ ```
192
+
193
+ No `repoDir` is needed: the package carries `server.py` and `webui/dist-plugin`, so the plugin falls back to
194
+ its own directory.
195
+
196
+ **Option B — from a checkout (development):**
197
+
198
+ ```bash
199
+ cd touchstone-dsh
200
+ ./dsh-plugin/install.sh # idempotent install of this checkout into the profile
201
+ ```
202
+
203
+ The installer prints the optional profile patch for pointing the plugin at your working copy (or picking a
204
+ specific interpreter); skip it to use the package's own directory:
205
+
206
+ ```yaml
207
+ - id: touchstone
208
+ config: { repoDir: /path/to/touchstone-dsh, pythonPath: /path/to/python3 }
209
+ ```
210
+
211
+ Both run modes share one database (`~/.touchstone/touchstone.db` by default) and are mutually exclusive
212
+ while running; the second instance refuses to start and tells you who holds the lock.
213
+
214
+ ### Windows
215
+
216
+ A cross-platform launcher offers the same commands:
217
+
218
+ ```bash
219
+ python touchstone.py start | stop | restart | status | build | test
220
+ ```
221
+
222
+ ### First steps in the UI
223
+
224
+ 1. Sign in and open **Settings → Change password** if you used the one-time password.
225
+ 2. **Add project** — source directory, work directory (defaults to `<project>/.touchstone`), environment
226
+ label, and the guidance the agent should follow. The case library and bug report directories are
227
+ derived and created for you.
228
+ 3. Create a task (or a board card) and let the queue pick it up. Round logs stream live; the session window
229
+ shows the transcript as it grows.
230
+
231
+ ## Configuration
232
+
233
+ | Variable | Default | Purpose |
234
+ |----------|---------|---------|
235
+ | `TS_PORT` / `TS_HOST` | `4601` / `127.0.0.1` | Listen address. Use `TS_HOST=0.0.0.0` to expose the site on your LAN |
236
+ | `TS_PYTHON` | `python3` | Interpreter used by the launcher (must have the runtime dependencies) |
237
+ | `TOUCHSTONE_DB` | `~/.touchstone/touchstone.db` | SQLite database. Must live on a local disk — file locking does not work on CIFS/network shares |
238
+ | `TS_ADMIN_PASSWORD` | *(random, printed once)* | Initial `admin` password; setting it skips the forced change |
239
+ | `TS_WEB_DIR` | `webui/dist` | Static front-end directory the server serves |
240
+ | `TOUCHSTONE_RUN_DIR` | `.run/` in the repository | PID / log / port files |
241
+ | `TS_EXT_DIR` | `extensions` | Root of the built-in asset manifests |
242
+ | `TS_ARCHIVE_SYNC` | `1` | Keep board "Done" and `dsh` session archive in sync (set `0` to disable) |
243
+ | `TS_DSH_PROFILE` / `TS_DSH_PYTHON` | `web` / auto-detected | `dsh` profile and interpreter used by the plugin installer |
244
+
245
+ Runtime paths inside a project's work directory:
246
+
247
+ | Path | Contents |
248
+ |------|----------|
249
+ | `free_style/` | Case library (cases, status files, indexes) |
250
+ | `bug_report/` | Bug reports, one directory per report |
251
+ | `.web/` | Round logs, chat logs, stress metrics and reports |
252
+ | `.live/live.json` | Agent live state used by the monitoring page |
253
+ | `board_media/` | Attachments pasted onto board cards |
254
+
255
+ ## Capabilities and limits
256
+
257
+ | Area | Supported |
258
+ |------|-----------|
259
+ | Agent sessions | Create, resume, reply, inject into the running turn, cancel, compact, fork, rewind-by-fork, model and permission-preset switching |
260
+ | Session observability | Full transcript rendering, archive state, attachment preview, live status stream (no polling) |
261
+ | Tasks | Six types, seven stages, stop conditions, date-range scoping, per-round logs, restart, continue |
262
+ | Board | Cards across five columns, drag & drop, queue position, parent dependencies, scheduled start, trash, isolated worktrees |
263
+ | Case library | Derived indexes, change-based retest triage, optional semantic (RAG) search |
264
+ | Stress testing | Scenario validation, concurrent load, second-by-second metrics, charts, Markdown/JSON reports per run |
265
+ | Notifications | Feishu (Lark) outbound push, inbound commands, and answering questions from chat cards |
266
+ | Multi-user | Login, admin/user roles, per-project ownership checks on every project-scoped endpoint |
267
+
268
+ Known limitations, stated plainly:
269
+
270
+ - **The UI is currently Chinese-only.**
271
+ - **Agent execution requires plugin mode**; standalone mode is the site without the agent.
272
+ - **Rewind and "compact into a new session" are approximations** — rewind starts a new branch at an
273
+ earlier point (the original session is kept), rather than truncating in place.
274
+ - **No error banner for failed model requests** — `dsh` has no event for it, so the session window shows
275
+ what the host reported and nothing more.
276
+ - **The Windows launcher is implemented but `dsh` itself has not been verified on Windows yet.**
277
+ - **End-to-end test scripts are not distributed** in this repository (see below), so `test-full` and
278
+ `test-ui` report a skip rather than running.
279
+
280
+ ## Repository layout
281
+
282
+ ```
283
+ touchstone-dsh/
284
+ ├── server.py HTTP site: routing, auth, REST, SSE, static front end
285
+ ├── runner.py Task execution engine and per-project scheduling
286
+ ├── waitq.py Unified queue model (the single source of truth for "who runs next")
287
+ ├── board.py Development board: cards, gates, agent sessions, archive sync
288
+ ├── chat.py Session chat: queued messages and injection
289
+ ├── prompts.py Per-round prompt templates (per task type, per stage)
290
+ ├── sessparse.py Reads the dsh session store into a renderable transcript
291
+ ├── dshdriver.py Client for the in-process dsh agent driver
292
+ ├── dshevents.py Folds the dsh state stream into an in-process registry
293
+ ├── rag.py Optional semantic search over the case library
294
+ ├── loadgen.py Built-in stress engine (scenarios, metrics, reports)
295
+ ├── feishu.py Feishu (Lark) integration
296
+ ├── db.py SQLite data layer
297
+ ├── builtin_prompts/ Prompt assets injected into first-round prompts
298
+ ├── dsh-plugin/ The dsh plugin package (thin Node shell + driver + client bundle)
299
+ ├── extensions/ Built-in assets installable from the settings page
300
+ ├── webui/ React + Vite front end
301
+ ├── tests/ pytest / vitest suites and the isolated-instance harness
302
+ └── touchstone.sh|py|cmd Launchers (Linux / cross-platform / Windows)
303
+ ```
304
+
305
+ ## Development
306
+
307
+ ```bash
308
+ ./touchstone.sh build # install front-end deps and build webui/dist
309
+ ./touchstone.sh test # backend pytest + front-end vitest
310
+ ./touchstone.sh test-full # + isolated end-to-end scripts (scripts are not distributed here)
311
+ ./touchstone.sh test-ui # Playwright end-to-end (needs a running site; scripts not distributed)
312
+ cd webui && npm run dev # front-end dev server on :5173, /api proxied to :4601
313
+ ```
314
+
315
+ Optional commit gate:
316
+
317
+ ```bash
318
+ git config core.hooksPath githooks # pre-commit runs the fast test layer (SKIP_TS_TESTS=1 to skip once)
319
+ ```
320
+
321
+ See [tests/README.md](tests/README.md) for the test matrix and prerequisites.
322
+
323
+ ## Security notes
324
+
325
+ - The site listens on `127.0.0.1` by default and requires a login. Exposing it (`TS_HOST=0.0.0.0`) puts it
326
+ on your network — do that deliberately.
327
+ - Every project-scoped endpoint checks ownership before returning data; the `admin` account is the only
328
+ administrator and cannot be renamed or deleted.
329
+ - The agent runs with the permission preset you configure. The default is the most permissive one (no
330
+ approval prompts), which is convenient and sharp-edged: **review the project guidance and the preset
331
+ before pointing it at a repository you care about.**
332
+ - Passwords are stored with the hashing scheme the project was specified against (unsalted MD5 for new
333
+ passwords, PBKDF2-SHA256 for legacy seed accounts). Treat this as a local-development-grade store.
334
+
335
+ ## License
336
+
337
+ [MIT](LICENSE) © Touchstone contributors