@vibes.diy/prompts 14.3.42 → 14.3.44

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.
Files changed (2) hide show
  1. package/llms/backend.md +37 -5
  2. package/package.json +4 -4
package/llms/backend.md CHANGED
@@ -251,9 +251,14 @@ const gh = await ctx.github.fetch("/repos/acme/site/issues", { method: "POST", b
251
251
  `next`. On the last page the property is absent, not undefined — `"next" in
252
252
  page` is `false`.
253
253
  - Both reads are read-gated as the acting identity, through the same gate:
254
- anonymous `fetch` callers are denied, and in `fetch`/`onChange` a database
255
- bound to an access function cannot be read at all (keep those lanes' read
256
- databases unbound). In `scheduled` (admin mode) reads are
254
+ anonymous `fetch` callers are denied, and in `fetch` a database bound to an
255
+ access function cannot be read at all (keep the fetch lane's read databases
256
+ unbound, or declare `config.fetch.unfilteredReads`). In `onChange` a bound
257
+ database reads **filtered to the triggering user's channels** — the same
258
+ per-reader filter the client's own reads use, so the handler sees exactly
259
+ what the user who triggered it could see: neighbouring docs for dedup, rank
260
+ and "don't repeat what's already there" checks, and nothing privileged. In
261
+ `scheduled` (admin mode) reads are
257
262
  **unfiltered** — access-fn-bound databases return every doc, across all users
258
263
  and channels. Made for `scheduled` sweeps: read, decide, then `put`/`delete`.
259
264
  - The one exception to that last sentence is the declared opt-in above,
@@ -880,6 +885,32 @@ Two rules keep change-reactions sane:
880
885
  same-database ping-pong is still wasted work. Different db + dbName guard
881
886
  makes loops structurally impossible.
882
887
 
888
+ ### `onChange` reads what the triggering user could read
889
+
890
+ A reaction usually needs the set its write joins — the siblings, the existing
891
+ keys, what's already there. `ctx.db.query` and `ctx.db.get` on a bound
892
+ database return exactly the docs in the triggering user's channels, through
893
+ the same per-reader filter the client's own reads use. Nothing privileged
894
+ ever comes back: a doc the triggerer couldn't open stays invisible, and reads
895
+ page like any other query (walk `next` to exhaustion).
896
+
897
+ ```js
898
+ export async function onChange(event, ctx) {
899
+ if (event.dbName !== "links" || event.deleted) return;
900
+ // What did sibling drafts already say about this link? Only docs the
901
+ // triggering user could read come back — a private sibling stays hidden.
902
+ // Walk every page to exhaustion: a fully-filtered page still carries `next`,
903
+ // so stopping on an empty page would miss a sibling on a later one.
904
+ let after = null;
905
+ do {
906
+ const page = await ctx.db.query({ db: "drafts", field: "linkId", key: event.doc.linkId, limit: 100, after });
907
+ if (page.some((d) => d.angle === event.doc.angle)) return; // already covered
908
+ after = page.next;
909
+ } while (after);
910
+ await ctx.db.put({ _id: "draft-" + event.docId, linkId: event.doc.linkId, angle: event.doc.angle }, { db: "drafts" });
911
+ }
912
+ ```
913
+
883
914
  ### Jobs that finish even when a run crashes
884
915
 
885
916
  **A job that survives a crash carries its status, its claim and its lease on the document.**
@@ -903,8 +934,9 @@ sweep's `query` row), then `put` the next status with `ifRev: doc._rev`. A
903
934
  `attempts + 1`.
904
935
  - The finish carries the same `claimId`, and `access.js` refuses a `done`
905
936
  whose `claimId` differs from `oldDoc.claimId`. A slow run's lease can be
906
- taken back and the job claimed again while it works, and `onChange` cannot
907
- read the job back, so the token is how the finish knows it still owns it.
937
+ taken back and the job claimed again while it works; the second claim's
938
+ fresh `claimId` is what makes the first run's finish refuse instead of
939
+ overwrite.
908
940
  - The sweep releases an expired lease with `ifRev: job._rev` from its query,
909
941
  so it never overwrites a job that finished between the read and the write.
910
942
  - A lost claim returns rather than throws: a redelivered event carries the doc
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibes.diy/prompts",
3
- "version": "14.3.42",
3
+ "version": "14.3.44",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -37,9 +37,9 @@
37
37
  "license": "Apache-2.0",
38
38
  "dependencies": {
39
39
  "@adviser/cement": "~0.5.34",
40
- "@vibes.diy/call-ai-v2": "14.3.42",
41
- "@vibes.diy/identity": "14.3.42",
42
- "@vibes.diy/use-vibes-types": "14.3.42",
40
+ "@vibes.diy/call-ai-v2": "14.3.44",
41
+ "@vibes.diy/identity": "14.3.44",
42
+ "@vibes.diy/use-vibes-types": "14.3.44",
43
43
  "arktype": "~2.2.3",
44
44
  "json-schema-faker": "~0.6.3"
45
45
  },