@333eco/corpus 2.3.4 → 2.4.0

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
@@ -33,6 +33,7 @@ So the check moves into the response:
33
33
  "doi": "10.5281/zenodo.22217516",
34
34
  "opentimestamps": true,
35
35
  "deposited_matches_current": true,
36
+ "hostile_review": null,
36
37
  "verify": {
37
38
  "sha256": "printf '%s' \"$(cat <file>)\" | shasum -a 256 # compare to provenance.sha256",
38
39
  "doi": "https://doi.org/10.5281/zenodo.22217516",
@@ -44,6 +45,11 @@ So the check moves into the response:
44
45
  The `verify` block is an instruction, not a promise — it tells you exactly what
45
46
  to run, so you do not have to trust this sentence either.
46
47
 
48
+ `hostile_review` is the date of the latest ruled review by an outside reader chosen as
49
+ the one most likely to find the document wrong, whose section structure still matches
50
+ the text served — or `null`, stated rather than omitted. It is derived from the corpus's
51
+ public `reviews.json` (roles only, never names), and a structural revision resets it.
52
+
47
53
  ⭐ **The demonstration is the contribution.** Anyone can propose provenance-carrying
48
54
  retrieval. Serving it over a corpus where the anchors are already years deep in
49
55
  the Bitcoin blockchain is a different claim, and it is not one that can be
@@ -54,6 +60,12 @@ manufactured on a schedule.
54
60
  | Tool | Returns |
55
61
  | --- | --- |
56
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 |
57
69
 
58
70
  ⭐ **`search_corpus` matches the phrase first, then all terms.** An exact substring hit
59
71
  always wins and ranks above everything else — which keeps `B-Heart` and `Re-Tip` precise,
@@ -70,11 +82,43 @@ verbatim. **A zero result was recording the matcher's limits while being read as
70
82
 
71
83
  ⭐ On a zero result the response now names **which terms appear in no document at all**
72
84
  (`absent_terms`), so a dead end says something instead of nothing.
73
- | `get_document` | one document in full — canonical text, never a summary |
74
- | `list_documents` | slugs, titles, genres, licences, provenance summaries |
75
- | `list_predictions` | the research program's pre-registered predictions, with falsifiers and status |
76
- | `get_prediction` | one prediction, plus the provenance envelope of the paper that registered it |
77
- | `get_program` | the program's hard core, chapters, stopping rule and count reconciliation, verbatim |
85
+
86
+ ### Reading a whole shelf
87
+
88
+ ⭐ **Search answers from excerpts, and a model answers from what it opened.** A frontier
89
+ model connected to this server gave answers that were accurate but incomplete: it searched,
90
+ opened a few documents and stopped. The fix is not a bigger context window — a shelf of this
91
+ corpus already fits one — but a way to read the shelf.
92
+
93
+ - **`list_documents` reports `bytes` and `words`** per document and `total_bytes` /
94
+ `total_words` for the filtered set, so a caller can see whether a slice fits before reading
95
+ it. ⛔ **Never tokens:** a token count is true for one tokenizer and wrong for every other
96
+ model family; bytes and words are checkable.
97
+ - **`read_documents`** takes the same filters as `list_documents` — or `slugs` — and returns
98
+ every matching document in full, **one content block per document**, each behind its
99
+ provenance header, so each still verifies on its own. ⛔ Never a concatenation and never a
100
+ summary.
101
+ - **Paged by size.** `max_bytes` defaults to 90,000 (under the 25,000-token point at which
102
+ Claude Code moves a tool result into a file) and may go to 400,000. **A document is never
103
+ split** — half a document verifies nothing — so one larger than the page arrives alone and
104
+ says `over_budget`. Follow `next_cursor`; a cursor from a different corpus version is refused
105
+ rather than serving page 2 of another corpus.
106
+
107
+ ⭐ **Every document ends with an `[END OF DOCUMENT — <slug> · <n> words]` line**, by every
108
+ route. The server never cuts a document, but a client may, and a cut document reads as a
109
+ complete one. The end is stated in the text, where a cut removes it — not in a field that would
110
+ survive the cut and assert a completeness the text no longer has.
111
+
112
+ ### Nothing silently missing
113
+
114
+ The envelope proves each served document authentic; nothing used to prove that none was
115
+ **dropped**. The build now writes a **manifest** — every file it considered, and what became of
116
+ it — and refuses to finish unless `candidates = served + excluded + held`. Both surfaces refuse
117
+ to serve a corpus whose documents do not match its manifest, and two files claiming one slug
118
+ fail the build rather than leaving one listed and unreadable. The counts, and the reason for
119
+ every exclusion or hold, arrive in `list_documents` under `completeness`; the full manifest is at
120
+ `https://corpus.333.eco/manifest.json`. ⚠️ **It detects omission, not tampering** — each
121
+ document's sha256 is the other half.
78
122
 
79
123
  ⭐ **The three program tools return the STATING PAPER's envelope, not the register's.**
80
124
  That is the register's own instruction rather than a design flourish: *"verify the
@@ -86,7 +130,7 @@ and the build refuses to emit one that is not — a field must match a *complete
86
130
  cell of its source, because a fragment of a cell is still a substring of it.
87
131
 
88
132
  The program tools appear only when the index carries a program block. An index
89
- built over a corpus without one advertises three tools, not six.
133
+ built over a corpus without one advertises four tools, not seven.
90
134
 
91
135
  ## Resources
92
136
 
@@ -100,7 +144,8 @@ resource is consumed differently: clients hand its contents straight to a model
100
144
  context, and a `mimeType` field does not travel with a quotation. So every read
101
145
  returns a `[PROVENANCE — corpus.333.eco]` header — licence and whom to attribute,
102
146
  sha256 and **what it does not cover**, both DOIs, the OpenTimestamps command, and
103
- the one-line `curl … | shasum` check — followed by the document verbatim.
147
+ the one-line `curl … | shasum` check — followed by the document verbatim and its
148
+ `[END OF DOCUMENT]` line.
104
149
 
105
150
  This is the letters' rule applied a second time. Voice in the letters is marked
106
151
  inline rather than in metadata because *with a field an agent must LOOK to know;
@@ -126,13 +171,11 @@ actively strip.
126
171
 
127
172
  ## Attribution is a build-time property
128
173
 
129
- Seven documents are CC-BY and the rest CC0. A CC-BY document that names no author
174
+ Most documents are CC0 and the rest CC-BY (counted in the licence table below). A CC-BY document that names no author
130
175
  hands every consumer an obligation nobody can discharge, so **the build fails**
131
176
  rather than serving it — the same reasoning as the licence gate: a property, not a
132
177
  rule someone has to remember.
133
178
 
134
- | `list_predictions` | the research program's pre-registered predictions, with falsifiers and status |
135
-
136
179
  **Results are structured.** Every tool returns `structuredContent` — the typed
137
180
  object — and uses `content` for the human form: the document text with its
138
181
  provenance header for `get_document`, readable excerpts for `search_corpus`, a
@@ -164,11 +207,11 @@ only if its own source declares a licence this corpus publishes under. There is
164
207
  no glob and no directory allowlist, because the source repositories are **not**
165
208
  uniformly licensed and never were:
166
209
 
167
- - `TH/publications` — 96 CC0, **7 CC-BY author-voice essays**
210
+ - `TH/publications` — CC0, plus the **CC-BY author-voice essays**
168
211
  - `TH/film` — rights-reserved, a separate repository *by licence*. Never served.
169
212
  - `333.eco` — the namespace policy is commercial and explicitly unpublished.
170
213
 
171
- A glob would have relicensed seven essays by publication. A file with **no**
214
+ A glob would have relicensed the author-voice essays by publication. A file with **no**
172
215
  declaration is excluded and reported, never assumed CC0 — the default-open
173
216
  failure is the one nobody can undo after somebody builds on it.
174
217
 
@@ -271,6 +314,7 @@ per isolate and memoises it.
271
314
  Transport is **Streamable HTTP**, not the superseded HTTP+SSE pair. The server is
272
315
  stateless and read-only, so it never opens a stream: `POST /mcp` for JSON-RPC,
273
316
  `GET /mcp` returns 405 rather than holding open a stream that would carry nothing.
317
+ `GET /manifest.json` returns the served corpus's manifest.
274
318
 
275
319
  ```sh
276
320
  cd worker
@@ -360,11 +404,11 @@ because there is no enforcer.
360
404
 
361
405
  ⛔ **Not one beacon per tool call.** An agent working through the corpus fires
362
406
  dozens of calls in seconds, and a notification channel that reports each of them
363
- is a channel nobody reads. The beacon fires on the *handshake*, and the receiving
364
- function pushes only the **first sighting of a client label**, counting every one
365
- after it in silence — so a notification means *a client we have never seen
366
- appeared*. `corpus_error` is exempt and always pushes: it is rare by construction,
367
- and silence is the wrong default for an outage.
407
+ is a channel nobody reads. The beacon fires on the *handshake*, once per
408
+ connection. What the receiving function does with it is its own setting: since
409
+ 2026-09-09 it pushes one notification per handshake, and a flag restores
410
+ *first sighting of a client label only*. `corpus_error` always pushes: it is rare by
411
+ construction, and silence is the wrong default for an outage.
368
412
 
369
413
  ⚠️ **A dead beacon must not look like a quiet one.** If the receiving allowlist
370
414
  changes, the POST 403s and the pushes simply stop — indistinguishable from *no new