@gavinc-cn/touchstone-dsh 0.0.0-stage → 0.1.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 +21 -0
- package/README.md +335 -2
- package/README.zh.md +317 -0
- package/agents.py +247 -0
- package/auth.py +86 -0
- package/board.py +4229 -0
- package/builtin_assets.py +808 -0
- package/builtin_prompts/free_style/flow.md +301 -0
- package/builtin_prompts/free_style/load_test.md +114 -0
- package/builtin_prompts/free_style/templates/bug_report_template.md +41 -0
- package/builtin_prompts/free_style/templates/case_template.md +23 -0
- package/builtin_prompts/free_style/templates/index_template.md +41 -0
- package/builtin_prompts/free_style/templates/load_charts_template.md +104 -0
- package/builtin_prompts/free_style/templates/load_index_template.md +5 -0
- package/builtin_prompts/free_style/templates/load_plan_template.md +76 -0
- package/builtin_prompts/free_style/templates/load_scenario_template.md +49 -0
- package/builtin_prompts/free_style/templates/status_template.md +18 -0
- package/chat.py +616 -0
- package/db.py +1407 -0
- package/dsh-plugin/cordis.patch.yml +21 -0
- package/dsh-plugin/install.sh +79 -0
- package/dsh-plugin/lib/agent-driver.js +1888 -0
- package/dsh-plugin/lib/client.bundle.js +397 -0
- package/dsh-plugin/lib/index.js +284 -0
- package/dsh-plugin/scripts/build.mjs +37 -0
- package/dsh-plugin/scripts/prepack-check.mjs +61 -0
- package/dsh-plugin/scripts/select-bundle.mjs +51 -0
- package/dsh-plugin/src/client.js +384 -0
- package/dshdriver.py +702 -0
- package/dshevents.py +438 -0
- package/export_cases.py +160 -0
- package/extensions/dsh-autocommit/asset.json +18 -0
- package/extensions/dsh-autocommit/pkg/lib/index.mjs +361 -0
- package/extensions/dsh-autocommit/pkg/package.json +10 -0
- package/feishu.py +2139 -0
- package/lib.py +245 -0
- package/lifecycle.py +417 -0
- package/loadcase.py +558 -0
- package/loadgen.py +678 -0
- package/localbus.py +91 -0
- package/migrate_p7b.py +191 -0
- package/package.json +74 -4
- package/platcompat.py +272 -0
- package/prompts.py +666 -0
- package/rag.py +553 -0
- package/requirements.txt +9 -0
- package/runner.py +2471 -0
- package/server.py +5337 -0
- package/sessparse.py +638 -0
- package/touchstone.py +512 -0
- package/waitq.py +1319 -0
- package/webui/dist-plugin/assets/index-B0WoP1Qy.css +1 -0
- package/webui/dist-plugin/assets/index-eHpxBfP6.js +473 -0
- package/webui/dist-plugin/index.html +18 -0
- package/worktree.py +293 -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,336 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
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)
|
|
8
|
+
[](https://www.python.org/)
|
|
9
|
+
[](https://nodejs.org/)
|
|
10
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
11
|
+
|
|
12
|
+
English | [中文](README.zh.md)
|
|
13
|
+
|
|
14
|
+
<img src="docs/images/board.png" alt="Touchstone development board" width="920">
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
## What is Touchstone?
|
|
19
|
+
|
|
20
|
+
Touchstone turns "we really should test more" into a running loop. You register a project — its source
|
|
21
|
+
directory, a working directory, an environment label, and the house rules the agent must follow — and
|
|
22
|
+
Touchstone drives an AI agent through [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
23
|
+
(`dsh`) to **generate test cases, execute them, report failures as bug reports, fix the code, and
|
|
24
|
+
re-verify the fix**. Every artifact lands on disk in a reviewable form: a case library of Markdown case
|
|
25
|
+
files, a `bug_report/` directory, and per-round logs.
|
|
26
|
+
|
|
27
|
+
It is not a one-shot "run my test suite" CLI. Touchstone is built around **long-lived, multi-round agent
|
|
28
|
+
sessions**: a task runs round after round in the same session with its context intact, so the agent
|
|
29
|
+
remembers what it already tried. A unified queue keeps exactly one writer per project (no two agents
|
|
30
|
+
editing the same checkout at once), and the whole thing is observable — live round logs, a rendered
|
|
31
|
+
session window, and an SSE-backed board.
|
|
32
|
+
|
|
33
|
+
Touchstone runs **locally**. It is a Python web site with a SQLite database and a file-system workspace;
|
|
34
|
+
no data leaves your machine except for the model calls your `dsh` host makes.
|
|
35
|
+
|
|
36
|
+
## Highlights
|
|
37
|
+
|
|
38
|
+
- **Six task types** covering the whole QA loop — exploration, regression, stress, fix, retest, and case
|
|
39
|
+
revision — each following a seven-stage lifecycle (generate cases → execute → report → analyze → fix →
|
|
40
|
+
deploy → retest).
|
|
41
|
+
- **A case library, not a test log.** Cases are human-readable Markdown (`case.md` + `status.md` per
|
|
42
|
+
case, plus an `INDEX.md` per directory). Agents read and extend them across tasks; you can fix a bad
|
|
43
|
+
case by editing a file.
|
|
44
|
+
- **Bug reports as first-class artifacts.** Failures are written up as structured reports (severity,
|
|
45
|
+
reproduction steps, log evidence, related cases) and can be routed back into fix / retest / case-revision
|
|
46
|
+
tasks from the UI.
|
|
47
|
+
- **Unified per-project queue.** Tasks, board cards, and chat messages all take the same serial slot per
|
|
48
|
+
project; queue position, the current holder, and evidence are queryable rather than guessed.
|
|
49
|
+
- **A board for agent-driven development.** Kanban cards start, queue, block, and complete agent sessions;
|
|
50
|
+
cards can run in an isolated `git worktree` so exploratory work never touches your main checkout.
|
|
51
|
+
- **Observable sessions.** Render the full transcript of any agent session (messages, reasoning, tool
|
|
52
|
+
calls, results), reply to it, inject into the running turn, compact it, fork it, or rewind to an earlier
|
|
53
|
+
point through a fork.
|
|
54
|
+
- **Stress testing built in.** A stress task asks the agent for a scenario + script; the platform then
|
|
55
|
+
drives the load itself, N runs per task, with per-run metrics, charts, and Markdown/JSON reports.
|
|
56
|
+
- **Optional integrations.** Feishu (Lark) push notifications with two-way answering from chat cards, and
|
|
57
|
+
RAG-based semantic search over the case library.
|
|
58
|
+
- **Self-contained stack.** Backend: Python standard library plus four small dependencies. Frontend: React
|
|
59
|
+
+ Vite. Storage: SQLite + plain files. Runs on Linux and Windows.
|
|
60
|
+
|
|
61
|
+
## Screenshots
|
|
62
|
+
|
|
63
|
+
The development board — cards per column, task entries inline, per-project queue badges:
|
|
64
|
+
|
|
65
|
+

|
|
66
|
+
|
|
67
|
+
Test tasks — six task types, round counts, statuses, and per-task actions:
|
|
68
|
+
|
|
69
|
+

|
|
70
|
+
|
|
71
|
+
The session window — the full agent transcript rendered from the `dsh` session store, with reply,
|
|
72
|
+
approval, and model controls:
|
|
73
|
+
|
|
74
|
+

|
|
75
|
+
|
|
76
|
+
Card detail — description, scheduling, dependent cards, bound sessions, and comments:
|
|
77
|
+
|
|
78
|
+

|
|
79
|
+
|
|
80
|
+
## How it works
|
|
81
|
+
|
|
82
|
+
```mermaid
|
|
83
|
+
flowchart LR
|
|
84
|
+
U[Browser] -->|REST + SSE| S["Touchstone server<br/>Python stdlib · SQLite · files"]
|
|
85
|
+
S -->|"/touchstone-agent<br/>resident sessions"| D["dsh host<br/>DeepSeek Harness"]
|
|
86
|
+
D -->|"read / edit / bash"| R["Your repository"]
|
|
87
|
+
D --> C[("Case library<br/>free_style/")]
|
|
88
|
+
D --> B[("Bug reports<br/>bug_report/")]
|
|
89
|
+
S --- C
|
|
90
|
+
S --- B
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
1. **You create a project.** Touchstone stores the repository path, a work directory, the environment
|
|
94
|
+
label, optional project skills, and free-form guidance that is injected into every first-round prompt.
|
|
95
|
+
2. **You create a task.** Pick a type (say, *Exploration*) and an end stage (say, *report*), and Touchstone
|
|
96
|
+
queues it for that project.
|
|
97
|
+
3. **Rounds run in a resident agent session.** Touchstone asks the `dsh` plugin to create or resume a
|
|
98
|
+
session and sends the round prompt. Rounds stream back to the UI and to
|
|
99
|
+
`<work_dir>/.web/task_<id>_round_<n>.log` as they happen.
|
|
100
|
+
4. **Artifacts land in your work directory.** New cases under `free_style/`, bug reports under
|
|
101
|
+
`bug_report/`, monitoring state under `.live/`. You review them like code.
|
|
102
|
+
5. **Follow-up tasks close the loop.** A report can spawn a fix task, a fix can spawn a retest, and a
|
|
103
|
+
rejected report can spawn a case-revision task. When a task's end stage goes past "report", the
|
|
104
|
+
platform appends the downstream stages as a follow-up task automatically.
|
|
105
|
+
|
|
106
|
+
### Task types
|
|
107
|
+
|
|
108
|
+
| Type | What the agent does | Typical end stage |
|
|
109
|
+
|------|---------------------|-------------------|
|
|
110
|
+
| Exploration | Reads the code and writes new test cases into the case library | Report |
|
|
111
|
+
| Regression | Re-runs existing cases (optionally limited to a commit date range) | Report |
|
|
112
|
+
| Stress | Produces a load scenario + driver script, then the platform runs the load | Report |
|
|
113
|
+
| Fix | Analyzes a bug report, patches the code, deploys, and re-tests | Fix / Deploy / Retest |
|
|
114
|
+
| Retest | Re-verifies one bug report (retest only, deploy + retest, or deploy only) | Retest |
|
|
115
|
+
| Case revision | Rejects a bug report as a bad case and rewrites the case instead | Revision |
|
|
116
|
+
|
|
117
|
+
### Core concepts
|
|
118
|
+
|
|
119
|
+
| Concept | Meaning |
|
|
120
|
+
|---------|---------|
|
|
121
|
+
| Project | A repository plus its work directory, agent binding, environment label, and guidance |
|
|
122
|
+
| Task | One queued unit of work: a task type, a stage range, a stop condition, and a round history |
|
|
123
|
+
| Round | One prompt/response cycle in the task's agent session |
|
|
124
|
+
| Case library | `<work_dir>/free_style/` — Markdown cases, status files, and per-directory indexes |
|
|
125
|
+
| Bug report | `<work_dir>/bug_report/<timestamp>_FS_<title>/` — the failure dossier for a case |
|
|
126
|
+
| Card | A board item that can start, queue, and drive its own agent session |
|
|
127
|
+
| Queue | The per-project serial slot shared by tasks, cards, and chat messages |
|
|
128
|
+
|
|
129
|
+
## Quick start
|
|
130
|
+
|
|
131
|
+
### Prerequisites
|
|
132
|
+
|
|
133
|
+
| Requirement | Version | Needed for |
|
|
134
|
+
|-------------|---------|------------|
|
|
135
|
+
| Python | 3.12+ | The server (verified on 3.12) |
|
|
136
|
+
| Node.js | 22.19+ or 24+ | Running the `dsh` host (the front-end build alone needs Node 18+) |
|
|
137
|
+
| DeepSeek Harness (`dsh`) | current release | Agent execution — required for plugin mode |
|
|
138
|
+
|
|
139
|
+
### 1. Clone and install
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git clone https://github.com/gavinc-cn/touchstone-dsh.git
|
|
143
|
+
cd touchstone-dsh
|
|
144
|
+
python3 -m pip install -r requirements.txt
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 2. Start the site (standalone mode)
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
./touchstone.sh start # builds the front end on first run, then serves 127.0.0.1:4601
|
|
151
|
+
./touchstone.sh status # PID and the actual port
|
|
152
|
+
./touchstone.sh stop
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Then open <http://127.0.0.1:4601>.
|
|
156
|
+
|
|
157
|
+
The first start seeds an `admin` account. If `TS_ADMIN_PASSWORD` is not set, a random one-time password
|
|
158
|
+
is generated and printed **once** in the startup banner:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
grep '一次性初始口令' .run/server.log # or: ./touchstone.sh status
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
You will be asked to change it on first login. Set `TS_ADMIN_PASSWORD=<your-password>` before the first
|
|
165
|
+
start to skip the one-time password (and the forced change).
|
|
166
|
+
|
|
167
|
+
> Standalone mode gives you the full site — projects, case library, bug reports, board, queue, monitoring —
|
|
168
|
+
> but **agent execution needs plugin mode** (below), because the agent runs inside the `dsh` host process.
|
|
169
|
+
|
|
170
|
+
### 3. Run as a `dsh` plugin (recommended: enables agent execution)
|
|
171
|
+
|
|
172
|
+
The plugin embeds Touchstone in the `dsh` Web UI as a sidebar entry and panel, and lets Touchstone drive
|
|
173
|
+
resident agent sessions in the host process.
|
|
174
|
+
|
|
175
|
+
**Option A — from npm (self-contained package: whole platform + prebuilt front end):**
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
npx @deepseek-ai/dsh web # 1) start the dsh host once (creates ~/.dsh/profiles/web)
|
|
179
|
+
dsh plugin --profile web add @gavinc-cn/touchstone-dsh # 2) install the plugin package
|
|
180
|
+
# 3) select the bundle in the profile manifest (the Plugins panel toggle does the same thing):
|
|
181
|
+
node ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/dsh-plugin/scripts/select-bundle.mjs \
|
|
182
|
+
~/.dsh/profiles/web/package.json
|
|
183
|
+
# 4) restart the dsh web UI, open http://127.0.0.1:3080, use the Touchstone entry (Alt+T toggles the panel)
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The platform's own Python dependencies are installed with pip, not npm:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
pip install -r ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/requirements.txt
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
No `repoDir` is needed: the package carries `server.py` and `webui/dist-plugin`, so the plugin falls back to
|
|
193
|
+
its own directory.
|
|
194
|
+
|
|
195
|
+
**Option B — from a checkout (development):**
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
cd touchstone-dsh
|
|
199
|
+
./dsh-plugin/install.sh # idempotent install of this checkout into the profile
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
The installer prints the optional profile patch for pointing the plugin at your working copy (or picking a
|
|
203
|
+
specific interpreter); skip it to use the package's own directory:
|
|
204
|
+
|
|
205
|
+
```yaml
|
|
206
|
+
- id: touchstone
|
|
207
|
+
config: { repoDir: /path/to/touchstone-dsh, pythonPath: /path/to/python3 }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Both run modes share one database (`~/.touchstone/touchstone.db` by default) and are mutually exclusive
|
|
211
|
+
while running; the second instance refuses to start and tells you who holds the lock.
|
|
212
|
+
|
|
213
|
+
### Windows
|
|
214
|
+
|
|
215
|
+
A cross-platform launcher offers the same commands:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
python touchstone.py start | stop | restart | status | build | test
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### First steps in the UI
|
|
222
|
+
|
|
223
|
+
1. Sign in and open **Settings → Change password** if you used the one-time password.
|
|
224
|
+
2. **Add project** — source directory, work directory (defaults to `<project>/.touchstone`), environment
|
|
225
|
+
label, and the guidance the agent should follow. The case library and bug report directories are
|
|
226
|
+
derived and created for you.
|
|
227
|
+
3. Create a task (or a board card) and let the queue pick it up. Round logs stream live; the session window
|
|
228
|
+
shows the transcript as it grows.
|
|
229
|
+
|
|
230
|
+
## Configuration
|
|
231
|
+
|
|
232
|
+
| Variable | Default | Purpose |
|
|
233
|
+
|----------|---------|---------|
|
|
234
|
+
| `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 |
|
|
235
|
+
| `TS_PYTHON` | `python3` | Interpreter used by the launcher (must have the runtime dependencies) |
|
|
236
|
+
| `TOUCHSTONE_DB` | `~/.touchstone/touchstone.db` | SQLite database. Must live on a local disk — file locking does not work on CIFS/network shares |
|
|
237
|
+
| `TS_ADMIN_PASSWORD` | *(random, printed once)* | Initial `admin` password; setting it skips the forced change |
|
|
238
|
+
| `TS_WEB_DIR` | `webui/dist` | Static front-end directory the server serves |
|
|
239
|
+
| `TOUCHSTONE_RUN_DIR` | `.run/` in the repository | PID / log / port files |
|
|
240
|
+
| `TS_EXT_DIR` | `extensions` | Root of the built-in asset manifests |
|
|
241
|
+
| `TS_ARCHIVE_SYNC` | `1` | Keep board "Done" and `dsh` session archive in sync (set `0` to disable) |
|
|
242
|
+
| `TS_DSH_PROFILE` / `TS_DSH_PYTHON` | `web` / auto-detected | `dsh` profile and interpreter used by the plugin installer |
|
|
243
|
+
|
|
244
|
+
Runtime paths inside a project's work directory:
|
|
245
|
+
|
|
246
|
+
| Path | Contents |
|
|
247
|
+
|------|----------|
|
|
248
|
+
| `free_style/` | Case library (cases, status files, indexes) |
|
|
249
|
+
| `bug_report/` | Bug reports, one directory per report |
|
|
250
|
+
| `.web/` | Round logs, chat logs, stress metrics and reports |
|
|
251
|
+
| `.live/live.json` | Agent live state used by the monitoring page |
|
|
252
|
+
| `board_media/` | Attachments pasted onto board cards |
|
|
253
|
+
|
|
254
|
+
## Capabilities and limits
|
|
255
|
+
|
|
256
|
+
| Area | Supported |
|
|
257
|
+
|------|-----------|
|
|
258
|
+
| Agent sessions | Create, resume, reply, inject into the running turn, cancel, compact, fork, rewind-by-fork, model and permission-preset switching |
|
|
259
|
+
| Session observability | Full transcript rendering, archive state, attachment preview, live status stream (no polling) |
|
|
260
|
+
| Tasks | Six types, seven stages, stop conditions, date-range scoping, per-round logs, restart, continue |
|
|
261
|
+
| Board | Cards across five columns, drag & drop, queue position, parent dependencies, scheduled start, trash, isolated worktrees |
|
|
262
|
+
| Case library | Derived indexes, change-based retest triage, optional semantic (RAG) search |
|
|
263
|
+
| Stress testing | Scenario validation, concurrent load, second-by-second metrics, charts, Markdown/JSON reports per run |
|
|
264
|
+
| Notifications | Feishu (Lark) outbound push, inbound commands, and answering questions from chat cards |
|
|
265
|
+
| Multi-user | Login, admin/user roles, per-project ownership checks on every project-scoped endpoint |
|
|
266
|
+
|
|
267
|
+
Known limitations, stated plainly:
|
|
268
|
+
|
|
269
|
+
- **The UI is currently Chinese-only.**
|
|
270
|
+
- **Agent execution requires plugin mode**; standalone mode is the site without the agent.
|
|
271
|
+
- **Rewind and "compact into a new session" are approximations** — rewind starts a new branch at an
|
|
272
|
+
earlier point (the original session is kept), rather than truncating in place.
|
|
273
|
+
- **No error banner for failed model requests** — `dsh` has no event for it, so the session window shows
|
|
274
|
+
what the host reported and nothing more.
|
|
275
|
+
- **The Windows launcher is implemented but `dsh` itself has not been verified on Windows yet.**
|
|
276
|
+
- **End-to-end test scripts are not distributed** in this repository (see below), so `test-full` and
|
|
277
|
+
`test-ui` report a skip rather than running.
|
|
278
|
+
|
|
279
|
+
## Repository layout
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
touchstone-dsh/
|
|
283
|
+
├── server.py HTTP site: routing, auth, REST, SSE, static front end
|
|
284
|
+
├── runner.py Task execution engine and per-project scheduling
|
|
285
|
+
├── waitq.py Unified queue model (the single source of truth for "who runs next")
|
|
286
|
+
├── board.py Development board: cards, gates, agent sessions, archive sync
|
|
287
|
+
├── chat.py Session chat: queued messages and injection
|
|
288
|
+
├── prompts.py Per-round prompt templates (per task type, per stage)
|
|
289
|
+
├── sessparse.py Reads the dsh session store into a renderable transcript
|
|
290
|
+
├── dshdriver.py Client for the in-process dsh agent driver
|
|
291
|
+
├── dshevents.py Folds the dsh state stream into an in-process registry
|
|
292
|
+
├── rag.py Optional semantic search over the case library
|
|
293
|
+
├── loadgen.py Built-in stress engine (scenarios, metrics, reports)
|
|
294
|
+
├── feishu.py Feishu (Lark) integration
|
|
295
|
+
├── db.py SQLite data layer
|
|
296
|
+
├── builtin_prompts/ Prompt assets injected into first-round prompts
|
|
297
|
+
├── dsh-plugin/ The dsh plugin package (thin Node shell + driver + client bundle)
|
|
298
|
+
├── extensions/ Built-in assets installable from the settings page
|
|
299
|
+
├── webui/ React + Vite front end
|
|
300
|
+
├── tests/ pytest / vitest suites and the isolated-instance harness
|
|
301
|
+
└── touchstone.sh|py|cmd Launchers (Linux / cross-platform / Windows)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Development
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
./touchstone.sh build # install front-end deps and build webui/dist
|
|
308
|
+
./touchstone.sh test # backend pytest + front-end vitest
|
|
309
|
+
./touchstone.sh test-full # + isolated end-to-end scripts (scripts are not distributed here)
|
|
310
|
+
./touchstone.sh test-ui # Playwright end-to-end (needs a running site; scripts not distributed)
|
|
311
|
+
cd webui && npm run dev # front-end dev server on :5173, /api proxied to :4601
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
Optional commit gate:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
git config core.hooksPath githooks # pre-commit runs the fast test layer (SKIP_TS_TESTS=1 to skip once)
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
See [tests/README.md](tests/README.md) for the test matrix and prerequisites.
|
|
321
|
+
|
|
322
|
+
## Security notes
|
|
323
|
+
|
|
324
|
+
- The site listens on `127.0.0.1` by default and requires a login. Exposing it (`TS_HOST=0.0.0.0`) puts it
|
|
325
|
+
on your network — do that deliberately.
|
|
326
|
+
- Every project-scoped endpoint checks ownership before returning data; the `admin` account is the only
|
|
327
|
+
administrator and cannot be renamed or deleted.
|
|
328
|
+
- The agent runs with the permission preset you configure. The default is the most permissive one (no
|
|
329
|
+
approval prompts), which is convenient and sharp-edged: **review the project guidance and the preset
|
|
330
|
+
before pointing it at a repository you care about.**
|
|
331
|
+
- Passwords are stored with the hashing scheme the project was specified against (unsalted MD5 for new
|
|
332
|
+
passwords, PBKDF2-SHA256 for legacy seed accounts). Treat this as a local-development-grade store.
|
|
333
|
+
|
|
334
|
+
## License
|
|
335
|
+
|
|
336
|
+
[MIT](LICENSE) © Touchstone contributors
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Touchstone(试金石)
|
|
4
|
+
|
|
5
|
+
**AI agent 驱动的自动化测试平台。** 把它指向一个代码仓库,它会读代码、写用例、跑用例,
|
|
6
|
+
把失败沉淀成 bug 报告,修完再复测一遍。
|
|
7
|
+
|
|
8
|
+
[](LICENSE)
|
|
9
|
+
[](https://www.python.org/)
|
|
10
|
+
[](https://nodejs.org/)
|
|
11
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
12
|
+
|
|
13
|
+
[English](README.md) | 中文
|
|
14
|
+
|
|
15
|
+
<img src="docs/images/board.png" alt="Touchstone 开发看板" width="920">
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
## Touchstone 是什么
|
|
20
|
+
|
|
21
|
+
Touchstone 把「我们真该多测一点」变成一条持续转动的流水线。你登记一个项目——源码目录、
|
|
22
|
+
工作目录、环境标签、以及要求 agent 遵守的项目约定——Touchstone 就会通过
|
|
23
|
+
[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh`)驱动 AI agent:
|
|
24
|
+
**生成测试用例 → 执行 → 把失败写成 bug 报告 → 修代码 → 再复测**。所有产物都以可直接审阅的形式
|
|
25
|
+
落在磁盘上:Markdown 写的案例库、`bug_report/` 目录、以及逐轮日志。
|
|
26
|
+
|
|
27
|
+
它不是「跑一遍我的测试」的一次性 CLI。Touchstone 的核心是**多轮常驻 agent 会话**:一个任务在同一
|
|
28
|
+
会话里一轮接一轮地跑,上下文不断档,agent 记得自己试过什么。统一队列保证同一个项目同一时刻只有
|
|
29
|
+
一个写者(不会有两个 agent 同时改同一份检出),并且全流程可观测——逐轮实时日志、可渲染的会话窗口、
|
|
30
|
+
以及基于 SSE 的看板。
|
|
31
|
+
|
|
32
|
+
Touchstone 是**本地运行**的:Python 站点 + SQLite + 文件系统工作区。除了你的 `dsh` 宿主发起的模型
|
|
33
|
+
调用之外,数据不出本机。
|
|
34
|
+
|
|
35
|
+
## 主要特性
|
|
36
|
+
|
|
37
|
+
- **六类任务**覆盖完整测试闭环:探索 / 回归 / 压测 / 修复 / 复测 / 修例,每类都走七阶段生命周期
|
|
38
|
+
(生成用例 → 测试 → 生成报告 → 报告分析 → 问题修复 → 重新部署 → 复测)。
|
|
39
|
+
- **案例库而不是测试日志**。用例是可读的 Markdown(每个用例 `case.md` + `status.md`,每层目录一个
|
|
40
|
+
`INDEX.md`)。agent 跨任务读写同一份案例库;用例写错了,你直接改文件就能修。
|
|
41
|
+
- **bug 报告是一等产物**。失败会写成结构化报告(严重程度、复现步骤、日志证据、关联用例),并可在
|
|
42
|
+
界面上直接派生成修复 / 复测 / 修例任务。
|
|
43
|
+
- **按项目的统一队列**。任务、看板卡片、会话消息共用同一个项目级串行位;排队位次、当前占用者与
|
|
44
|
+
判定证据都可查,不靠猜。
|
|
45
|
+
- **面向 agent 开发的看板**。卡片可以起跑、排队、阻塞、完成各自的 agent 会话;需要时在独立的
|
|
46
|
+
`git worktree` 里跑,探索性改动不碰你的主检出。
|
|
47
|
+
- **会话可观测**。完整渲染任意 agent 会话的消息、思考、工具调用与返回;可续聊、可往当前轮注入、
|
|
48
|
+
可压缩、可 fork、也可通过 fork 回退到更早的节点。
|
|
49
|
+
- **内置压测**。压测任务先让 agent 产出场景与脚本,之后由平台自己发压,一个任务可跑 N 次,每次都有
|
|
50
|
+
指标、图表与 Markdown/JSON 报告。
|
|
51
|
+
- **可选集成**。飞书(Lark)推送通知与卡片双向作答;案例库的可选语义检索(RAG)。
|
|
52
|
+
- **自包含技术栈**。后端:Python 标准库 + 4 个小依赖;前端:React + Vite;存储:SQLite + 普通文件。
|
|
53
|
+
Linux 与 Windows 均可运行。
|
|
54
|
+
|
|
55
|
+
## 界面截图
|
|
56
|
+
|
|
57
|
+
开发看板——五列卡片、任务条目内联展示、项目级排队徽标:
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
测试任务——六类任务、轮次、状态与逐任务操作:
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
会话窗口——从 `dsh` 会话存储渲染出的完整对话(消息、思考、工具调用),带回复、审批与模型控件:
|
|
66
|
+
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
卡片详情——描述、定时开工、父任务依赖、绑定会话与评论:
|
|
70
|
+
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
## 工作原理
|
|
74
|
+
|
|
75
|
+
```mermaid
|
|
76
|
+
flowchart LR
|
|
77
|
+
U[浏览器] -->|REST + SSE| S["Touchstone 站点<br/>Python 标准库 · SQLite · 文件"]
|
|
78
|
+
S -->|"/touchstone-agent<br/>常驻会话"| D["dsh 宿主<br/>DeepSeek Harness"]
|
|
79
|
+
D -->|"读 / 改 / 执行"| R["你的代码仓库"]
|
|
80
|
+
D --> C[("案例库<br/>free_style/")]
|
|
81
|
+
D --> B[("bug 报告<br/>bug_report/")]
|
|
82
|
+
S --- C
|
|
83
|
+
S --- B
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
1. **建项目**:Touchstone 记录仓库路径、工作目录、环境标签、可选的项目能力 skill,以及每轮首轮
|
|
87
|
+
提示词都会注入的自由文本约定。
|
|
88
|
+
2. **建任务**:选类型(例如「探索」)与终点阶段(例如「生成报告」),入该项目的队列。
|
|
89
|
+
3. **多轮会话执行**:Touchstone 经 `dsh` 插件新建或续接一个常驻会话,下发本轮提示词;过程实时回流
|
|
90
|
+
到界面,并写入 `<工作目录>/.web/task_<id>_round_<n>.log`。
|
|
91
|
+
4. **产物落到工作目录**:新用例进 `free_style/`,bug 报告进 `bug_report/`,监控状态进 `.live/`——
|
|
92
|
+
你像审代码一样审它们。
|
|
93
|
+
5. **后段任务闭环**:报告可派生修复任务,修复可派生复测任务,被否决的报告可派生修例任务;当任务的
|
|
94
|
+
终点越过「生成报告」时,平台会自动追加后段阶段任务。
|
|
95
|
+
|
|
96
|
+
### 任务类型
|
|
97
|
+
|
|
98
|
+
| 类型 | agent 做什么 | 常见终点 |
|
|
99
|
+
|------|--------------|----------|
|
|
100
|
+
| 探索 | 读代码并把新用例写进案例库 | 生成报告 |
|
|
101
|
+
| 回归 | 重跑已有用例(可限定提交日期范围) | 生成报告 |
|
|
102
|
+
| 压测 | 产出压测场景 + 驱动脚本,随后由平台发压 | 生成报告 |
|
|
103
|
+
| 修复 | 分析 bug 报告、改代码、部署并复测 | 问题修复 / 重新部署 / 复测 |
|
|
104
|
+
| 复测 | 针对一份 bug 报告复验(仅复测 / 部署后复测 / 仅部署) | 复测 |
|
|
105
|
+
| 修例 | 判定报告对应的用例本身有误,改写用例 | 修订用例 |
|
|
106
|
+
|
|
107
|
+
### 核心概念
|
|
108
|
+
|
|
109
|
+
| 概念 | 含义 |
|
|
110
|
+
|------|------|
|
|
111
|
+
| 项目 | 一个仓库 + 工作目录 + 智能体绑定 + 环境标签 + 项目约定 |
|
|
112
|
+
| 任务 | 一个排队单元:任务类型、阶段范围、停止条件与轮次历史 |
|
|
113
|
+
| 轮次 | 任务会话里的一次「提示词 → agent 执行」循环 |
|
|
114
|
+
| 案例库 | `<工作目录>/free_style/`:Markdown 用例、状态文件与逐层索引 |
|
|
115
|
+
| bug 报告 | `<工作目录>/bug_report/<时间戳>_FS_<标题>/`:一条用例的失败档案 |
|
|
116
|
+
| 卡片 | 看板条目,可起跑、排队并驱动自己的 agent 会话 |
|
|
117
|
+
| 队列 | 任务 / 卡片 / 会话消息共享的项目级串行位 |
|
|
118
|
+
|
|
119
|
+
## 快速开始
|
|
120
|
+
|
|
121
|
+
### 环境要求
|
|
122
|
+
|
|
123
|
+
| 依赖 | 版本 | 用途 |
|
|
124
|
+
|------|------|------|
|
|
125
|
+
| Python | 3.12+ | 运行站点(实测 3.12) |
|
|
126
|
+
| Node.js | 22.19+ 或 24+ | 运行 `dsh` 宿主(仅构建前端时 Node 18+ 即可) |
|
|
127
|
+
| DeepSeek Harness(`dsh`) | 当前版本 | agent 执行——插件形态必需 |
|
|
128
|
+
|
|
129
|
+
### 1. 克隆并安装
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
git clone https://github.com/gavinc-cn/touchstone-dsh.git
|
|
133
|
+
cd touchstone-dsh
|
|
134
|
+
python3 -m pip install -r requirements.txt
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### 2. 启动站点(独立形态)
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
./touchstone.sh start # 首次启动会自动构建前端,然后监听 127.0.0.1:4601
|
|
141
|
+
./touchstone.sh status # 查看 PID 与实际端口
|
|
142
|
+
./touchstone.sh stop
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
浏览器打开 <http://127.0.0.1:4601>。
|
|
146
|
+
|
|
147
|
+
首次启动会种子一个 `admin` 账号。若未设置 `TS_ADMIN_PASSWORD`,平台会随机生成一次性初始口令,
|
|
148
|
+
**只在启动横幅打印一次**:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
grep '一次性初始口令' .run/server.log # 或:./touchstone.sh status
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
首次登录会被要求改密。想跳过一次性口令(以及强制改密),在首次启动前设置
|
|
155
|
+
`TS_ADMIN_PASSWORD=<你的口令>` 即可。
|
|
156
|
+
|
|
157
|
+
> 独立形态给的是完整站点——项目、案例库、bug 报告、看板、队列、监控都能用;但**agent 执行需要
|
|
158
|
+
> 插件形态**(见下),因为 agent 跑在 `dsh` 宿主进程里。
|
|
159
|
+
|
|
160
|
+
### 3. 以 `dsh` 插件形态运行(推荐:启用 agent 执行)
|
|
161
|
+
|
|
162
|
+
插件把 Touchstone 嵌进 `dsh` Web 界面(侧栏入口 + 面板),并让 Touchstone 能驱动宿主进程内的常驻
|
|
163
|
+
agent 会话。
|
|
164
|
+
|
|
165
|
+
**方式 A —— 从 npm 安装(自包含包:整个平台 + 预构建前端都在包里):**
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npx @deepseek-ai/dsh web # 1) 先启动一次 dsh 宿主(会创建 ~/.dsh/profiles/web)
|
|
169
|
+
dsh plugin --profile web add @gavinc-cn/touchstone-dsh # 2) 装插件包
|
|
170
|
+
# 3) 把包名选进 profile 清单(等同 Plugins 面板里那一行的开关):
|
|
171
|
+
node ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/dsh-plugin/scripts/select-bundle.mjs \
|
|
172
|
+
~/.dsh/profiles/web/package.json
|
|
173
|
+
# 4) 重启 dsh web,打开 http://127.0.0.1:3080,用侧栏里的 Touchstone 入口(Alt+T 开关面板)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
平台自身的 Python 依赖走 pip,npm 不管:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pip install -r ~/.dsh/profiles/web/node_modules/@gavinc-cn/touchstone-dsh/requirements.txt
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
**不需要配 `repoDir`**:包里带着 `server.py` 与 `webui/dist-plugin`,插件缺省就用包自身目录。
|
|
183
|
+
|
|
184
|
+
**方式 B —— 从检出安装(开发用):**
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
cd touchstone-dsh
|
|
188
|
+
./dsh-plugin/install.sh # 幂等安装本检出到 profile
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
安装脚本会打印**可选**的 profile 覆盖(指向本机工作副本、或指定解释器);不写就用包自身目录:
|
|
192
|
+
|
|
193
|
+
```yaml
|
|
194
|
+
- id: touchstone
|
|
195
|
+
config: { repoDir: /path/to/touchstone-dsh, pythonPath: /path/to/python3 }
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
两种形态默认共用同一个数据库(`~/.touchstone/touchstone.db`),运行时互斥:第二个实例会拒绝启动,
|
|
199
|
+
并打印当前占用者。
|
|
200
|
+
|
|
201
|
+
### Windows
|
|
202
|
+
|
|
203
|
+
跨平台启停器提供同一套命令:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
python touchstone.py start | stop | restart | status | build | test
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 界面里的第一步
|
|
210
|
+
|
|
211
|
+
1. 登录;若用的是一次性口令,先去 **设置 → 修改密码**。
|
|
212
|
+
2. **添加项目**——源码目录、工作目录(默认 `<项目目录>/.touchstone`)、环境标签,以及要求 agent
|
|
213
|
+
遵守的约定。案例库与 bug 报告目录由平台派生并自动创建。
|
|
214
|
+
3. 新建任务(或建一张看板卡),等队列调度。逐轮日志实时刷新,会话窗口随对话增长即时渲染。
|
|
215
|
+
|
|
216
|
+
## 配置
|
|
217
|
+
|
|
218
|
+
| 环境变量 | 默认值 | 作用 |
|
|
219
|
+
|----------|--------|------|
|
|
220
|
+
| `TS_PORT` / `TS_HOST` | `4601` / `127.0.0.1` | 监听地址;`TS_HOST=0.0.0.0` 可对局域网开放 |
|
|
221
|
+
| `TS_PYTHON` | `python3` | 启停器使用的解释器(需装好运行依赖) |
|
|
222
|
+
| `TOUCHSTONE_DB` | `~/.touchstone/touchstone.db` | SQLite 数据库,必须放本地盘——文件锁在 CIFS/网盘上不可用 |
|
|
223
|
+
| `TS_ADMIN_PASSWORD` | *(随机,打印一次)* | `admin` 初始口令;设了就跳过强制改密 |
|
|
224
|
+
| `TS_WEB_DIR` | `webui/dist` | 站点托管的前端静态目录 |
|
|
225
|
+
| `TOUCHSTONE_RUN_DIR` | 仓库内 `.run/` | PID / 日志 / 端口标记文件目录 |
|
|
226
|
+
| `TS_EXT_DIR` | `extensions` | 内置资产清单根目录 |
|
|
227
|
+
| `TS_ARCHIVE_SYNC` | `1` | 看板「已完成」与 `dsh` 会话归档双向同步(置 `0` 关闭) |
|
|
228
|
+
| `TS_DSH_PROFILE` / `TS_DSH_PYTHON` | `web` / 自动探测 | 插件安装脚本使用的 `dsh` profile 与解释器 |
|
|
229
|
+
|
|
230
|
+
项目工作目录下的运行路径:
|
|
231
|
+
|
|
232
|
+
| 路径 | 内容 |
|
|
233
|
+
|------|------|
|
|
234
|
+
| `free_style/` | 案例库(用例、状态文件、逐层索引) |
|
|
235
|
+
| `bug_report/` | bug 报告,一份报告一个目录 |
|
|
236
|
+
| `.web/` | 逐轮日志、对话日志、压测指标与报告 |
|
|
237
|
+
| `.live/live.json` | 监控页数据源(agent 运行状态) |
|
|
238
|
+
| `board_media/` | 粘贴到看板卡片的附件 |
|
|
239
|
+
|
|
240
|
+
## 能力与边界
|
|
241
|
+
|
|
242
|
+
| 领域 | 支持情况 |
|
|
243
|
+
|------|----------|
|
|
244
|
+
| agent 会话 | 新建、续接、回复、往当前轮注入、中断、compact 压缩、fork、按 fork 回退、模型与权限档切换 |
|
|
245
|
+
| 会话可观测 | 完整对话渲染、归档状态、附件预览、实时状态流(零状态轮询) |
|
|
246
|
+
| 任务 | 六类型、七阶段、停止条件、日期范围限定、逐轮日志、重启、继续 |
|
|
247
|
+
| 看板 | 五列卡片、拖拽、排队位次、父任务依赖、定时开工、回收站、独立 worktree |
|
|
248
|
+
| 案例库 | 派生索引、按变更文件做复测粗筛、可选语义检索(RAG) |
|
|
249
|
+
| 压测 | 场景校验、并发发压、秒级指标、图表、每次运行独立的 Markdown/JSON 报告 |
|
|
250
|
+
| 通知 | 飞书推送、入站指令、在聊天卡片上直接作答 |
|
|
251
|
+
| 多用户 | 登录、admin/普通用户、所有按项目进入的接口都做归属校验 |
|
|
252
|
+
|
|
253
|
+
如实说明的已知限制:
|
|
254
|
+
|
|
255
|
+
- **界面目前只有中文。**
|
|
256
|
+
- **agent 执行必须走插件形态**;独立形态是「没有 agent 的站点」。
|
|
257
|
+
- **回退与「压缩并新建」是语义近似**——回退是从更早的节点另起一支(原会话保留),不是原地截断。
|
|
258
|
+
- **模型请求失败没有错误横幅**——`dsh` 没有对应事件通道,会话窗只能显示宿主真实回报的内容。
|
|
259
|
+
- **Windows 启停器已实现,但 `dsh` 在 Windows 上尚未实机验证。**
|
|
260
|
+
- **端到端测试脚本不随本仓分发**(见下),因此 `test-full` 与 `test-ui` 只会提示跳过。
|
|
261
|
+
|
|
262
|
+
## 仓库结构
|
|
263
|
+
|
|
264
|
+
```
|
|
265
|
+
touchstone-dsh/
|
|
266
|
+
├── server.py HTTP 站点:路由、鉴权、REST、SSE、静态前端
|
|
267
|
+
├── runner.py 任务执行引擎与按项目调度
|
|
268
|
+
├── waitq.py 统一队列模型(「下一个谁跑」的唯一权威)
|
|
269
|
+
├── board.py 开发看板:卡片、门禁、agent 会话、归档同步
|
|
270
|
+
├── chat.py 会话对话:排队消息与注入
|
|
271
|
+
├── prompts.py 逐轮提示词模板(按任务类型与阶段)
|
|
272
|
+
├── sessparse.py 读取 dsh 会话存储,还原成可渲染的对话
|
|
273
|
+
├── dshdriver.py dsh 进程内 agent 驱动的客户端
|
|
274
|
+
├── dshevents.py 把 dsh 状态流折进进程内注册表
|
|
275
|
+
├── rag.py 案例库可选语义检索
|
|
276
|
+
├── loadgen.py 内置压测引擎(场景、指标、报告)
|
|
277
|
+
├── feishu.py 飞书集成
|
|
278
|
+
├── db.py SQLite 数据层
|
|
279
|
+
├── builtin_prompts/ 注入首轮提示词的提示词资产
|
|
280
|
+
├── dsh-plugin/ dsh 插件包(Node 薄壳 + 驱动 + 客户端 bundle)
|
|
281
|
+
├── extensions/ 设置页可一键安装的内置资产
|
|
282
|
+
├── webui/ React + Vite 前端
|
|
283
|
+
├── tests/ pytest / vitest 套件与隔离实例夹具
|
|
284
|
+
└── touchstone.sh|py|cmd 启停入口(Linux / 跨平台 / Windows)
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## 开发
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
./touchstone.sh build # 安装前端依赖并构建 webui/dist
|
|
291
|
+
./touchstone.sh test # 后端 pytest + 前端 vitest
|
|
292
|
+
./touchstone.sh test-full # 追加隔离实例 e2e(本仓不随附这些脚本)
|
|
293
|
+
./touchstone.sh test-ui # Playwright e2e(需站点在跑;本仓不随附这些脚本)
|
|
294
|
+
cd webui && npm run dev # 前端开发服务器 :5173,/api 代理到 :4601
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
可选的提交门禁:
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
git config core.hooksPath githooks # pre-commit 跑测试快层(SKIP_TS_TESTS=1 单次跳过)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
测试矩阵与前置条件见 [tests/README.md](tests/README.md)。
|
|
304
|
+
|
|
305
|
+
## 安全说明
|
|
306
|
+
|
|
307
|
+
- 站点默认只监听 `127.0.0.1` 并要求登录。用 `TS_HOST=0.0.0.0` 对外暴露等于把它放进你的网络里,
|
|
308
|
+
请有意为之。
|
|
309
|
+
- 所有按项目进入的接口先做归属校验;`admin` 是唯一管理员,不可改名或删除。
|
|
310
|
+
- agent 以你配置的权限档运行,默认是限制最松的一档(免审批)。方便,但也锋利:**把它指向你在意的
|
|
311
|
+
仓库之前,请先看清项目约定与权限档。**
|
|
312
|
+
- 口令存储沿用本项目既定的算法(新口令为无盐 MD5,历史种子账号为 PBKDF2-SHA256)。请把它当作
|
|
313
|
+
本地开发级别的口令存储来对待。
|
|
314
|
+
|
|
315
|
+
## 许可证
|
|
316
|
+
|
|
317
|
+
[MIT](LICENSE) © Touchstone contributors
|