dsh-clone 0.0.0-stage → 0.2.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.
@@ -0,0 +1,28 @@
1
+ # Acceptable use
2
+
3
+ `dsh-clone` rebuilds an interface from a picture. That is a normal design and engineering workflow, and it is also easy to misuse. This page is short on purpose.
4
+
5
+ ## Fine
6
+
7
+ - Rebuilding **your own** designs, screenshots, mockups, or an interface you are migrating from.
8
+ - Prototyping: "make it look like this" is a legitimate way to describe intent.
9
+ - Internal tools, throwaway experiments, teaching, and design exploration.
10
+ - Recreating a **layout pattern** (a pricing table, a dashboard grid) — layout is not owned by anyone.
11
+ - Cloning a screen you have written permission to clone, or one published under a permissive licence.
12
+
13
+ ## Not fine
14
+
15
+ - Cloning a third-party product's interface to **ship as your own product**, or to pass it off as the original.
16
+ - Reproducing a competitor's brand: logo, wordmark, illustrations, mascots, or photography you do not hold rights to.
17
+ - Cloning a screen in order to bypass a paywall, a login, or any access control.
18
+ - Building phishing look-alikes of banking, wallet, exchange, or identity-provider screens. This is the one case where the author will publicly recommend against the plugin's use, and the one case where a bug report will be closed without discussion.
19
+
20
+ ## Practical guidance
21
+
22
+ The builders are instructed to approximate photos and illustrations with CSS and SVG, so the output is a **structural** copy rather than a pixel copy. Keep it that way: if your result would be indistinguishable from someone else's shipped product, that is the signal to stop and take the layout idea rather than the identity.
23
+
24
+ When in doubt, ask: *if the original's team saw this, would they call it inspiration or impersonation?*
25
+
26
+ ## Reporting
27
+
28
+ If you believe dsh-clone is being used in a way this page forbids, open an issue with the repository and a description. Do not include credentials, private screenshots, or personal data.
package/CHANGELOG.md ADDED
@@ -0,0 +1,96 @@
1
+ # Changelog
2
+
3
+ ## 0.2.0 — 2026-11-09
4
+
5
+ Everything in this release is about the plugin being right when it is left alone.
6
+
7
+ **Scoring is now a real measurement**
8
+
9
+ - colour comparison forgives a small uniform shift, so a 4px offset is not a
10
+ different design while a misplaced panel still costs real points;
11
+ - a separate **structure** term compares where the detail sits (softened edge
12
+ energy, normalised by the reference), so a flat block that happens to average
13
+ to the right colour no longer scores as a faithful rebuild;
14
+ - published runs re-measured on the same artifacts: dashboard 91.9%, landing
15
+ 91.9%, billing card 97.8%, sign-in 79%. Two unrelated screens now score 24-58%
16
+ instead of ~89%, which is the whole point of having a number.
17
+
18
+ **The engine survives being interrupted**
19
+
20
+ - each clone writes `state.json` next to its work; `status` and `pick` restore
21
+ clones from disk after a plugin reload or a restart;
22
+ - a lane that was building when the plugin went away keeps whatever it had
23
+ already written, and is reported as interrupted rather than finished;
24
+ - unloading the plugin now interrupts its builder agents instead of leaving them
25
+ spending tokens for a result nobody can reach.
26
+
27
+ **New pass: iterate instead of restarting**
28
+
29
+ - `/clone refine [lane] [change]` copies the adopted page into a fresh
30
+ single-lane clone and asks for the smallest edit that satisfies one change;
31
+ the reference and viewport are unchanged, so the result reports a score delta.
32
+
33
+ **Budget**
34
+
35
+ - `laneTokenBudget` stops a lane that burns past its ceiling and keeps whatever it
36
+ delivered. Off by default: an agent re-sends its context every step, so a naive
37
+ ceiling stops honest builds mid-analysis — set it deliberately as a backstop.
38
+
39
+ **A nudge instead of a wasted run**
40
+
41
+ - a lane past 12 tool calls with no `index.html` on disk gets one steering
42
+ message telling it to stop measuring and write the page. Observed failure that
43
+ motivated it: a builder spent every call sampling pixels and ended with an
44
+ empty directory. The prompts now also forbid image-measurement scripts
45
+ outright.
46
+
47
+ **Robustness**
48
+
49
+ - a rendered screenshot must decode before it is scored; a truncated capture is
50
+ retried instead of producing a garbage number;
51
+ - the renderer finds Chrome/Chromium/Edge/Brave on Windows as well as macOS and
52
+ Linux;
53
+ - `status` accepts a `clone_id`, so an older clone stays inspectable.
54
+
55
+ ## 0.1.0 — 2026-11-09
56
+
57
+ ## 0.1.0 — 2026-11-09
58
+
59
+ First release.
60
+
61
+ **Core**
62
+
63
+ - `/clone [lanes] [note]` starts 1-4 builder agents on the last image in the
64
+ conversation (or an image path in the note), plus `status`, `pick <lane>`,
65
+ `cancel` and `discard`; the same operations are exposed as the `clone` tool.
66
+ - Lane isolation: a real `git worktree` on its own branch inside a repository,
67
+ a plain directory otherwise. `node_modules`, `.venv` and `vendor` are shared by
68
+ symlink, and `.dsh-clone/` is added to `.git/info/exclude`.
69
+ - Clone panel in the conversation view ring: the reference beside every lane's
70
+ live page, with strategy, timing, tool calls, file count and token spend.
71
+ - Adoption copies only deliverable files (no `.git`, no symlinked dependencies,
72
+ no dotted scratch directories) into `clone-<id>-lane-<n>/`.
73
+ - Lane pages are served from the page's own origin under a `sandbox` CSP and
74
+ mounted in a `sandbox="allow-scripts"` iframe.
75
+
76
+ **Scoring**
77
+
78
+ - Delivered lanes are screenshotted by an installed Chromium-family browser and
79
+ compared with the reference on a coarse colour grid; the highest score
80
+ suggests the winner. No browser means no score, and nothing else changes.
81
+ - Viewport defaults to the reference image's own pixel size.
82
+ - Per-lane wall-clock limit: a builder that keeps polishing is stopped and its
83
+ finished page is delivered and scored.
84
+
85
+ **Distribution**
86
+
87
+ - Format-1 plugin market index (`index.json`), validated with the official
88
+ `parseMarketIndex`, so the plugin installs from a Discover tab without npm.
89
+ - Storefront icon (`docs/assets/icon-180.png`), `screenshots.json`, GitHub
90
+ release tarball, and a ready-to-submit awesome-dsh-plugin entry.
91
+
92
+ **Tests**
93
+
94
+ - 30 unit tests (grammar, ranking, scoring, PNG decoding, engine lifecycle), a
95
+ real `git worktree` isolation test, and a render-and-score integration test
96
+ that drives the plugin's own scoring path.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Egor Fedorov
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,261 @@
1
- # Temporary Holding Version
1
+ <p align="center">
2
+ <a href="https://egorfedorov.github.io/dsh-clone/"><img src="docs/assets/hero.png" alt="dsh-clone — screenshot in, working UI out" width="100%"></a>
3
+ </p>
2
4
 
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.
5
+ <p align="center">
6
+ <a href="LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-4d6bff?style=flat-square"></a>
7
+ <img alt="DeepSeek Harness plugin" src="https://img.shields.io/badge/DeepSeek%20Harness-plugin-4d6bff?style=flat-square">
8
+ <img alt="Node 20+" src="https://img.shields.io/badge/node-%E2%89%A520-16202f?style=flat-square">
9
+ <a href="https://egorfedorov.github.io/dsh-clone/demo/"><img alt="Live demo" src="https://img.shields.io/badge/live-demo-22c55e?style=flat-square"></a>
10
+ <a href="https://github.com/egorfedorov/dsh-clone/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/egorfedorov/dsh-clone?style=flat-square&color=4d6bff"></a>
11
+ </p>
12
+
13
+ <h1 align="center">Screenshot in. Working UI out.</h1>
14
+
15
+ <p align="center">
16
+ Paste a screenshot of any interface. Run <code>/clone 3</code>. Three agents rebuild it in parallel,<br>
17
+ each in its own isolated directory. A live panel shows the reference beside every attempt,<br>
18
+ rendered and scored. You adopt the page that looks right — and it is already a working page.
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="https://egorfedorov.github.io/dsh-clone/demo/"><b>→ Open a real clone in the browser</b></a>
23
+ <br>
24
+ <sub>built by this plugin from <a href="docs/assets/reference.png">this screenshot</a> · 92.7% picture match</sub>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <img src="docs/assets/demo.gif" alt="The flow: the reference arrives, three lanes build in parallel, one is adopted and scored" width="100%">
29
+ </p>
30
+
31
+ ---
32
+
33
+ ## The 30-second version
34
+
35
+ ```
36
+ you: [paste a screenshot] /clone 3
37
+ me: ▸ three agents, three isolated directories, same reference
38
+ ▸ live panel: reference | lane 1 | lane 2 | lane 3 (rendered + scored)
39
+ you: [Adopt this one]
40
+ me: ▸ ./clone-a91c-lane-2/index.html ← open it, it runs
41
+ ```
42
+
43
+ No build step, no dependencies, no server. The adopted page is plain HTML, CSS and vanilla JS.
44
+
45
+ ## Why this exists
46
+
47
+ A screenshot is the most precise specification a person can give. Every other input loses information: a paragraph drops the spacing rhythm, the type scale, the alignment of every block; a component list drops the picture.
48
+
49
+ The usual flow is still: describe it, get one attempt, describe the differences, get another attempt. One attempt is a lottery — you cannot tell whether the model misunderstood you or simply chose a different solution, because you only ever see one.
50
+
51
+ `dsh-clone` changes the cost of being wrong. Three or four builders see the same reference and work the same problem from different angles, every delivered page is rendered and compared with the reference, and you keep the best.
52
+
53
+ | Lane strategy | What that builder is told to do |
54
+ |---|---|
55
+ | **Measure first** | write a layout spec — regions, grid, spacing scale, sampled hex palette, type scale — then build strictly to it |
56
+ | **Structure first** | the whole page as semantic HTML first, then style region by region from the outside in |
57
+ | **Visual first** | reproduce the picture first — surfaces, type, spacing, silhouette — then add only the behaviour the image implies |
58
+ | **Component first** | find the 5-8 reused parts, define each once, compose the page from them |
59
+
60
+ ## Demo
61
+
62
+ Real runs, not mocks: one command each, no retries, no hand edits. Every page is a static file — open it and it runs.
63
+
64
+ | Reference | The clone, rendered by the plugin | Result |
65
+ |---|---|---|
66
+ | <img src="docs/assets/nebula-dashboard.png" alt="reference observability dashboard" width="330"> | <img src="docs/assets/nebula-clone.png" alt="the dashboard clone, rendered" width="330"> | **91.9% match** · 1280×800 · two lanes raced, the better one adopted · [open it](https://egorfedorov.github.io/dsh-clone/demo/nebula/) |
67
+ | <img src="docs/assets/aperture-landing.png" alt="reference landing page" width="330"> | <img src="docs/assets/aperture-clone.png" alt="the landing clone, rendered" width="330"> | **91.9% match** · 1280×800 · one lane · [open it](https://egorfedorov.github.io/dsh-clone/demo/aperture/) |
68
+ | <img src="docs/assets/card-reference.png" alt="reference billing card" width="330"> | <img src="docs/assets/card-clone.png" alt="the billing card clone, rendered" width="330"> | **97.8% match** · 520×360 · one file · [open it](https://egorfedorov.github.io/dsh-clone/demo/card.html) |
69
+ | <img src="docs/assets/reference.png" alt="reference sign-in screen" width="330"> | <img src="demo/preview.png" alt="the sign-in clone, rendered" width="330"> | **79% match** · 900×620 · [open it](https://egorfedorov.github.io/dsh-clone/demo/) |
70
+
71
+ The dashboard and the landing page are the interesting ones: a sidebar, KPI cards with sparklines, a layered area chart, a donut, a data table; glass panels over a gradient mesh, a feature grid and a footer. Both were rebuilt from a single screenshot.
72
+
73
+ The score is the plugin's own, and it has three parts: both images are averaged into a coarse colour grid, the colour comparison forgives a small uniform shift, and a separate **structure** term compares where the detail sits. The mix measures *how much of the picture agrees*, not whether the page is correct — two unrelated dark interfaces land around 58%, a faithful rebuild above 90%. See [Honest limits](#honest-limits).
74
+
75
+ ## Install
76
+
77
+ **In the Harness Web UI** — Settings → Plugins → **Add plugin**, then install by package name:
78
+
79
+ ```
80
+ dsh-clone
81
+ ```
82
+
83
+ Or add this repository's market index under **Plugins → Custom plugin indexes**, and install `dsh-clone` from the Discover tab in one click:
84
+
85
+ ```
86
+ https://raw.githubusercontent.com/egorfedorov/dsh-clone/main/index.json
87
+ ```
88
+
89
+ **From a checkout** (development):
90
+
91
+ ```bash
92
+ git clone https://github.com/egorfedorov/dsh-clone
93
+ # Settings → Plugins → Add plugin → /absolute/path/to/dsh-clone
94
+ ```
95
+
96
+ **Updating** — the market reports `update-available` when this repository's index (or npm) lists a newer compatible version. The market format has no in-place upgrade, so an update is a reinstall: your work lives in the workspace (`.dsh-clone/`, `clone-*/`), so reinstalling loses nothing. See [docs/PUBLISHING.md](docs/PUBLISHING.md) for the whole distribution story.
97
+
98
+ Requires a DeepSeek Harness profile with `subagents` (the `dsh-base` bundle ships the `spawn` backend) and Node 20+. Scoring additionally uses a Chromium-family browser if one is installed; without it everything else still works.
99
+
100
+ ## Usage
101
+
102
+ Paste a screenshot into the conversation, then:
103
+
104
+ | Command | What it does |
105
+ |---|---|
106
+ | `/clone` | 3 lanes rebuild the last image in this conversation |
107
+ | `/clone 4` | four lanes — maximal spread of approaches |
108
+ | `/clone 2 darker, mobile-first` | two lanes plus a note every builder must honour |
109
+ | `/clone 3 ./mock.png` | use an explicit image path instead of the conversation image |
110
+ | `/clone status` | lane states, scores, and the suggested winner |
111
+ | `/clone pick 2` | adopt lane 2 into the workspace |
112
+ | `/clone refine 2 move the CTA up` | rebuild the adopted page with one change, scored against the same reference |
113
+ | `/clone cancel` | stop the builders |
114
+ | `/clone discard` | delete the scratch directories and lane branches |
115
+
116
+ The agent has the same operations as a tool, so you can also just say *"rebuild this screenshot, three tries"*:
117
+
118
+ ```
119
+ clone({ action: "start", lanes: 3, note: "keep the sidebar" })
120
+ clone({ action: "status" })
121
+ clone({ action: "pick", lane: 2 })
122
+ ```
123
+
124
+ ### The panel
125
+
126
+ A **Clone** tab appears in the conversation view ring while a clone exists:
127
+
128
+ - the reference screenshot on the left, at the size the lanes are building for;
129
+ - one card per lane: a live iframe of the actual page, its strategy, elapsed time, tool calls, file count, token spend, and its **picture-match score** once rendered;
130
+ - the best-scoring lane is marked as suggested, and **Adopt this one** works on any lane that produced an `index.html`.
131
+
132
+ A small chip under the composer shows `clone · 2/3` while builders run, so you can leave the tab.
133
+
134
+ ## How it works
135
+
136
+ **Isolation.** Each lane gets its own directory. Inside a git repository that is a real `git worktree` on its own branch (`dsh-clone/<id>-lane-<n>`), so nothing leaks between attempts and nothing touches your working tree. Outside a repository it is a plain directory under `.dsh-clone/<id>/lane-<n>/`. Existing `node_modules`, `.venv` and `vendor` are symlinked into each lane instead of reinstalled.
137
+
138
+ **The builders.** Each lane is a subagent with one job: read the reference image, then ship `index.html` plus any local CSS/JS/assets. The delivery contract is identical for every lane and non-negotiable:
139
+
140
+ > no build step · no network at runtime · no CDN · no placeholder copy · fill the viewport · approximate every image with CSS/SVG · leave no scratch files
141
+
142
+ The strategies differ; the contract does not. Every lane also carries an explicit effort budget (≈20-25 tool calls) and a wall-clock limit: a builder that keeps polishing is stopped, and whatever it already wrote is delivered and scored instead of stalling the clone.
143
+
144
+ **The score.** When a lane delivers, the plugin finds an installed Chromium-family browser (Chrome, Chromium, Edge, Brave — `DSH_CLONE_BROWSER` overrides), screenshots the page at the reference's own pixel size, and compares it with the reference: both images are averaged into a 48×32 colour grid and the mean absolute difference becomes a percentage. Highest score suggests the winner; you still choose. No browser, no score — the panel then falls back to completeness and finish order.
145
+
146
+ **The preview.** Lane pages are served from this page's own origin through `/api/dsh-clone/preview/<clone>/<lane>/` — no extra port, no proxy, the same authenticated connection the UI already uses. Because the HTML is model-written, it is served with a `sandbox` CSP (no `allow-same-origin`) and mounted in a `sandbox="allow-scripts"` iframe: a clone can run its own code, but it cannot reach your session, credentials, or the Harness API.
147
+
148
+ **Adoption.** `pick` copies the chosen lane into the workspace as `clone-<id>-lane-<n>/`, without `.git`, without the symlinked dependency directories, and without the builder's scratch files. The other lanes stay where they are until you `/clone discard`.
149
+
150
+ **Iteration.** `refine` takes an adopted lane, copies its page into a fresh single-lane clone and asks the builder for the smallest edit that satisfies one change — the reference and the viewport stay the same, so the new score is directly comparable and the clone reports the delta.
151
+
152
+ **Durability.** Each clone writes a small `state.json` next to its work. A plugin reload or a restart does not throw the run away: `status` and `pick` rebuild it from disk, and a lane that was mid-build keeps whatever it had already written, labelled as interrupted rather than pretending it finished.
153
+
154
+ **Budgets.** Every builder gets an effort budget in the prompt and a wall-clock limit (`laneTimeoutMs`); whichever is hit first settles the lane with whatever it delivered. `laneTokenBudget` adds a hard token ceiling and is off by default, because an agent re-sends its context on every step — a small ceiling stops honest builds mid-analysis, so it is a deliberate opt-in backstop rather than a default.
155
+
156
+ **The nudge.** Some models answer "measure first" by sampling the screenshot's pixels for their entire budget and then ending with nothing written. If a lane is past `nudgeAtTools` (12) tool calls with no `index.html` on disk, the plugin sends it one steering message: stop measuring, write the page now. One message, once per lane.
157
+
158
+ ## Configuration
159
+
160
+ All optional; the defaults are the intended experience.
161
+
162
+ | Key | Default | Meaning |
163
+ |---|---|---|
164
+ | `lanes` | `3` | lane count when the command does not name one |
165
+ | `maxLanes` | `4` | hard cap on lanes per clone |
166
+ | `viewport` | `auto` | build and render size; `auto` uses the reference image's own pixel size |
167
+ | `laneTimeoutMs` | `900000` | wall-clock limit per lane (15 min); the lane is stopped and its output kept |
168
+ | `laneTokenBudget` | `0` (off) | token ceiling per lane. Off by default because an agent re-sends its context every step; 2M+ is a sensible backstop |
169
+ | `nudgeAtTools` | `12` | tool calls after which a lane with no `index.html` is told to stop analysing and write the page; `0` disables it |
170
+ | `provider` | `spawn` | `ctx.subagents` backend used for builders |
171
+ | `pollMs` | `900` | live counter refresh interval |
172
+ | `commandName` | `clone` | rename the slash command |
173
+ | `command` / `tool` | `true` | disable either entry point |
174
+
175
+ ```yaml
176
+ - id: dsh-clone
177
+ name: dsh-clone
178
+ config:
179
+ lanes: 4
180
+ laneTimeoutMs: 600000
181
+ ```
182
+
183
+ ## Safety
184
+
185
+ - Clones are **static pages**: no package installs, no network at runtime, no server.
186
+ - Lane pages are sandboxed into an opaque origin, so model-written HTML cannot reach your session, credentials, or the Harness API.
187
+ - Every write happens inside the workspace: `.dsh-clone/` for scratch, `clone-*/` for adopted results, plus lane branches in your repository (removed by `/clone discard`).
188
+ - `git worktree` is used without touching your checkout: no commit, no checkout, no reset in your working tree. `test/git-lane.mjs` asserts exactly that.
189
+ - The scoring renderer is a one-shot headless screenshot of a local file. It loads no remote page.
190
+
191
+ ## Honest limits
192
+
193
+ - **Cost is N×.** Three builders cost roughly three builds. `lanes: 2` is a reasonable everyday setting; `lanes: 1` makes it a plain "screenshot → page" button.
194
+ - **The score measures the picture, not the truth.** 92% agreement can still hide wrong copy, a missing form action, or broken behaviour. It ranks attempts; it does not certify one.
195
+ - **The score is coarse by design.** A 48×32 grid with shift tolerance is forgiving about a few pixels and strict about a panel on the wrong side; the structure term catches "right colour, wrong picture". Two lanes a few points apart are still a coin flip — open both before adopting.
196
+ - **Vision is required.** The builder must actually see the reference. A text-only model produces a guess; pair dsh-clone with a vision-capable route or a vision bridge plugin.
197
+ - **Images are approximated.** Without image generation, photos and illustrations become CSS/SVG stand-ins with the right silhouette and palette, not the original pixels.
198
+ - **Static output.** No Next.js project, no design system — by design, so the result is always runnable in one click.
199
+ - **Scoring needs an installed browser.** Chrome, Chromium, Edge or Brave on macOS, Windows or Linux; `DSH_CLONE_BROWSER` overrides the probe. No browser means no percentage, and nothing else changes.
200
+ - **A careful builder is a slow builder.** Hence the effort budget and the wall-clock limit; tune those, not your patience.
201
+
202
+ ## Roadmap
203
+
204
+ 1. **Region scoring** — "clone just this card": compare only the rectangle that matters instead of the whole page.
205
+ 2. **Adopt as a diff** — when the workspace is a component library, adopt as an edit to an existing file instead of a new folder.
206
+ 3. **Multi-reference** — several screenshots of the same flow, one page per screen.
207
+ 4. **Panel screenshots in the storefront** — the four declared images are plugin output, not the panel itself.
208
+
209
+ ## Repository layout
210
+
211
+ ```
212
+ index.js Host half: /clone command, clone tool, web routes, poller
213
+ client.js Client half: the Clone panel and the composer chip
214
+ lib/engine.js Clone state machine (pure, dependency-injected)
215
+ lib/prompts.js The delivery contract, the effort budget, four strategies
216
+ lib/render.js Headless screenshot through an installed Chromium browser
217
+ lib/score-lane.js Render-and-score composition shared by the plugin and its test
218
+ lib/score.js Coarse-grid picture comparison
219
+ lib/png.js Dependency-free PNG decoder
220
+ lib/parse.js /clone grammar
221
+ lib/rank.js Adoptability, score-first ordering, suggestion
222
+ lib/preview.js Static lane serving, media types, sandbox CSP, JSON routes
223
+ lib/util.js Small pure helpers
224
+ test/smoke.mjs 30 tests, no Harness required
225
+ test/git-lane.mjs worktree isolation against a real repository
226
+ test/render-score.mjs real render + score through the plugin's own path
227
+ index.json Format-1 plugin market index (Custom plugin indexes)
228
+ screenshots.json Storefront screenshots (read by dsh-market)
229
+ tools/make-hero.py Regenerates docs/assets/hero.png
230
+ tools/make-references.py Regenerates the showcase reference screenshots
231
+ tools/make-icon.py Regenerates the storefront icon
232
+ tools/make-demo.py Regenerates docs/assets/demo.gif
233
+ docs/PUBLISHING.md npm, the awesome list, indexes, the official program
234
+ docs/storefront/ Ready-to-submit entry for awesome-dsh-plugin
235
+ docs/index.html GitHub Pages landing page
236
+ docs/demo/ Four real clones, served live
237
+ docs/ARCHITECTURE.md
238
+ ACCEPTABLE-USE.md
239
+ ```
240
+
241
+ ## Development
242
+
243
+ ```bash
244
+ npm run check # syntax-check every shipped file
245
+ npm test # 30 assertions: grammar, ranking, scoring, engine lifecycle
246
+ npm run test:git # the git-worktree isolation model against a real repository
247
+ npm run test:score # a real render + score through the plugin's own code path
248
+ npm run test:all # all three
249
+ ```
250
+
251
+ The engine takes every side effect as a dependency, so the tests drive the real state machine against a temporary directory with fake subagents — no Harness, no network, no model. The pixel tests decode the demo reference and a committed real lane render, so a regression in either the decoder or the scoring curve fails the suite. `test/git-lane.mjs` builds a throwaway repository to prove that lanes are real worktrees, that your own dirty working tree and branch are untouched, that dependency directories are shared by symlink, and that discard removes worktrees and branches while the adopted copy survives. `test/render-score.mjs` goes through the plugin's own scoring path with two fake builders — one faithful, one deliberately desaturated — and asserts that both come back scored, that the faithful one wins, and that the snapshot carries the score and the render URL. It skips itself when no browser is installed.
252
+
253
+ ## По-русски
254
+
255
+ Плагин для DeepSeek Harness: скидываешь скриншот интерфейса, пишешь `/clone 3` — три агента параллельно собирают его в изолированных папках (в репозитории — через git worktree). В панели «Clone» видно эталон и все попытки рядом; каждая готовая страница рендерится в headless-браузере и получает процент совпадения картинки. Нажимаешь «Adopt this one» — выбранный вариант копируется в рабочую папку как готовая страница. Остальные удаляются командой `/clone discard`.
256
+
257
+ Честно: стоимость — примерно N попыток; оценка совпадения меряет картинку, а не правильность (текст и поведение всё равно проверяй глазами); нужна модель, которая видит изображение.
258
+
259
+ ## License
260
+
261
+ MIT — see [LICENSE](LICENSE). Use it on interfaces you have the right to rebuild; see [ACCEPTABLE-USE.md](ACCEPTABLE-USE.md).