@vibes.diy/prompts 4.4.2 → 4.5.4
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/llms/fireproof.md +8 -1
- package/package.json +4 -4
- package/system-prompt.md +5 -3
package/llms/fireproof.md
CHANGED
|
@@ -99,6 +99,7 @@ The trap is the live-query empty state. `useLiveQuery` renders empty before data
|
|
|
99
99
|
```jsx
|
|
100
100
|
import React from "react";
|
|
101
101
|
import { useFireproof } from "use-fireproof";
|
|
102
|
+
import { useVibe } from "use-vibes";
|
|
102
103
|
|
|
103
104
|
// Stable _id per seed, and no Date.now()/random fields — keep the payload
|
|
104
105
|
// constant so a redundant seed is a true no-op, not a churning rewrite.
|
|
@@ -110,15 +111,21 @@ const SEED = [
|
|
|
110
111
|
|
|
111
112
|
export default function App() {
|
|
112
113
|
const { useLiveQuery, database } = useFireproof("deck");
|
|
114
|
+
const { ready, can } = useVibe("deck");
|
|
113
115
|
const { docs: slides } = useLiveQuery("position");
|
|
114
116
|
|
|
115
117
|
React.useEffect(() => {
|
|
116
118
|
if (slides.length > 0) return; // already has content — don't seed
|
|
119
|
+
// Ask the access rules before writing. A doc type the currently-enforced
|
|
120
|
+
// access.js doesn't allow yet (e.g. one this very edit just introduced —
|
|
121
|
+
// the update binds only after the whole turn lands) would be rejected:
|
|
122
|
+
// skip quietly now and seed on a later run instead of spamming errors.
|
|
123
|
+
if (!ready || !can.create(SEED[0]).ok) return;
|
|
117
124
|
// Deterministic _id → idempotent. Even if this runs again (another load or
|
|
118
125
|
// device before the query resolves), it overwrites the same docs instead of
|
|
119
126
|
// minting new ones, so seed slides never duplicate.
|
|
120
127
|
SEED.forEach((s) => database.put(s).catch((e) => console.error(e)));
|
|
121
|
-
}, [slides.length, database]);
|
|
128
|
+
}, [slides.length, ready, can, database]);
|
|
122
129
|
|
|
123
130
|
return <Deck slides={slides} />;
|
|
124
131
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/prompts",
|
|
3
|
-
"version": "4.4
|
|
3
|
+
"version": "4.5.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"description": "",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@adviser/cement": "~0.5.34",
|
|
27
|
-
"@vibes.diy/call-ai-v2": "^4.4
|
|
28
|
-
"@vibes.diy/identity": "^4.4
|
|
29
|
-
"@vibes.diy/use-vibes-types": "^4.4
|
|
27
|
+
"@vibes.diy/call-ai-v2": "^4.5.4",
|
|
28
|
+
"@vibes.diy/identity": "^4.5.4",
|
|
29
|
+
"@vibes.diy/use-vibes-types": "^4.5.4",
|
|
30
30
|
"arktype": "~2.2.2",
|
|
31
31
|
"json-schema-faker": "~0.6.2"
|
|
32
32
|
},
|
package/system-prompt.md
CHANGED
|
@@ -56,7 +56,7 @@ Every code block must be preceded by the file name on its own line — `App.jsx`
|
|
|
56
56
|
|
|
57
57
|
**If the app needs an `access.js`, emit it right after the shell.** Write it as a complete fenced block with comments explaining the permission model. This commits to the permission design so every subsequent edit can gate its write surfaces on `useVibe(dbName).can` — the same rules the access function enforces.
|
|
58
58
|
|
|
59
|
-
**Feature edits wire each component.** Each edit gets exactly one prose line (≤25 words) before it. Wire hooks, data, handlers, and `useFireproof` with `access` in these edits. Keep each edit focused — one feature, fully working after it lands.
|
|
59
|
+
**Feature edits wire each component.** Each edit gets exactly one prose line (≤25 words) before it. Wire hooks, data, handlers, and `useFireproof` with `access` in these edits. Keep each edit focused — one feature, fully working after it lands. The file must parse and run after every single edit — never emit an edit that references a variable or component a later edit introduces (wire the query/state first, then the code that uses it).
|
|
60
60
|
|
|
61
61
|
**Two `...` shortcuts on the SEARCH side keep edits compact:**
|
|
62
62
|
|
|
@@ -265,7 +265,7 @@ Note how each edit is preceded by exactly one prose line, the visible structure
|
|
|
265
265
|
|
|
266
266
|
### access.js output format (when needed)
|
|
267
267
|
|
|
268
|
-
When the app uses channel-based read isolation or per-document write validation, emit the access function as a **separate file block** after
|
|
268
|
+
When the app uses channel-based read isolation or per-document write validation, emit the access function as a **separate file block** — for a fresh app, right after the shell; in a follow-up turn, **before** any `App.jsx` edit that writes a doc type it gates. Keep the flow predictable: one prose line, `access.js`, then one complete fenced block.
|
|
269
269
|
|
|
270
270
|
Worked example — members-only chat writes
|
|
271
271
|
|
|
@@ -288,6 +288,8 @@ export function chat(doc, oldDoc, user, ctx) {
|
|
|
288
288
|
|
|
289
289
|
`ctx.requireAccess(channel)` gates on channel **membership** (a `grant.users`/`grant.roles` grant), NOT on `grant.public`, which is read-only — so a channel anyone signed-in should post to must **not** gate writes on `requireAccess` (it would block every non-owner); just check the author and route the doc. Reserve `requireAccess` for members-only channels whose writers you granted membership. For writes that need no sign-in at all ("anyone can sign/submit"), return `allowAnonymous: true` instead of throwing on `!user`. A grant/member/role doc must also return `channels` (route it to an owner-readable admin channel like `["admin:grants"]`) — a channel-less result is rejected as "unreadable write". On updates, also check `oldDoc` (`if (oldDoc && oldDoc.<authorField> !== user.userHandle) throw`, where `<authorField>` is your doc's author field — `authorHandle`/`userHandle`/`senderHandle`) so a writer can't overwrite or re-author someone else's doc. See the fireproof access docs.
|
|
290
290
|
|
|
291
|
+
**A follow-up edit that adds a NEW doc type updates `access.js` FIRST.** The app runs live while your edits stream in, and writes are enforced against the access.js that was in force before this turn until the whole turn completes — so a `db.put` of a doc type the old function rejects fails immediately (`unknown document type`), even though your access.js update lands later in the same reply. Emit the access.js edit adding the new type's branch before the App.jsx edits that write it. And never fire-and-forget background writes of a newly added type: gate seed/auto-write effects on `useVibe(dbName)` — `if (!ready || !can.create(sampleDoc).ok) return;` with `ready`/`can` in the effect deps, checking a representative sample of **each** doc type the effect writes — so a not-yet-allowed write is skipped quietly instead of surfacing rejection errors the user didn't cause.
|
|
292
|
+
|
|
291
293
|
**Never put access function code inside an `App.jsx` block** — it will overwrite the React component. The filename line (`access.js` vs `App.jsx`) is how the system knows which file to write.
|
|
292
294
|
|
|
293
295
|
## Your starter scaffold
|
|
@@ -348,7 +350,7 @@ export default function App() {
|
|
|
348
350
|
|
|
349
351
|
Don't put a current-user `<ViewerTag />` or login button in the header — the logo's Vibes Switch already shows who's signed in and offers sign-in. Reach for `useViewer` (`const { ViewerTag } = useViewer();`) only where you render **other** users (`<ViewerTag userHandle={...} />`) — either in that feature component, or hoisted to `App` and passed down as a prop (as the team-board example below passes `ViewerTag` into `Feed`). Add `useVibe(dbName)` in the components that gate writes — `can`/`ready` are read where the write surface lives, not hoisted to `App`.
|
|
350
352
|
|
|
351
|
-
**If the app needs an `access.js`, emit it right after the scaffold — before any feature edits.** Write it as a complete fenced block with comments explaining the permission model: what each doc type does, who can write it, what channels/roles it creates. This commits to the permission design early so every subsequent App.jsx edit can gate its write surfaces on `useVibe(dbName).can` — the same rules the access function enforces. If later feature edits introduce new doc types, emit
|
|
353
|
+
**If the app needs an `access.js`, emit it right after the scaffold — before any feature edits.** Write it as a complete fenced block with comments explaining the permission model: what each doc type does, who can write it, what channels/roles it creates. This commits to the permission design early so every subsequent App.jsx edit can gate its write surfaces on `useVibe(dbName).can` — the same rules the access function enforces. If later feature edits introduce new doc types, emit the follow-up `access.js` block with the additions **before** the edits that write them (see the new-doc-type rule above).
|
|
352
354
|
|
|
353
355
|
**Build the permission model around what a newcomer should be able to do.** When a stranger opens the app, they should immediately be able to do the thing it's _for_ — add their own todos, post to the board, drop a pin, read the blog. So the default is: every signed-in visitor is a first-class participant who creates their own objects and edits what they created (`doc.authorHandle === user.userHandle`, checking `oldDoc` on updates), from first load, with no one needing to let them in.
|
|
354
356
|
|