softr-vibe-coding 2.15.0 → 2.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/SKILL.md +1 -1
- package/package.json +1 -1
- package/references/softr-mcp.md +40 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,10 @@ All notable changes to this skill are documented here. Versions follow [Semantic
|
|
|
4
4
|
|
|
5
5
|
Entries from 1.3.1 onward are generated automatically from git commit subjects between version bumps (see `.github/workflows/publish.yml`). Entries before 1.3.1 were backfilled by hand from the existing commit history.
|
|
6
6
|
|
|
7
|
+
## [2.15.1] - 2026-10-08
|
|
8
|
+
- Release 2.15.1
|
|
9
|
+
- softr-mcp: unicode escapes come back decoded on push
|
|
10
|
+
|
|
7
11
|
## [2.15.0] - 2026-10-07
|
|
8
12
|
- Release 2.15.0
|
|
9
13
|
- Add the brand date picker reference
|
package/SKILL.md
CHANGED
|
@@ -102,7 +102,7 @@ You generate complete, production-ready Softr Vibe Coding blocks as TypeScript R
|
|
|
102
102
|
- Static block: no hardcoded user-visible copy — every string/image/link is an editable setting (see [references/editable-settings.md](references/editable-settings.md#granularity-doctrine-settings-first-static-blocks))
|
|
103
103
|
- Array-setting rows keyed by **index**, never by a builder-editable field value
|
|
104
104
|
- Media settings that may start empty (`src: ""`) gated with a conditional render or placeholder — never an unconditional `<img src={setting.src}>`
|
|
105
|
-
- **Deploying through the MCP:** `errors: null` on a push is not proof — compare the push result's `sourceSha256` with `shasum -a 256` of the file you sent, every byte counted, trailing newline included (Softr stores exactly
|
|
105
|
+
- **Deploying through the MCP:** `errors: null` on a push is not proof — compare the push result's `sourceSha256` with `shasum -a 256` of the file you sent, every byte counted, trailing newline included (Softr stores exactly the text that reaches it; the one-byte drift we once blamed on it was a chunked read on our side). No `\uXXXX` escapes in pushed source: they arrive decoded to the characters and the hashes differ, so write the characters themselves (with a comment saying why) or build them from code points (`String.fromCharCode(0x300)`); lone surrogates are the exception ([why](references/softr-mcp.md#unicode-escapes-come-back-decoded)). Prove deployed == disk *before* editing the same way, with `vibe_coding_block_get_code` and `includeCode: false`, so a Studio-side change is never overwritten. Fetch the full `sourceCode` only when a digest is missing or the hashes differ. Protocol in [references/softr-mcp.md → Verifying a push](references/softr-mcp.md#verifying-a-push--the-deployed-source-is-the-only-proof)
|
|
106
106
|
- **Then check it in a browser.** Once the push checks pass, check rendering and behaviour in a fresh preview with saves blocked, per [references/browser-checks.md](references/browser-checks.md)
|
|
107
107
|
|
|
108
108
|
## What to Clarify
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "softr-vibe-coding",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.1",
|
|
4
4
|
"description": "Claude Code skill for generating production-ready Softr Vibe Coding blocks (JSX). Installs into ~/.claude/skills/ and auto-updates on each Claude Code session.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"softr-vibe-coding": "bin/cli.js"
|
package/references/softr-mcp.md
CHANGED
|
@@ -280,7 +280,7 @@ reports neither field. With `includeCode: false`, `vibe_coding_block_get_code` r
|
|
|
280
280
|
`sourceCode: null`. Verified live 2026-10-01: a deployed block's `sourceSha256` equalled the SHA-256
|
|
281
281
|
of the exact source last pushed to it (taken from the push call), and the read came back at about
|
|
282
282
|
1 KB for a 15 KB block. The same check showed that block's local mirror had picked up three comment
|
|
283
|
-
edits since that push, which is exactly what step 1 below exists to catch. (The digest on push results
|
|
283
|
+
edits since that push, which is exactly what step 1 below exists to catch. (The digest on push results was first known from Softr's release notes; our own pushes have returned it since at least 2026-10-08.)
|
|
284
284
|
Right after that release our client's copy of the tool definition did not declare `includeCode`, so
|
|
285
285
|
the argument went out as the string `"false"` and the server still honoured it. Whatever the loaded
|
|
286
286
|
definition says, check that `sourceCode` came back `null`.
|
|
@@ -308,10 +308,12 @@ definition says, check that `sourceCode` came back `null`.
|
|
|
308
308
|
|
|
309
309
|
Matching hashes prove what Softr stored, not how the block behaves: for that, check it in a fresh preview with saves blocked, per [browser-checks.md](browser-checks.md).
|
|
310
310
|
|
|
311
|
-
**Hash the exact bytes, trailing newline included.** Softr stores exactly
|
|
311
|
+
**Hash the exact bytes, trailing newline included.** Softr stores exactly the text that reaches it: across
|
|
312
312
|
112 push→fetch pairs between 2026-09-09 and 2026-09-30 the fetched
|
|
313
313
|
`sourceCode` was byte- and MD5-identical to the text sent, including two pushes sent *without* a
|
|
314
|
-
final newline and stored without one.
|
|
314
|
+
final newline and stored without one. (One thing does not reach Softr as written: a `\uXXXX`
|
|
315
|
+
escape in the source arrives decoded, see [below](#unicode-escapes-come-back-decoded).)
|
|
316
|
+
The "deployed block is one byte shorter" we chased on
|
|
315
317
|
2026-09-09 was our own read: an agent that reads a large file in chunks can drop the final
|
|
316
318
|
newline (or a blank line at a chunk boundary) before transmission. A comparison that normalises
|
|
317
319
|
the trailing newline hides exactly that class of error — so do not normalise anything; a mismatch
|
|
@@ -356,6 +358,41 @@ from the docs):
|
|
|
356
358
|
(`application_get`) with the version's `createdAt` (`vibe_coding_block_list_versions`): on
|
|
357
359
|
2026-09-01 a block we believed staged went live with a publish 28 minutes after it was saved.
|
|
358
360
|
|
|
361
|
+
#### Unicode escapes come back decoded
|
|
362
|
+
|
|
363
|
+
Verified 2026-10-08 on a large dashboard block pushed in stages with `vibe_coding_block_update_code`
|
|
364
|
+
and `vibe_coding_block_update_code_search_replace`: exactly the calls whose text held a JavaScript
|
|
365
|
+
`\uXXXX` escape came back with a `sourceSha256` that differed from the hash of the planned text. The
|
|
366
|
+
block's accent-folding regex, `/[\u0300-\u036f]/g`, was stored with both escapes replaced by the
|
|
367
|
+
characters themselves, two combining marks sitting raw between the brackets. `\d`, `\D` and `\s` in
|
|
368
|
+
the same block arrived as written.
|
|
369
|
+
|
|
370
|
+
The decoding happens somewhere between the tool call and storage (the client's JSON handling of
|
|
371
|
+
the argument, or the server), not in Softr's compiler: the stored source text itself changed. It
|
|
372
|
+
looks like the [encoding trap](#which-edit-tool-full-replace-vs-targeted-search-replace) above,
|
|
373
|
+
reaching a backslash-u that was meant to stay in the source. The exception is a lone surrogate:
|
|
374
|
+
`\udc00-\udfff` in the same regexes has no character form, and those pushes stored it unchanged.
|
|
375
|
+
(The `\u{…}` form is untested; treat it the same.)
|
|
376
|
+
|
|
377
|
+
**So: no `\uXXXX` in pushed source, lone surrogates aside.** Find them before a push with
|
|
378
|
+
`grep -n '\\u[0-9a-fA-F]\{4\}' <file>`, then either:
|
|
379
|
+
|
|
380
|
+
- **Write the characters themselves**, with a comment saying why, since combining marks and other
|
|
381
|
+
invisible characters cannot be read in an editor. Spell "backslash-u" out in that comment so it
|
|
382
|
+
holds no escape either. Check first that the character means the same raw in that spot: a range
|
|
383
|
+
of combining marks in a character class does (the block's regexes, escaped and raw, matched the
|
|
384
|
+
same set across all 65,536 BMP code points), but written raw, a `/` ends a regex literal, a `]`
|
|
385
|
+
closes a class, a backslash or quote changes the token, and U+2028/U+2029 are line terminators a
|
|
386
|
+
regex literal may not contain.
|
|
387
|
+
- **Build it from code points** where a raw character is unwanted or unsafe:
|
|
388
|
+
`new RegExp("[" + String.fromCharCode(0x300) + "-" + String.fromCharCode(0x36f) + "]", "g")`,
|
|
389
|
+
created once at module scope. No backslash-u reaches the tool, so there is nothing to decode.
|
|
390
|
+
Strings likewise: `String.fromCharCode(0x2014)`, not `"\u2014"`.
|
|
391
|
+
|
|
392
|
+
If a push has already stored the decoded form, applying the same replacement to the mirror brings
|
|
393
|
+
the hashes back together; confirm the raw characters behave the same (first bullet) before calling
|
|
394
|
+
it done.
|
|
395
|
+
|
|
359
396
|
### The array-argument rejection, and why it is a security issue
|
|
360
397
|
|
|
361
398
|
**Several workspace-server tools take an array argument, and a call that sends it as a JSON *string*
|