softr-vibe-coding 2.1.1 → 2.1.2

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 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.1.2] - 2026-08-26
8
+ - Document four linked-record write traps verified live 2026-08-26
9
+ - Fail the build when main moves ahead of npm
10
+
7
11
  ## [2.1.1] - 2026-08-26
8
12
  - Release 2.1.1
9
13
  - Document external-URL attachment ingestion (copy, not link)
@@ -291,6 +291,43 @@ parentAccount: "RECORD_ID_1"
291
291
  string-array shape is the verified current form on Softr Database; if a linked-record write
292
292
  fails on an Airtable-backed block, try the `[{ id }]` object shape before deeper debugging.
293
293
 
294
+ ### Linked-record write traps (verified live 2026-08-26)
295
+
296
+ Four Softr Database behaviors proven by direct experiment on a live production build — a
297
+ 49-link backfill across a self-referencing parent/child pair. They bite hardest in backfills
298
+ and schema work, and **none of them raises an error**.
299
+
300
+ 1. **A single-valued link pair is enforced ON WRITE — and it clobbers silently.** With
301
+ `allowMultipleEntries: false` on the inverse side, writing child N's link to a parent
302
+ silently unlinks child N−1: no error, the earlier link just vanishes (16 of 49 backfill
303
+ links disappeared this way before it was caught). Pre-existing multi links DO survive a
304
+ flip from multi to single, which is why a scratch-table spike that flips an
305
+ already-linked pair reports the setting as "cosmetic only" and misleads — the
306
+ enforcement only fires on the next write. If one side must hold many links, both sides
307
+ must allow multiple entries; enforce any one-parent rule in the UI, not the schema.
308
+
309
+ 2. **`allowMultipleEntries` is a TOP-LEVEL field property, not part of `options`.** The
310
+ workspace MCP's `update_field` silently ignores it when nested inside `options` — the
311
+ call succeeds and changes nothing. A Tables API `PUT /fields/{id}` with the property at
312
+ top level works.
313
+
314
+ 3. **A Tables API field PUT that omits `options.inverseLinkFieldId` SEVERS the inverse
315
+ pairing** — it comes back `null` and the two sides stop mirroring each other. Always
316
+ echo `inverseLinkFieldId` inside the `options` you send, and re-read BOTH sides after
317
+ any linked-record field PUT to confirm the pairing survived.
318
+
319
+ 4. **An empty multi-entry link reads back as `[]`, which is truthy in JS.** Any
320
+ "already linked — skip" guard written as `if (value)` matches every record after a
321
+ single→multi flip, so a resumable backfill re-processes nothing or skips everything.
322
+ Test presence explicitly:
323
+
324
+ ```jsx
325
+ const hasLink = Array.isArray(v) ? v.length > 0 : !!v;
326
+ ```
327
+
328
+ (The populated read shapes are in [fields.md](fields.md); this is the empty case, and
329
+ it becomes a write trap the moment a backfill uses it as a skip condition.)
330
+
294
331
  ## Writing to Field Types
295
332
 
296
333
  Different Softr field types accept different value shapes in mutation payloads. The shape returned when you READ a field is often different from the shape you must SEND when you WRITE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "softr-vibe-coding",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
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"
@@ -122,6 +122,13 @@ Known limits and behaviors (per official docs):
122
122
  `{ filename, url }` on an ATTACHMENT field with any publicly reachable URL; Softr fetches it, stores its
123
123
  own copy and generates thumbnails, so backfilling images from another system is one write per record
124
124
  with no upload step. Verified 2026-08-26 — see [../datasources/writing.md](../datasources/writing.md#attachment).
125
+ - **`update_field` silently ignores `allowMultipleEntries` nested inside `options`** — it is a TOP-LEVEL
126
+ field property; the call succeeds and changes nothing (verified 2026-08-26). To flip a LINKED_RECORD
127
+ field between single and multi, `PUT` it via the Tables API with `allowMultipleEntries` at top level —
128
+ and always echo `options.inverseLinkFieldId` in that PUT, because omitting it severs the inverse
129
+ pairing. Full write-up, including the silent on-write clobbering of single-valued link pairs and the
130
+ truthy-`[]` empty-link read shape:
131
+ [../datasources/writing.md](../datasources/writing.md#linked-record-write-traps-verified-live-2026-08-26).
125
132
  - Limits: 100 records per `create_records` call, 200 records per read (silently capped, not an error), 2 group-by fields in `aggregate_data`. For big tables prefer a filter or aggregate over paging.
126
133
 
127
134
  Typical Vibe Coding uses: "list every field on `Wigs` with id, name, type, and dropdown options", "what's the option id for `Payment status` = 'Partially paid'?", "show 3 sample records so we know value shapes", "verify the field id in my `q.select()` exists". This eliminates the field-id-typo / wrong-option-uuid class of bugs entirely.