Commit 259d294
authored
Skills: full detail page with diff-confirmed saves (#175)
* Add tests for the skill detail page and diff flow
Covers the line-diff utility (edits, insertions, removals, line
numbering, empty sides), the skill detail page's diff-confirmed save
(Save… opens the review with the diff and writes nothing, Keep editing
keeps the edit, Confirm & save publishes), the version list with compare
and restore, and the new read of a skill at one commit. The roster and
route suites move to the roster-only contract: /skills lists, and a
single skill lives at its own route.
Claude-Session: https://claude.ai/code/session_01Shhie5zM8L54bLHq5gFQti
* Skills: full detail page with diff-confirmed saves
/skills/<name> is now a real page instead of a placeholder: the skill's
content editor, its version list, and a diff view — no new storage, since
a skill's git history already is its version store.
A save is never silent. "Save…" in the top bar opens a review step
showing the diff between the published version and the editor buffer,
with "Confirm & save" and "Keep editing"; the commit happens only on
confirm. The same renderer draws the comparison between any earlier
version and the current one, read through a new
GET /:name/versions/:commitSha that reads a skill at one commit without
writing anything.
The line diff itself is @corbits/text-diff, a dependency-free
longest-common-subsequence script so an edit in the middle of a document
reads as that one edit.
The roster keeps only what a roster does: the inline skill panel and the
create dialog's edit mode are gone, so there is one skill editor rather
than two.
Claude-Session: https://claude.ai/code/session_01Shhie5zM8L54bLHq5gFQti
* Add tests for bounded diffs and the save head precondition
Pins the diff's refusal to allocate for a wholly rewritten large document
and its linear cost when the identical head and tail are trimmed, the
collapse of long unchanged runs, and newline normalization. On the page:
a save that lost the race is refused, re-diffed against the version that
won, and never buries it; side-action failures stay local and never
discard a dirty draft; a missing skill says so; and CRLF in the buffer
neither reads as a change nor changes the bytes written.
Claude-Session: https://claude.ai/code/session_01Shhie5zM8L54bLHq5gFQti
* Skills: bound the diff and refuse a save that lost the race
Two defects in the review flow, both fixed at the root.
The diff allocated a dense longest-common-subsequence table over the whole
document, so a 12k-line skill cost gigabytes. It now normalizes newlines,
trims the identical head and tail before building anything, refuses the
quadratic walk past a hard cap (1500 changed lines per side, 400k
characters) with an honest "too large to show line by line" summary, and
collapses long unchanged runs to a single row. The table itself is
Int32Array-backed, so the capped worst case is about 9MB. The script is
computed once and both the rows and the change summary are read off that
one result.
The confirmed diff was computed against the version loaded when the page
opened, so a save could silently bury whoever published in between. A save
now carries the version it was reviewed against; PUT /:name refuses a
stale one with a 409, and the page re-reads, keeps the edit, and re-opens
the review against what is actually published, saying why.
Also: the buffer is newline-normalized so the bytes reviewed are the bytes
written, and the description is saved exactly as reviewed rather than
trimmed on the way out; side actions (visibility, restore, compare) report
failures next to themselves instead of replacing the page, and never reset
an unsaved edit; failures read through describeApiError rather than
rendering a server message, with a distinct "no skill named …" state for a
404; the new version read validates its id at the route and 404s a commit
that isn't in the skill's history rather than dating it to 1970; and the
versions list stacks at 1100px, as DESIGN.md specifies.
Claude-Session: https://claude.ai/code/session_01Shhie5zM8L54bLHq5gFQti1 parent d0b3ab3 commit 259d294
22 files changed
Lines changed: 2107 additions & 530 deletions
File tree
- apps/web
- src
- pages
- test
- packages
- icons/src
- skills
- src
- test
- text-diff
- src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
19 | | - | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
20 | 19 | | |
21 | 20 | | |
22 | 21 | | |
| |||
63 | 62 | | |
64 | 63 | | |
65 | 64 | | |
66 | | - | |
| 65 | + | |
| 66 | + | |
67 | 67 | | |
68 | 68 | | |
69 | 69 | | |
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | 85 | | |
97 | 86 | | |
98 | 87 | | |
99 | | - | |
100 | | - | |
101 | | - | |
102 | | - | |
103 | | - | |
104 | | - | |
| 88 | + | |
| 89 | + | |
105 | 90 | | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | 91 | | |
113 | 92 | | |
114 | 93 | | |
| |||
128 | 107 | | |
129 | 108 | | |
130 | 109 | | |
131 | | - | |
132 | | - | |
133 | 110 | | |
134 | 111 | | |
135 | 112 | | |
136 | | - | |
137 | | - | |
138 | | - | |
| 113 | + | |
| 114 | + | |
139 | 115 | | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | 116 | | |
144 | | - | |
145 | | - | |
| 117 | + | |
146 | 118 | | |
147 | 119 | | |
148 | 120 | | |
149 | 121 | | |
150 | 122 | | |
151 | | - | |
| 123 | + | |
152 | 124 | | |
153 | 125 | | |
154 | 126 | | |
155 | 127 | | |
156 | 128 | | |
157 | | - | |
158 | | - | |
| 129 | + | |
159 | 130 | | |
160 | 131 | | |
161 | 132 | | |
| |||
167 | 138 | | |
168 | 139 | | |
169 | 140 | | |
170 | | - | |
171 | | - | |
| 141 | + | |
172 | 142 | | |
173 | 143 | | |
174 | 144 | | |
| |||
195 | 165 | | |
196 | 166 | | |
197 | 167 | | |
198 | | - | |
199 | | - | |
200 | | - | |
| 168 | + | |
201 | 169 | | |
202 | | - | |
203 | | - | |
204 | | - | |
| 170 | + | |
| 171 | + | |
205 | 172 | | |
206 | 173 | | |
207 | 174 | | |
| |||
221 | 188 | | |
222 | 189 | | |
223 | 190 | | |
224 | | - | |
| 191 | + | |
225 | 192 | | |
226 | 193 | | |
227 | | - | |
| 194 | + | |
228 | 195 | | |
229 | 196 | | |
230 | 197 | | |
| |||
238 | 205 | | |
239 | 206 | | |
240 | 207 | | |
241 | | - | |
| 208 | + | |
242 | 209 | | |
243 | | - | |
| 210 | + | |
244 | 211 | | |
245 | 212 | | |
246 | 213 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
| 7 | + | |
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
| 12 | + | |
16 | 13 | | |
17 | 14 | | |
18 | 15 | | |
| |||
49 | 46 | | |
50 | 47 | | |
51 | 48 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
60 | | - | |
61 | | - | |
62 | | - | |
63 | | - | |
64 | 49 | | |
65 | 50 | | |
66 | 51 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
0 commit comments