@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 +162 -0
- package/README.md +30 -0
- package/dist/cli.mjs +266 -46
- package/dist/{gateway-api-Ck1l_Sgs-B-_wMYLB.mjs → gateway-api-uhx2l1kC-C2BAxISt.mjs} +197 -17
- package/dist/gateway.mjs +1 -1
- package/docs/deploying.md +41 -8
- package/docs/ingesting.md +25 -8
- package/package.json +3 -3
- package/templates/scaffold/AGENTS.md +34 -5
- package/templates/scaffold/README.md +78 -7
- package/templates/scaffold/mcp.json +13 -0
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
|