@panaversity/ksor 0.0.52 → 0.0.54

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
@@ -1,5 +1,167 @@
1
1
  # @panaversity/ksor
2
2
 
3
+ ## 0.0.54
4
+
5
+ ### Patch Changes
6
+
7
+ - 3f55e91: `ksor calibrate` names the free-tier path when a quota refuses it, and the
8
+ calibration text model moves to `gemini-3.7-flash`.
9
+
10
+ Walked on a real free-tier key: embedding is free of charge and a first corpus
11
+ embeds fine (23 chunks, 0 failed), but the DEFAULT calibration door writes one
12
+ probe question per sampled passage with an LLM — and the free tier allows five
13
+ generations a minute. So the documented way to turn on the product's headline
14
+ feature failed, surfacing the vendor's sentence and nothing else.
15
+
16
+ Two quotas reach that code and they need opposite answers: the generation cap is
17
+ a wall no wait clears (the remedy is `--queries-file`, the zero-LLM door), and
18
+ the embedding cap is a per-minute window (the remedy is to wait, and the usual
19
+ cause is an ingest immediately before). Both are now named, with why. A 429 this
20
+ does not recognise is re-thrown untouched — an invented remedy is worse than the
21
+ vendor's own message.
22
+
23
+ `docs/ingesting.md` documents the zero-LLM door where the reader meets the
24
+ command, including how to choose the questions: the floor is set by the weakest
25
+ one, so a vague question drags it down and a question the record cannot answer
26
+ invalidates the measurement.
27
+
28
+ The text model moves `gemini-2.5-flash` → `gemini-3.7-flash`. Cheap, unlike the
29
+ embedding model: it only writes probe questions, so nothing stored is
30
+ re-computed and no floor is invalidated — and the door is recorded beside every
31
+ number, which is what stops two measurements being compared as one experiment.
32
+
33
+ **And calibration now embeds on the patient retry.** It used the READ plane's
34
+ door, which never retries a 429 — correct for a live search, which should
35
+ degrade to keyword-only in under a second rather than stall a reader behind
36
+ backoff, and wrong for a measurement nobody is waiting on. So a free-tier key
37
+ that rate-limited mid-run refused the whole calibration. The intent stays
38
+ `query` (a floor must be measured through the label the door searches with);
39
+ only the retry policy moves, to the one `isRetryable`'s own comment describes
40
+ for batch work. Calibration's text generation already took that path, so this
41
+ was the two halves of one act disagreeing.
42
+
43
+ - dd6371b: Two things: a false claim removed from a shipped page, and the scaffold gains
44
+ `.mcp.json`.
45
+
46
+ **The false claim.** `docs/deploying.md` told adopters "The MCP surface already
47
+ applies the audience scope **per request**", under the heading of the very
48
+ requirement it does not meet. It does not: `content-gateway/src/compose.ts`
49
+ reads `KSOR_AUDIENCE` from the environment once at boot into a per-process
50
+ viewer, and the request path never touches it — `docs/authorization.md` says so
51
+ plainly ("Any caller holding a valid token gets the whole record") and
52
+ `specs/ksor/serve/spec.md` names per-request visibility filtering as out of
53
+ scope. A reader who believed the page would point every caller at one door and
54
+ serve them the restricted half. The page now says what the door does — one
55
+ viewer per door, so one process per audience — and separates the audit it does
56
+ give (a `retrieval_log` row naming the verified caller) from the authorization
57
+ it does not. A docs-truth assertion now fails on the claim itself, not merely on
58
+ a command that no longer exists.
59
+
60
+ **`.mcp.json`.** The scaffold's closed root set gains one member: the MCP
61
+ servers a coding agent may reach from the project. It ships with Neon's, which
62
+ turns the step the tool could never do for an adopter — provision a Postgres,
63
+ enable pgvector, produce a connection string — into four real tool calls
64
+ (`create_project`, `run_sql`, `create_branch`, `get_connection_string`) and one
65
+ sentence to the agent. The scaffold's README and AGENTS.md carry that sentence,
66
+ and both now say plainly which step no agent can do at any price: the embedding
67
+ API key, which no vendor mints over a protocol. Committed rather than ignored,
68
+ because both entries authenticate interactively and the file carries no secret —
69
+ stated, because pasting an API key into it would change that.
70
+
71
+ - eebd777: OpenAI joins Gemini behind the embedding seam, and the wiring stops naming one
72
+ vendor (issue #25).
73
+
74
+ The seam was already vendor-neutral in shape — `EmbeddingProvider`, the
75
+ framework's normalization and degeneracy checks, and an embedding space
76
+ identified by `modelId` + column width and never by the vendor. What was
77
+ Gemini-bound was the WIRING: `GEMINI_API_KEY` was spelled into three composition
78
+ roots, so a second provider could not obtain a key even though the registry
79
+ would happily build it. Each registry row now names its own key variable, and
80
+ the roots ask, exactly as `instance.md` names the DSN variable rather than
81
+ hardcoding it.
82
+
83
+ `provider: openai` with `model: text-embedding-3-small` and `dim: 1536` reads
84
+ `OPENAI_API_KEY`. Over `fetch`, no SDK — the same call decision 12's 2026-08-22
85
+ revision made for Gemini, and for the same reason.
86
+
87
+ Two things a live call surfaced that a stub would not. Response items carry
88
+ their own `index` and the vendor does not promise array order, so they are
89
+ sorted before the framework pairs them positionally — a shuffled response is the
90
+ same count, the same width and all finite, so every downstream check passes
91
+ while every passage carries another's vector. And an exhausted balance arrives
92
+ as **429**, the same status as a rate limit: it is now read from the vendor's
93
+ `error.type` and never retried, because five exponential backoffs do not add
94
+ credit.
95
+
96
+ Switching provider is a re-embed of the whole corpus and a re-measured
97
+ `vector_floor`. A different provider is a different embedding space, and the
98
+ invariant against copying a calibrated constant applies across vendors with more
99
+ force, not less.
100
+
101
+ Verified live against the real API on a funded key: 1536-dimension vectors, a
102
+ paraphrase at cosine 0.812 against an unrelated sentence at 0.058, and the two
103
+ intents agreeing to 0.9997 — which is the symmetry that makes the empty task
104
+ labels correct. Then through the whole plane: a real record ingested to Postgres
105
+ under `embedding_model = text-embedding-3-small`, 23 chunks, 0 failed, stored at
106
+ the declared width of 1536 and L2-normalized as the framework promises.
107
+
108
+ One more defect the live call found: `buildShippedProvider` handed EVERY
109
+ provider Gemini's task labels from global config, so an OpenAI run logged its
110
+ space as `text-embedding-3-small/d1536/RETRIEVAL_DOCUMENT` — a label that vendor
111
+ has no concept of and never received. The labels moved onto the registry row,
112
+ where a vendor's shape belongs.
113
+
114
+ - eb54871: The npm page shows what the product does, on the first screen.
115
+
116
+ It asserted the headline behaviour — a cited answer, an honest refusal — and
117
+ demonstrated it nowhere. A reader had no way to tell a real mechanism from a
118
+ prompt instruction, which is exactly the skepticism this product exists to
119
+ answer. It now shows three things, all of them real output: the admitted count
120
+ moving when a human approves a draft, the `provenance` and `governance` a search
121
+ hit carries, and an abstention envelope. It also links the hello world.
122
+
123
+ Nothing was added to the tarball; this is the README npm renders.
124
+
125
+ - 6e5ff3e: Repo documentation and a test only — nothing an adopter installs changes.
126
+
127
+ `docs/status.md` named 0.0.42 while the published package was 0.0.53. Authority
128
+ rule 3 makes that file the only authority on what is built, and it is the first
129
+ thing an evaluator's coding agent reads. It is current now, and a docs-truth
130
+ assertion holds it equal to `packages/ksor/package.json` so a Version PR cannot
131
+ bump one without the other. It also records that the full kernel walk was re-run
132
+ against 0.0.53 — it had last run against 0.0.18, thirty-five releases earlier.
133
+
134
+ - ed947c1: The deploy runbook stops ruling out the one step Vercel calls required.
135
+
136
+ `docs/deploying.md` said the silent-404 failure "does not depend on the
137
+ Application Preset". Vercel's own guide says the opposite: a project builds as
138
+ services only when the preset is `Services` AND `vercel.json` carries a
139
+ `services` key, and "if either is missing, Vercel falls back to its default
140
+ framework detection and ignores your services configuration" — which is that
141
+ failure exactly, and no file in the repository can set a project setting.
142
+
143
+ One measurement of ours disagrees with that guide and is recorded rather than
144
+ reconciled: two projects read back from the API, one `Services` and one `Other`,
145
+ both built and served. Both facts are real; guessing between them is what
146
+ produced the sentence that steered adopters away from the fix.
147
+
148
+ The scaffold's runbook now sets the preset at step 2, and ends with the three
149
+ curls that tell a live deployment from a Ready-and-404 one — `/mcp` answering
150
+ 405 is the door refusing a GET, which is how you know it is routed at all.
151
+
152
+ ## 0.0.53
153
+
154
+ ### Patch Changes
155
+
156
+ - f77ca55: The emitted README documents `.ksor/people.yaml`.
157
+
158
+ Display names shipped documented in the scaffold's AGENTS.md and not in its
159
+ README — so the coding agent knew about the feature and the owner did not, on
160
+ the one feature whose entire input is a human typing their colleagues' names.
161
+ The README now carries it beside the keys that publish a document: the map
162
+ shape, that an actor with no entry renders exactly as stored, and that
163
+ appearing in the file grants no authority at all.
164
+
3
165
  ## 0.0.52
4
166
 
5
167
  ### Patch Changes
package/README.md CHANGED
@@ -16,6 +16,36 @@ pnpm install
16
16
  pnpm dev # the site, live at http://localhost:3000
17
17
  ```
18
18
 
19
+ Then write a document and publish it:
20
+
21
+ ```console
22
+ $ pnpm exec ksor build
23
+ ksor build: 6 document(s), 5 admitted to a machine surface
24
+ ```
25
+
26
+ **Six documents, five admitted.** The one you just wrote is a `draft`, so it
27
+ reaches nothing an AI agent reads — not `llms.txt`, not the markdown twins —
28
+ until a human approves it. Approve it and the count moves. That is the whole
29
+ product, and it costs nothing: no database, no API key, no account.
30
+
31
+ Climb one rung and an agent asks the record a question. The answer carries
32
+ where it came from:
33
+
34
+ ```json
35
+ "provenance": { "stable_id": "knowledge/refund-policy", "generation": 1 },
36
+ "governance": { "status": "stable", "approval": { "by": "human:you" } }
37
+ ```
38
+
39
+ …and a question the record does not cover is declined rather than guessed at:
40
+
41
+ ```json
42
+ { "ok": false, "abstained": true, "gate": { "floor": 0.622 } }
43
+ ```
44
+
45
+ **[Hello world](https://github.com/panaversity/ksor/blob/main/docs/tutorials/00-hello-world.md)**
46
+ walks all of that in about fifteen minutes. Every command and output in it was
47
+ run and pasted as it appeared — including the ones above.
48
+
19
49
  One command emits a complete governed project: the record (`knowledge/`,
20
50
  plain CommonMark), a working documentation site with hot reload, offline
21
51
  search and `llms.txt`, adopter CI, a dependency-free format checker