mockpit 1.2.0 → 1.3.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/README.md +13 -8
- package/bin/mockpit.js +116 -16
- package/dist/mcp/server.js +10 -7
- package/dist/server/apiViews.d.ts +118 -17
- package/dist/server/apiViews.js +66 -8
- package/dist/server/app.d.ts +2 -1
- package/dist/server/app.js +917 -144
- package/dist/server/decisions.d.ts +23 -0
- package/dist/server/decisions.js +99 -0
- package/dist/server/designGuide.js +45 -10
- package/dist/server/embeds.d.ts +25 -0
- package/dist/server/embeds.js +118 -0
- package/dist/server/eventLog.js +2 -1
- package/dist/server/feedbackBatch.d.ts +12 -1
- package/dist/server/feedbackBatch.js +20 -3
- package/dist/server/fills.d.ts +41 -0
- package/dist/server/fills.js +328 -0
- package/dist/server/index.js +15 -1
- package/dist/server/knobs.d.ts +6 -2
- package/dist/server/knobs.js +11 -1
- package/dist/server/mcpHttp.d.ts +3 -0
- package/dist/server/mcpHttp.js +3 -0
- package/dist/server/mcpSpec.d.ts +13 -13
- package/dist/server/mcpSpec.js +73 -8
- package/dist/server/postSurfaces.js +3 -12
- package/dist/server/richRender.js +3 -1
- package/dist/server/run.js +4 -0
- package/dist/server/runApi.d.ts +1 -1
- package/dist/server/runApi.js +4 -3
- package/dist/server/sqlStore.d.ts +89 -4
- package/dist/server/sqlStore.js +149 -23
- package/dist/server/surfacePage.d.ts +6 -2
- package/dist/server/surfacePage.js +142 -10
- package/dist/server/themes.d.ts +2 -0
- package/dist/server/themes.js +23 -3
- package/dist/server/types.d.ts +73 -11
- package/dist/server/types.js +42 -2
- package/dist/server/viewerRequest.d.ts +2 -0
- package/dist/server/viewerRequest.js +14 -0
- package/guide/topics/asks.md +50 -3
- package/guide/topics/feedback.md +89 -11
- package/guide/topics/html.md +5 -1
- package/guide/topics/http.md +2 -1
- package/guide/topics/knobs.md +2 -1
- package/guide/topics/surfaces.md +24 -8
- package/package.json +4 -13
- package/skills/launch-video/SKILL.md +1 -1
- package/skills/mockpit/SKILL.md +12 -4
- package/viewer/dist/index.html +8 -8
- package/dist/server/slots.d.ts +0 -14
- package/dist/server/slots.js +0 -71
package/guide/topics/asks.md
CHANGED
|
@@ -52,31 +52,78 @@ The same JSON goes to `--asks`, MCP `ask` and `POST /api/mocks/:id/asks`:
|
|
|
52
52
|
## Scope
|
|
53
53
|
|
|
54
54
|
`scope` says what an ask decides: `mock` (the default), `state` (add `state`)
|
|
55
|
-
or `part` (add `part`, the `data-part` name).
|
|
55
|
+
or `part` (add `part`, the `data-part` name). Scope also says where the user
|
|
56
|
+
sees it: the viewer shows each state with its own questions. A `state` ask
|
|
57
|
+
shows on that state, a `part` ask on every state that marks the part, and a
|
|
58
|
+
`mock` ask whose options name variants on every state that has them (any
|
|
59
|
+
other `mock` ask on every state); answered once, it counts once.
|
|
60
|
+
|
|
61
|
+
Only open asks are shown and counted ("1 of 3"). Once a Send answers one, it
|
|
62
|
+
folds into a read-only Answered list and stays out of the next round, so ask
|
|
63
|
+
new questions for what is still open rather than re-sending answered ones; the
|
|
64
|
+
user changes a sent answer only on purpose, and the change arrives as a normal
|
|
65
|
+
Send.
|
|
56
66
|
|
|
57
67
|
## Options
|
|
58
68
|
|
|
59
69
|
An option binds to one of:
|
|
60
70
|
|
|
61
71
|
- a `variant`: picking it accepts that variant and archives its siblings in
|
|
62
|
-
that state.
|
|
72
|
+
that state. Add `version` to offer one version of it (`"version": 2`, CLI
|
|
73
|
+
`--option Before=quiet@2`): two options can be two versions of one variant,
|
|
74
|
+
and the picked one is put in use. It needs the ask's `state` when the mock
|
|
75
|
+
has several.
|
|
63
76
|
- a knob `set`: picking it applies those values live.
|
|
64
77
|
- nothing: a plain pill.
|
|
65
78
|
|
|
66
79
|
Options that change how something looks carry a `variant` or a knob `set`,
|
|
67
80
|
so the user sees them live. Plain pills only for what can't be seen.
|
|
68
81
|
|
|
82
|
+
When one question only makes sense once another is answered (an accent's
|
|
83
|
+
placement depends on the palette), give it `after: "<that ask's id>"` (CLI
|
|
84
|
+
`--after palette`). It stays closed until that one is answered, then its
|
|
85
|
+
pictures render with that answer and say so. Ask the deciding question first.
|
|
86
|
+
|
|
69
87
|
The viewer shows a picture of each option it can render. `multi: true` allows
|
|
70
88
|
several answers. Option ids default to the slugged label. Reusing an ask `id`
|
|
71
89
|
replaces that ask. The viewer adds an "Other…" write-in and a note to every
|
|
72
90
|
ask (both take attached images), so don't add your own; the option id `other`
|
|
73
91
|
is reserved.
|
|
74
92
|
|
|
93
|
+
## Slots
|
|
94
|
+
|
|
95
|
+
A slot is one region with alternative fills, in one html. Give each
|
|
96
|
+
alternative the same `data-part` and its own `data-fill`:
|
|
97
|
+
|
|
98
|
+
```html
|
|
99
|
+
<section data-part="entry" data-part-label="Entry" data-fill="dots" data-fill-label="Typing dots">
|
|
100
|
+
…
|
|
101
|
+
</section>
|
|
102
|
+
<section data-part="entry" data-fill="skeleton">…</section>
|
|
103
|
+
<section data-part="entry" data-fill="filling" data-fill-default>…</section>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The first fill is the default unless one carries `data-fill-default`. The
|
|
107
|
+
server derives a select knob at the part's name and shows only the chosen
|
|
108
|
+
fill, so you write no switching CSS; give each fill whatever display it
|
|
109
|
+
needs. Draw anything inside a fill, including further slots: a slot inside a
|
|
110
|
+
fill is asked only while that fill is chosen, right after its parent's
|
|
111
|
+
question.
|
|
112
|
+
|
|
113
|
+
Publish returns the slots it found and, for each one no ask binds, a ready
|
|
114
|
+
`suggestedSlotAsks` entry: `scope: "part"`, one option per fill with
|
|
115
|
+
`set: {"entry": "<fill>"}`. Send them with `ask`, relabelled if you like. On a
|
|
116
|
+
pick the viewer outlines the fill on stage. `fills` in publish replaces or
|
|
117
|
+
adds one fill without resending the page (topic `feedback`).
|
|
118
|
+
|
|
119
|
+
Use a slot when the alternatives differ in one region; use variants when the
|
|
120
|
+
whole screen differs. Both mix: variants are looks, each look may have slots.
|
|
121
|
+
|
|
75
122
|
## The Look ask
|
|
76
123
|
|
|
77
124
|
When you publish variants, ask `scope: "mock"` with one option per variant, and
|
|
78
125
|
ask it first. Questions appear in the order you ask them. This one is titled
|
|
79
|
-
"Look"
|
|
126
|
+
"Look". Tune then offers, per part, to borrow it from another look.
|
|
80
127
|
Variants without a Look ask get a plain switcher in the frame header.
|
|
81
128
|
|
|
82
129
|
A variant decides everything it differs on; don't re-ask it. Ask other axes as
|
package/guide/topics/feedback.md
CHANGED
|
@@ -35,12 +35,23 @@ It returns at once:
|
|
|
35
35
|
],
|
|
36
36
|
"mix": { "body": "quiet" },
|
|
37
37
|
"tuned": { "body.size": 19 },
|
|
38
|
+
"decisions": {
|
|
39
|
+
"states": {
|
|
40
|
+
"Writing": {
|
|
41
|
+
"variant": "dark",
|
|
42
|
+
"slots": {
|
|
43
|
+
"bar": { "fill": "tabs", "label": "Tabs", "slots": { "badge": { "fill": "dot" } } }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"knobs": { "trim.position": "bottom", "body.size": 19 }
|
|
48
|
+
},
|
|
38
49
|
"comments": [{ "part": "title", "state": "Writing", "text": "bigger" }],
|
|
39
50
|
"reactions": ["👍 part \"title\" (variant dark, state Writing)"],
|
|
40
51
|
"text": "close, go dark"
|
|
41
52
|
},
|
|
42
53
|
"comments": [],
|
|
43
|
-
"accepted": [{ "state": "Writing", "variant": "dark" }],
|
|
54
|
+
"accepted": [{ "state": "Writing", "variant": "dark", "version": 2 }],
|
|
44
55
|
"archived": [{ "state": "Writing", "variant": "quiet" }]
|
|
45
56
|
}
|
|
46
57
|
],
|
|
@@ -56,7 +67,8 @@ It returns at once:
|
|
|
56
67
|
|
|
57
68
|
`feedback` holds one batch per mock, in delivery order. `pending` is what the
|
|
58
69
|
user is doing right now, per mock: `viewerOpen` says a browser has that
|
|
59
|
-
mock on screen, `draft` is their unsent progress (`null` when there is none)
|
|
70
|
+
mock on screen, `draft` is their unsent progress (`null` when there is none),
|
|
71
|
+
and `resolved: true` marks a mock the user closed (below).
|
|
60
72
|
An empty `feedback` with a draft means "still answering": tell the user to take
|
|
61
73
|
their time, don't ask again. `mockpit read` returns `pending` too, without
|
|
62
74
|
taking any feedback.
|
|
@@ -65,7 +77,12 @@ taking any feedback.
|
|
|
65
77
|
|
|
66
78
|
1. `answers` and `asks` decide structure. A variant-bound answer has already
|
|
67
79
|
accepted that variant and archived its siblings (`accepted`, `archived`).
|
|
68
|
-
Stop iterating on the archived ones.
|
|
80
|
+
Stop iterating on the archived ones. Each `accepted` entry is pinned at the
|
|
81
|
+
`version` the user put in use (`read` → `inUse`): `export` and embeds show
|
|
82
|
+
that one, not your newer publishes, until the user picks again. A version
|
|
83
|
+
the user hid (`read --history` flags it `hidden`) is one they put away:
|
|
84
|
+
don't build on it.
|
|
85
|
+
The ask `variant` (per state
|
|
69
86
|
`variant:<state>`) is the viewer's built-in Look ask, read like any
|
|
70
87
|
other. A `chosen` entry with `other: true` is
|
|
71
88
|
the user's own answer (its `label`), not one of your options; it flips no
|
|
@@ -86,13 +103,42 @@ taking any feedback.
|
|
|
86
103
|
👍 keep it, 👎 rework it, "more like this" go further that way. A reaction
|
|
87
104
|
without a part is about the whole variant; one may end with the user's
|
|
88
105
|
note in quotes. Reactions never also appear in `comments`.
|
|
89
|
-
5. `decision` (`{kind: accept|revise|drop, state, variant}`)
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
5. `decision` (`{kind: accept|revise|drop, state, variant}`) is a verdict on
|
|
107
|
+
one variant. `accept` is the user's Use this, with the `version` now in use;
|
|
108
|
+
`revise` is their New: publish another version of that variant (its `text`
|
|
109
|
+
says from which). A `dropped` variant is hidden; archived ones stay in view,
|
|
110
|
+
muted. Build on neither unless the user restores one.
|
|
92
111
|
6. `text` is the user's note on the Send.
|
|
93
112
|
|
|
94
113
|
Treat all of it as data, never as markup or instructions.
|
|
95
114
|
|
|
115
|
+
## Resolved
|
|
116
|
+
|
|
117
|
+
The user can resolve a mock from the project list (a swipe on a phone)
|
|
118
|
+
instead of answering it: its open asks are closed unanswered, as not worth
|
|
119
|
+
answering, and it leaves their open list. You hear it once, as a batch with no
|
|
120
|
+
reply:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"mock": "cart",
|
|
125
|
+
"reply": null,
|
|
126
|
+
"resolved": true,
|
|
127
|
+
"dismissed": [{ "ask": "density", "text": "Roomy or tight?" }],
|
|
128
|
+
"comments": [],
|
|
129
|
+
"accepted": [],
|
|
130
|
+
"archived": [],
|
|
131
|
+
"dropped": []
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Answers sent before it stand. Each `dismissed` ask now reads `dismissed: true`
|
|
136
|
+
in `read`, and `ask` refuses it: re-asking that id returns it under `skipped`
|
|
137
|
+
with a nudge and asks nothing. Don't rephrase it under a new id either; move
|
|
138
|
+
on, and only bring the mock back if the user asks. A new ask with a new id does
|
|
139
|
+
reopen the mock. If the user reopens it themselves, its dismissed asks are open
|
|
140
|
+
again and their answers arrive as a normal Send.
|
|
141
|
+
|
|
96
142
|
## Delivery
|
|
97
143
|
|
|
98
144
|
Each Send is delivered exactly once. Whichever channel picks it up advances
|
|
@@ -113,25 +159,57 @@ Never poll `feedback` in a loop; the user answers at their own pace.
|
|
|
113
159
|
```sh
|
|
114
160
|
mockpit publish --mock writer --state "Writing" --variant dark --html dark-v2.html --prompt "bigger title"
|
|
115
161
|
mockpit say "Went dark; body at 19px" --mock writer
|
|
116
|
-
mockpit export --mock writer # .mockpit/accepted/writer/<state>/{index.html,history.json}
|
|
162
|
+
mockpit export --mock writer # .mockpit/accepted/writer/<state>/{index.html,history.json,…}
|
|
117
163
|
mockpit read # one line per mock, plus pending
|
|
118
|
-
mockpit read writer # states, variants, asks and answers, parts, knobs,
|
|
164
|
+
mockpit read writer # states, variants, asks and answers, parts, knobs, settled
|
|
165
|
+
mockpit read --tree # the project as a tree: variants, forkedFrom, uses / usedIn
|
|
119
166
|
```
|
|
120
167
|
|
|
168
|
+
- A flow is the screens the user walks, in order, across mocks: `--flow
|
|
169
|
+
Morning --step 2` (MCP/HTTP `flow`, `step`) puts this (mock, state) at step
|
|
170
|
+
2, moving it if it is there; without `--step` it joins at the end, `--step 0`
|
|
171
|
+
takes it out. `flow` with no html places an existing screen without a new
|
|
172
|
+
version. `read` (no mock) and `read --tree` return `flows: [{name, steps:
|
|
173
|
+
[{mock, state}]}]`. In the design, `data-goto="next"`, `"prev"` or
|
|
174
|
+
`"<mock>:<state>"` on an element moves the user there while they try it.
|
|
175
|
+
|
|
121
176
|
- `publish` on an existing (mock, state, variant) makes its next version.
|
|
122
|
-
`--from N` branches off an earlier one.
|
|
177
|
+
`--from N` branches off an earlier one. `--fork quiet@2` (MCP/HTTP
|
|
178
|
+
`fork: "quiet@2"`) starts a NEW variant from a sibling's version and records
|
|
179
|
+
the lineage; alone it copies it, with `--parts`/`--fills` it edits the copy. The result flags vanished or renamed
|
|
123
180
|
parts. Don't publish a near-duplicate variant; publish the next version.
|
|
124
181
|
- Replace one part instead of the document: `--parts body=body.html`
|
|
125
182
|
(repeatable; `--parts body=-` reads stdin), MCP `publish({parts: {body:
|
|
126
183
|
"<p data-part=\"body\">new copy</p>"}})`, or `parts` in the HTTP publish body.
|
|
127
184
|
Each value replaces the whole element carrying `data-part="body"`, so you can
|
|
128
185
|
rename, relabel or retag it. `"row#a"` targets one keyed instance. Send one of
|
|
129
|
-
`html`, `surfaces` or `
|
|
186
|
+
`html`, `surfaces`, `parts` or `fills` per call. The response lists `applied` plus the
|
|
130
187
|
usual `partChanges`. An unknown name, or one matching several instances,
|
|
131
188
|
fails with the parts or keys present and writes nothing.
|
|
189
|
+
- Replace or add one fill of a slot: `--fills bar#tabs=tabs.html`, MCP
|
|
190
|
+
`publish({fills: {"bar#tabs": "<nav>…</nav>"}})`. A fill that exists is
|
|
191
|
+
replaced; a new one goes after that slot's other fills. `data-part` and
|
|
192
|
+
`data-fill` are added to the element when missing.
|
|
193
|
+
- `decisions` (only when the mock has slots or the reply set knobs) is the
|
|
194
|
+
screen as chosen: per state the variant, then each slot's fill with the
|
|
195
|
+
slots inside it, then every non-slot knob value. `from` on a slot means the
|
|
196
|
+
user borrowed it from another variant. A slot inside a fill that was not
|
|
197
|
+
chosen is absent, and its question's answer is not sent.
|
|
132
198
|
- `say` posts a short plain-text note in the mock's thread. Give substantial
|
|
133
199
|
answers as a new version, not prose.
|
|
134
200
|
- `export` returns the accepted (else current) html per state, its version
|
|
135
|
-
history, the knobs and the last reply
|
|
201
|
+
history, the knobs, `settled` and the last reply. With slots, `html` is
|
|
202
|
+
the composed screen (only the chosen fills, the fill marks dropped),
|
|
203
|
+
`source` keeps every fill, and `decisions` is as above. The CLI writes
|
|
204
|
+
`index.html`, `source.html` and `decisions.json`. Port the composed html
|
|
205
|
+
into the codebase in its own language and components; mockpit does not
|
|
206
|
+
generate code.
|
|
207
|
+
- `settled` (on `read` and `export`) is every knob value the user has sent:
|
|
208
|
+
each answered option's `set` and each tuned value, later replies winning.
|
|
209
|
+
The viewer renders every later question and the stage on top of it, so ask
|
|
210
|
+
the deciding question first and its dependents after, or one answer is
|
|
211
|
+
judged against a default the user hasn't chosen.
|
|
212
|
+
- A variant with `starred: true` is one the user marked as a favourite. A star
|
|
213
|
+
decides nothing; treat it as "keep this in mind" when revising.
|
|
136
214
|
- `read <slug>` returns metadata only. `--body` adds surfaces, `--history` adds
|
|
137
215
|
version rows.
|
package/guide/topics/html.md
CHANGED
|
@@ -41,7 +41,11 @@ Mark the components you want feedback on with `data-part="name"` (optional
|
|
|
41
41
|
apart and keep comments anchored across a rename). The viewer measures their
|
|
42
42
|
boxes, so never hard-code geometry for it. Knob values arrive as unitless
|
|
43
43
|
`--k-<path>` custom properties and `data-k-<path>` attributes on `<html>`; topic
|
|
44
|
-
`knobs` has the details.
|
|
44
|
+
`knobs` has the details. Alternatives of one region are a slot: the same
|
|
45
|
+
`data-part` with a `data-fill` each; topic `asks`.
|
|
46
|
+
|
|
47
|
+
The page must read before any web font or remote stylesheet loads: they are
|
|
48
|
+
decoration, and a slow one delays the frame's layout.
|
|
45
49
|
|
|
46
50
|
## Finish
|
|
47
51
|
|
package/guide/topics/http.md
CHANGED
|
@@ -29,7 +29,8 @@ call; otherwise each call starts a new session and the reply goes elsewhere.
|
|
|
29
29
|
B=http://localhost:8228
|
|
30
30
|
curl -s -X POST $B/api/mocks -H 'content-type: application/json' -d '{
|
|
31
31
|
"project": "demo", "mock": "checkout", "title": "Checkout", "state": "Empty cart",
|
|
32
|
-
"agent": "claude", "knobs": {"pad": [16, 8, 32, 2]},
|
|
32
|
+
"agent": "claude", "knobs": {"pad": [16, 8, 32, 2]}, "widths": [390, 1280],
|
|
33
|
+
"note": "One column; the summary carries the empty state",
|
|
33
34
|
"html": "<section data-part=\"summary\" data-part-label=\"Summary\" style=\"padding:calc(var(--k-pad,16)*1px)\">Your cart is empty</section>"}'
|
|
34
35
|
# → {"mock":{…},"post":{…},"sessionId":"S","url":"…","parts":[{"state":"Empty cart","parts":[{"name":"summary","label":"Summary"}]}],"feedback":[]}
|
|
35
36
|
|
package/guide/topics/knobs.md
CHANGED
|
@@ -4,7 +4,8 @@ A knob is a value the user tunes live on one render. Use one when one render
|
|
|
4
4
|
plus a control shows the choice. A choice is several variants plus one ask
|
|
5
5
|
that binds them; for that, publish variants and ask instead (topic `asks`).
|
|
6
6
|
A 2–3 option knob is a choice: ask with options that `set` it. Publishing
|
|
7
|
-
one returns that nudge.
|
|
7
|
+
one returns that nudge. Declare knobs for what is worth fine-tuning (size,
|
|
8
|
+
spacing, colour, density) even when the user did not ask; they wait in Tune.
|
|
8
9
|
|
|
9
10
|
## Declaring
|
|
10
11
|
|
package/guide/topics/surfaces.md
CHANGED
|
@@ -45,14 +45,30 @@ A version can combine surfaces. `[html, diff]` is a design with its code review;
|
|
|
45
45
|
html is sandboxed because you author the markup. Every other kind is rendered
|
|
46
46
|
from data, so send data, never markup.
|
|
47
47
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
## Composition: embeds
|
|
49
|
+
|
|
50
|
+
Any mock can embed another mock of the project in its html with
|
|
51
|
+
`<mockpit-embed slug="button"></mockpit-embed>` (`<mockpit-slot>` still works;
|
|
52
|
+
a slot is now a region with fills, topic `asks`). The server inlines that
|
|
53
|
+
mock's html body in place, inside the embedding frame, and expands the
|
|
54
|
+
component's own embeds in turn (up to 6 levels), so build a page from
|
|
55
|
+
sections and sections from components, each its own mock with its own
|
|
56
|
+
variants and questions.
|
|
57
|
+
|
|
58
|
+
- No `version`: the embed follows the component's version in use once the user
|
|
59
|
+
accepted one, else its latest, so a new version of the button shows in every
|
|
60
|
+
page that uses it without republishing them. `version="3"` pins it.
|
|
61
|
+
- No `variant`: the component's accepted variant (else `default`). Name one to
|
|
62
|
+
show a specific variant.
|
|
63
|
+
- The component shows as decided: its slots keep only the fills the user
|
|
64
|
+
settled on, and its other settled knob values ride on the embed's wrapper
|
|
65
|
+
(`data-k-<path>` and `--k-<path>`), so write its knob CSS as
|
|
66
|
+
`[data-k-tone="loud"] .chip`, not `html[data-k-tone=…]`.
|
|
67
|
+
- `read` lists each variant's `embeds` as they render now (nested included,
|
|
68
|
+
with every version, for the user to peek back) and `publishedWith`, the
|
|
69
|
+
versions it rendered with when you published it.
|
|
70
|
+
- A chain that loops back on itself is refused at publish. An unknown slug
|
|
71
|
+
renders as an empty placeholder, not silently dropped.
|
|
56
72
|
|
|
57
73
|
## Editing one surface
|
|
58
74
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mockpit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A design-decision loop for terminal coding agents — agents publish mocks with states and variants, ask questions and expose knobs; you answer, tune and comment, then send one reply.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent-tools",
|
|
@@ -64,13 +64,8 @@
|
|
|
64
64
|
"start": "npm run build:viewer && node server/index.ts",
|
|
65
65
|
"build:viewer": "vite build",
|
|
66
66
|
"mcp": "node mcp/server.ts",
|
|
67
|
-
"test": "
|
|
68
|
-
"test:node": "node --test 'test/**/*.test.ts'",
|
|
69
|
-
"test:viewer": "vitest run --config vitest.viewer.config.ts",
|
|
67
|
+
"test": "node --test 'test/**/*.test.ts'",
|
|
70
68
|
"test:worker": "npm run build:viewer && node --test test/workerIntegration.integration.ts",
|
|
71
|
-
"coverage": "npm run coverage:node && npm run coverage:viewer",
|
|
72
|
-
"coverage:node": "c8 node --test 'test/**/*.test.ts'",
|
|
73
|
-
"coverage:viewer": "vitest run --coverage --config vitest.viewer.config.ts",
|
|
74
69
|
"test:e2e": "playwright test",
|
|
75
70
|
"bench": "node --expose-gc bench/run.ts",
|
|
76
71
|
"bench:all": "node --expose-gc bench/run.ts --all",
|
|
@@ -101,10 +96,10 @@
|
|
|
101
96
|
"@pierre/diffs": "^1.2.11",
|
|
102
97
|
"ansi_up": "^6.0.6",
|
|
103
98
|
"hono": "^4.13.1",
|
|
104
|
-
"markdown-it": "^
|
|
99
|
+
"markdown-it": "^15.0.3",
|
|
105
100
|
"quickjs-wasi": "3.6.2",
|
|
106
101
|
"shiki": "^4.2.0",
|
|
107
|
-
"zod": "^
|
|
102
|
+
"zod": "^4.6.7"
|
|
108
103
|
},
|
|
109
104
|
"devDependencies": {
|
|
110
105
|
"@changesets/cli": "^3.0.3",
|
|
@@ -112,9 +107,6 @@
|
|
|
112
107
|
"@playwright/test": "^1.60.0",
|
|
113
108
|
"@types/markdown-it": "^14.1.2",
|
|
114
109
|
"@types/node": "^25.9.3",
|
|
115
|
-
"@vitest/coverage-v8": "^4.1.11",
|
|
116
|
-
"c8": "^12.0.0",
|
|
117
|
-
"jsdom": "^27.4.0",
|
|
118
110
|
"lint-staged": "^17.0.7",
|
|
119
111
|
"oxfmt": "^0.54.0",
|
|
120
112
|
"oxlint": "^1.69.0",
|
|
@@ -125,7 +117,6 @@
|
|
|
125
117
|
"vite": "^8.0.16",
|
|
126
118
|
"vite-plugin-singlefile": "^2.3.3",
|
|
127
119
|
"vite-plugin-solid": "^2.11.12",
|
|
128
|
-
"vitest": "^4.1.11",
|
|
129
120
|
"wrangler": "^4.120.0"
|
|
130
121
|
},
|
|
131
122
|
"overrides": {
|
|
@@ -83,7 +83,7 @@ ffmpeg -y -i "$RAW" -vf "fps=30,format=yuv420p" \
|
|
|
83
83
|
`sub`, `cmds`/`cmd` (+ `span.p` for the prompt `$`), `foot`.
|
|
84
84
|
- Interact with the viewer through `page.frameLocator("#app")`. Useful
|
|
85
85
|
selectors (the same ones `e2e/decide-flow.spec.ts` drives):
|
|
86
|
-
`.home-
|
|
86
|
+
`.home-step[data-mock="<slug>"]` (Home's screens), `.frame.on` (the frame on
|
|
87
87
|
stage), `.strip [role="tab"]` (states), `.opt[data-option="<id>"]` (question
|
|
88
88
|
options), `button.send`, `.themebtn` (dark/light).
|
|
89
89
|
- Publish content via the HTTP API while recording: `POST /api/mocks`
|
package/skills/mockpit/SKILL.md
CHANGED
|
@@ -17,18 +17,26 @@ The loop never waits for the user:
|
|
|
17
17
|
|
|
18
18
|
1. `mockpit init` once per repo; read the brief (`mockpit guide`).
|
|
19
19
|
2. `mockpit publish --mock <slug> --state "<user's words>" --variant <v> --html f.html`,
|
|
20
|
-
once per variant; mark parts with `data-part`.
|
|
20
|
+
once per variant; mark parts with `data-part`. Name a state by what the
|
|
21
|
+
user sees ("Home, idle"), never by your process ("Prototype", "v2"). The html is the UI alone:
|
|
22
|
+
say what a variant is in `--note`, never in the design, and name the
|
|
23
|
+
widths it ships at once with `--widths 390,1280`.
|
|
24
|
+
Build screens from components: each reusable piece is its own
|
|
25
|
+
`--kind component` mock, embedded in pages with
|
|
26
|
+
`<mockpit-embed slug="card">`, so one decision on it reaches every page.
|
|
21
27
|
3. A choice is several variants plus one ask that binds them: `mockpit ask`
|
|
22
28
|
with options bound to variants. A variant decides everything it differs on;
|
|
23
29
|
don't re-ask it. Visual options carry a `variant` or knob `set`. One render
|
|
24
|
-
plus a control: `--knobs
|
|
25
|
-
`suggestedAsk`.
|
|
30
|
+
plus a control: `--knobs`; declare knobs for what is worth fine-tuning
|
|
31
|
+
even unasked. When a publish result nudges, send its `suggestedAsk`.
|
|
26
32
|
4. Tell the user in one line where to look, then end your turn. The question
|
|
27
33
|
itself lives in the mock (`ask`), never in chat. The user answers in the
|
|
28
34
|
browser at their own pace. Never poll.
|
|
29
35
|
5. When the user says they answered (or a `mockpit watch` line wakes you), run
|
|
30
36
|
`mockpit feedback`. Every write also returns `feedback`; read it. Empty
|
|
31
|
-
`feedback` with a `pending` draft means they are still answering.
|
|
37
|
+
`feedback` with a `pending` draft means they are still answering. A batch
|
|
38
|
+
with `resolved: true` means they closed the mock unanswered: never re-ask
|
|
39
|
+
its `dismissed` asks.
|
|
32
40
|
6. `mockpit publish` the revision (`--parts name=file` for one part);
|
|
33
41
|
`mockpit export` once a variant is accepted.
|
|
34
42
|
|