@333eco/corpus 2.3.5 → 2.4.1

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/README.md CHANGED
@@ -60,6 +60,12 @@ manufactured on a schedule.
60
60
  | Tool | Returns |
61
61
  | --- | --- |
62
62
  | `search_corpus` | matching documents, provenance envelope, and an excerpt around each match |
63
+ | `get_document` | one document in full — canonical text, never a summary |
64
+ | `read_documents` | whole documents — a shelf (the `list_documents` filters) or a list of slugs — one content block each, paged by size |
65
+ | `list_documents` | slugs, titles, genres, licences, provenance summaries, **sizes**, and the manifest's completeness counts |
66
+ | `list_predictions` | the research program's pre-registered predictions, with falsifiers and status |
67
+ | `get_prediction` | one prediction, plus the provenance envelope of the paper that registered it |
68
+ | `get_program` | the program's hard core, chapters, stopping rule and count reconciliation, verbatim |
63
69
 
64
70
  ⭐ **`search_corpus` matches the phrase first, then all terms.** An exact substring hit
65
71
  always wins and ranks above everything else — which keeps `B-Heart` and `Re-Tip` precise,
@@ -76,11 +82,62 @@ verbatim. **A zero result was recording the matcher's limits while being read as
76
82
 
77
83
  ⭐ On a zero result the response now names **which terms appear in no document at all**
78
84
  (`absent_terms`), so a dead end says something instead of nothing.
79
- | `get_document` | one document in full — canonical text, never a summary |
80
- | `list_documents` | slugs, titles, genres, licences, provenance summaries |
81
- | `list_predictions` | the research program's pre-registered predictions, with falsifiers and status |
82
- | `get_prediction` | one prediction, plus the provenance envelope of the paper that registered it |
83
- | `get_program` | the program's hard core, chapters, stopping rule and count reconciliation, verbatim |
85
+
86
+ ⭐ **Diacritics are optional.** `metta` finds what `mettā` finds, and `Tonle Sap` reaches the
87
+ text that writes `Tonlé Sap` — before 2.4.1 a plain-ASCII query found 6 documents where the
88
+ marked one found 20. ⛔ **Fold to match, serve verbatim:** the fold touches only what is
89
+ compared, and every excerpt carries the corpus's own spelling, because a Pāli or Sanskrit
90
+ spelling is a tradition marker rather than a typo. Only Latin combining diacritics are folded;
91
+ Khmer and Burmese vowel signs are marks too, and are left exactly as written.
92
+
93
+ ⭐ **Every result says it is an excerpt.** The text ends with a line naming how many of the
94
+ matches it shows and the `read_documents` call that reads those documents in full. It sits in
95
+ the result rather than only in the server's instructions, because a result reaches the model in
96
+ every client, at the moment it decides whether to keep reading.
97
+
98
+ ### Reading a whole shelf
99
+
100
+ ⭐ **Search answers from excerpts, and a model answers from what it opened.** A frontier
101
+ model connected to this server gave answers that were accurate but incomplete: it searched,
102
+ opened a few documents and stopped. The fix is not a bigger context window — a shelf of this
103
+ corpus already fits one — but a way to read the shelf.
104
+
105
+ - **`list_documents` reports `bytes` and `words`** per document and `total_bytes` /
106
+ `total_words` for the filtered set, so a caller can see whether a slice fits before reading
107
+ it. ⛔ **Never tokens:** a token count is true for one tokenizer and wrong for every other
108
+ model family; bytes and words are checkable.
109
+ - **`read_documents`** takes the same filters as `list_documents` — or `slugs` — and returns
110
+ every matching document in full, **one content block per document**, each behind its
111
+ provenance header, so each still verifies on its own. ⛔ Never a concatenation and never a
112
+ summary.
113
+ - **Paged by size.** `max_bytes` defaults to 90,000 (under the 25,000-token point at which
114
+ Claude Code moves a tool result into a file) and may go to 400,000. **A document is never
115
+ split** — half a document verifies nothing — so one larger than the page arrives alone and
116
+ says `over_budget`. Follow `next_cursor`; a cursor from a different corpus version is refused
117
+ rather than serving page 2 of another corpus.
118
+ - **`list_documents` says how to read what it listed:** `read_with` carries the same filters as
119
+ `read_documents` arguments.
120
+
121
+ ⚠️ **The server can point; it cannot make a model read.** Its instructions say *for a broad
122
+ question, read the relevant shelf in full* — deliberately conditional, because a whole shelf read
123
+ to answer a one-fact question is slower, costlier and often worse. Clients differ in whether they
124
+ show server instructions at all, which is why the pointers also live in the results.
125
+
126
+ ⭐ **Every document ends with an `[END OF DOCUMENT — <slug> · <n> words]` line**, by every
127
+ route. The server never cuts a document, but a client may, and a cut document reads as a
128
+ complete one. The end is stated in the text, where a cut removes it — not in a field that would
129
+ survive the cut and assert a completeness the text no longer has.
130
+
131
+ ### Nothing silently missing
132
+
133
+ The envelope proves each served document authentic; nothing used to prove that none was
134
+ **dropped**. The build now writes a **manifest** — every file it considered, and what became of
135
+ it — and refuses to finish unless `candidates = served + excluded + held`. Both surfaces refuse
136
+ to serve a corpus whose documents do not match its manifest, and two files claiming one slug
137
+ fail the build rather than leaving one listed and unreadable. The counts, and the reason for
138
+ every exclusion or hold, arrive in `list_documents` under `completeness`; the full manifest is at
139
+ `https://corpus.333.eco/manifest.json`. ⚠️ **It detects omission, not tampering** — each
140
+ document's sha256 is the other half.
84
141
 
85
142
  ⭐ **The three program tools return the STATING PAPER's envelope, not the register's.**
86
143
  That is the register's own instruction rather than a design flourish: *"verify the
@@ -92,7 +149,7 @@ and the build refuses to emit one that is not — a field must match a *complete
92
149
  cell of its source, because a fragment of a cell is still a substring of it.
93
150
 
94
151
  The program tools appear only when the index carries a program block. An index
95
- built over a corpus without one advertises three tools, not six.
152
+ built over a corpus without one advertises four tools, not seven.
96
153
 
97
154
  ## Resources
98
155
 
@@ -106,7 +163,8 @@ resource is consumed differently: clients hand its contents straight to a model
106
163
  context, and a `mimeType` field does not travel with a quotation. So every read
107
164
  returns a `[PROVENANCE — corpus.333.eco]` header — licence and whom to attribute,
108
165
  sha256 and **what it does not cover**, both DOIs, the OpenTimestamps command, and
109
- the one-line `curl … | shasum` check — followed by the document verbatim.
166
+ the one-line `curl … | shasum` check — followed by the document verbatim and its
167
+ `[END OF DOCUMENT]` line.
110
168
 
111
169
  This is the letters' rule applied a second time. Voice in the letters is marked
112
170
  inline rather than in metadata because *with a field an agent must LOOK to know;
@@ -132,13 +190,11 @@ actively strip.
132
190
 
133
191
  ## Attribution is a build-time property
134
192
 
135
- Seven documents are CC-BY and the rest CC0. A CC-BY document that names no author
193
+ Most documents are CC0 and the rest CC-BY (counted in the licence table below). A CC-BY document that names no author
136
194
  hands every consumer an obligation nobody can discharge, so **the build fails**
137
195
  rather than serving it — the same reasoning as the licence gate: a property, not a
138
196
  rule someone has to remember.
139
197
 
140
- | `list_predictions` | the research program's pre-registered predictions, with falsifiers and status |
141
-
142
198
  **Results are structured.** Every tool returns `structuredContent` — the typed
143
199
  object — and uses `content` for the human form: the document text with its
144
200
  provenance header for `get_document`, readable excerpts for `search_corpus`, a
@@ -170,11 +226,11 @@ only if its own source declares a licence this corpus publishes under. There is
170
226
  no glob and no directory allowlist, because the source repositories are **not**
171
227
  uniformly licensed and never were:
172
228
 
173
- - `TH/publications` — 96 CC0, **7 CC-BY author-voice essays**
229
+ - `TH/publications` — CC0, plus the **CC-BY author-voice essays**
174
230
  - `TH/film` — rights-reserved, a separate repository *by licence*. Never served.
175
231
  - `333.eco` — the namespace policy is commercial and explicitly unpublished.
176
232
 
177
- A glob would have relicensed seven essays by publication. A file with **no**
233
+ A glob would have relicensed the author-voice essays by publication. A file with **no**
178
234
  declaration is excluded and reported, never assumed CC0 — the default-open
179
235
  failure is the one nobody can undo after somebody builds on it.
180
236
 
@@ -277,6 +333,7 @@ per isolate and memoises it.
277
333
  Transport is **Streamable HTTP**, not the superseded HTTP+SSE pair. The server is
278
334
  stateless and read-only, so it never opens a stream: `POST /mcp` for JSON-RPC,
279
335
  `GET /mcp` returns 405 rather than holding open a stream that would carry nothing.
336
+ `GET /manifest.json` returns the served corpus's manifest.
280
337
 
281
338
  ```sh
282
339
  cd worker
@@ -366,11 +423,11 @@ because there is no enforcer.
366
423
 
367
424
  ⛔ **Not one beacon per tool call.** An agent working through the corpus fires
368
425
  dozens of calls in seconds, and a notification channel that reports each of them
369
- is a channel nobody reads. The beacon fires on the *handshake*, and the receiving
370
- function pushes only the **first sighting of a client label**, counting every one
371
- after it in silence — so a notification means *a client we have never seen
372
- appeared*. `corpus_error` is exempt and always pushes: it is rare by construction,
373
- and silence is the wrong default for an outage.
426
+ is a channel nobody reads. The beacon fires on the *handshake*, once per
427
+ connection. What the receiving function does with it is its own setting: since
428
+ 2026-09-09 it pushes one notification per handshake, and a flag restores
429
+ *first sighting of a client label only*. `corpus_error` always pushes: it is rare by
430
+ construction, and silence is the wrong default for an outage.
374
431
 
375
432
  ⚠️ **A dead beacon must not look like a quiet one.** If the receiving allowlist
376
433
  changes, the POST 403s and the pushes simply stop — indistinguishable from *no new