@ainize/core 0.1.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +20 -0
  3. package/dist/ain-ledger.d.ts +191 -0
  4. package/dist/ain-ledger.d.ts.map +1 -0
  5. package/dist/ain-ledger.js +714 -0
  6. package/dist/ain-ledger.js.map +1 -0
  7. package/dist/browser.d.ts +15 -0
  8. package/dist/browser.d.ts.map +1 -0
  9. package/dist/browser.js +16 -0
  10. package/dist/browser.js.map +1 -0
  11. package/dist/bytes.d.ts +3 -0
  12. package/dist/bytes.d.ts.map +1 -0
  13. package/dist/bytes.js +14 -0
  14. package/dist/bytes.js.map +1 -0
  15. package/dist/canonical.d.ts +5 -0
  16. package/dist/canonical.d.ts.map +1 -0
  17. package/dist/canonical.js +70 -0
  18. package/dist/canonical.js.map +1 -0
  19. package/dist/catalog.d.ts +181 -0
  20. package/dist/catalog.d.ts.map +1 -0
  21. package/dist/catalog.js +496 -0
  22. package/dist/catalog.js.map +1 -0
  23. package/dist/config-schema.d.ts +222 -0
  24. package/dist/config-schema.d.ts.map +1 -0
  25. package/dist/config-schema.js +302 -0
  26. package/dist/config-schema.js.map +1 -0
  27. package/dist/config.d.ts +128 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +330 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/events.d.ts +14 -0
  32. package/dist/events.d.ts.map +1 -0
  33. package/dist/events.js +20 -0
  34. package/dist/events.js.map +1 -0
  35. package/dist/identity.d.ts +15 -0
  36. package/dist/identity.d.ts.map +1 -0
  37. package/dist/identity.js +59 -0
  38. package/dist/identity.js.map +1 -0
  39. package/dist/index.d.ts +17 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +17 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/ledger.d.ts +134 -0
  44. package/dist/ledger.d.ts.map +1 -0
  45. package/dist/ledger.js +2 -0
  46. package/dist/ledger.js.map +1 -0
  47. package/dist/lineage.d.ts +63 -0
  48. package/dist/lineage.d.ts.map +1 -0
  49. package/dist/lineage.js +156 -0
  50. package/dist/lineage.js.map +1 -0
  51. package/dist/local-ledger.d.ts +74 -0
  52. package/dist/local-ledger.d.ts.map +1 -0
  53. package/dist/local-ledger.js +229 -0
  54. package/dist/local-ledger.js.map +1 -0
  55. package/dist/npz.d.ts +107 -0
  56. package/dist/npz.d.ts.map +1 -0
  57. package/dist/npz.js +502 -0
  58. package/dist/npz.js.map +1 -0
  59. package/dist/ops.d.ts +65 -0
  60. package/dist/ops.d.ts.map +1 -0
  61. package/dist/ops.js +9 -0
  62. package/dist/ops.js.map +1 -0
  63. package/dist/teach-auth.d.ts +19 -0
  64. package/dist/teach-auth.d.ts.map +1 -0
  65. package/dist/teach-auth.js +33 -0
  66. package/dist/teach-auth.js.map +1 -0
  67. package/dist/types.d.ts +1096 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +98 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/x402.d.ts +35 -0
  72. package/dist/x402.d.ts.map +1 -0
  73. package/dist/x402.js +84 -0
  74. package/dist/x402.js.map +1 -0
  75. package/package.json +49 -0
@@ -0,0 +1,1096 @@
1
+ /**
2
+ * Shared domain types for the n-gram knowledge patch marketplace.
3
+ *
4
+ * Vocabulary follows the patent specification (10-출원명세서-전문.md):
5
+ * - Patch (지식 패치): rows (addr, before, after) of an n-gram conditional-memory table + model identity.
6
+ * - Benchmark (벤치마크): queries/answers + collateral bound used to machine-verify a patch.
7
+ * - Anchor / Attest / Settle: ledger record kinds (등록·증명·정산 블록).
8
+ * - Publish state machine: DRAFT → ANNOUNCED → VERIFYING → LISTED | REJECTED, LISTED → CHALLENGED → VERIFYING,
9
+ * and any announced state → RETIRED when the author writes a `retire` record (the record stays; the sale stops).
10
+ */
11
+ export type PatchStatus = 'DRAFT' | 'ANNOUNCED' | 'VERIFYING' | 'LISTED' | 'REJECTED' | 'CHALLENGED' | 'SUPERSEDED'
12
+ /** The author appended a `retire` record: the anchor stays on the permanent record, the knowledge stops being sold. */
13
+ | 'RETIRED';
14
+ export declare const PATCH_STATUSES: PatchStatus[];
15
+ /** Billing model for a patch (청구항 12). */
16
+ export type BillingModel = 'per_download' | 'per_apply_hour' | 'per_hit';
17
+ /**
18
+ * The billing models a node can actually charge (finding 360).
19
+ *
20
+ * All three were offered on the publish form and printed to buyers as "pay per hour loaded" and "pay per use",
21
+ * and `settlePayment` charges `anchor.price` exactly once per 402 round and copies `billing` onto the settlement.
22
+ * Nothing anywhere meters an hour or a use. So a seller picked a revenue model the product does not implement,
23
+ * and a buyer was told they were paying by the hour when they had paid once. Anchors already carrying one of the
24
+ * other two keep it — the record is immutable — and every surface says what really happens to them; they are no
25
+ * longer OFFERED to anyone new.
26
+ */
27
+ export declare const BILLING_IMPLEMENTED: readonly BillingModel[];
28
+ export declare const billingImplemented: (b: unknown) => b is BillingModel;
29
+ export interface BenchmarkSpec {
30
+ /** Stable id of the benchmark schema (e.g. "krx-ticker-codes"). Patches sharing a schema are comparable/conflicting. */
31
+ schema: string;
32
+ /** Number of queries. */
33
+ queries: number;
34
+ /** Prompt formats included. */
35
+ format: string[];
36
+ /** Collateral (locality) bound in nats for unrelated-text logprob drift. */
37
+ collateral_bound_nat?: number;
38
+ /**
39
+ * Optional inline sample set: {prompt, expect} pairs used by verifiers. Teach anchors carry at most
40
+ * `TEACH_SAMPLES_ON_CHAIN` (the child's own first, then one per parent); the full list lives in the dataset blob's
41
+ * `benchmark.jsonl`, whose canonical hash is `answers_hash`. `source` names the parent a sample was taken from, so a
42
+ * verifier scores per source without fetching the parents (lineage design §5.1).
43
+ */
44
+ samples?: BenchmarkSample[];
45
+ /** sha256 of the sealed answer set (commit–reveal, 청구항 19-2) — for teach anchors: sha256(canonical full sample list). */
46
+ answers_hash?: string;
47
+ }
48
+ export interface BenchmarkSample {
49
+ prompt: string;
50
+ expect: string;
51
+ source?: string;
52
+ }
53
+ /** How many benchmark samples a teach anchor carries on the ledger (lineage design §5.1, F10: ~100 KB AIN free tier). */
54
+ export declare const TEACH_SAMPLES_ON_CHAIN = 32;
55
+ export interface ModelIdentity {
56
+ /** Human name, e.g. "Qwen3.8-Flash-Next-W4A16". */
57
+ id_M: string;
58
+ /** Checkpoint hash (optional in dev). */
59
+ checkpoint_hash?: string;
60
+ /** Tokenizer hash. */
61
+ tokenizer_hash?: string;
62
+ /** Hash constant / seed of the n-gram address function. */
63
+ hash_const?: string;
64
+ /** Row width (embedding dim) of the table. */
65
+ row_dim?: number;
66
+ }
67
+ /**
68
+ * A data provider credited on an anchor (teach mode). The on-chain `author` is always the publishing node
69
+ * (AIN write rule `auth.addr === newData.author`); contributors are signed claims carried inside the anchor body.
70
+ */
71
+ export interface Contributor {
72
+ /** Paid address. */
73
+ address: string;
74
+ /** Teaching key when different from `address` (payout wallet declared by the key holder). */
75
+ signer?: string;
76
+ /** Display name (≤ 40 chars; the operator may hide it in the UI). */
77
+ name?: string;
78
+ /** 0..1 fraction of the SELLER remainder after the lineage pool (carved sequentially, see royaltySplit). */
79
+ share: number;
80
+ role: 'data_provider';
81
+ /** 'signed' = `sig` proves the claim; 'declared' = payout wallet typed by the key holder (can only receive). */
82
+ proof: 'signed' | 'declared';
83
+ /** Signature by `signer ?? address` over hashCanonical({patch_sha256, benchmark_hash, address, share}). */
84
+ sig?: string;
85
+ }
86
+ /** Maximum number of contributors carried on one anchor (the knowledge app lives on the AIN free tier, ~100 KB state). */
87
+ export declare const MAX_CONTRIBUTORS = 4;
88
+ /**
89
+ * The floor under `PatchAnchor.royalty_share` (item 191). Every public surface of this product promises the original
90
+ * creators 30 % of each sale; before this constant that promise was `market.royaltyShare` on the node doing the
91
+ * SELLING, so a derivative's seller could set it to 0 and keep the base creator's share while her page still said
92
+ * 30 %. A seller may promise MORE (config, or a parent that already promised more); it may never promise less.
93
+ */
94
+ export declare const NETWORK_MIN_ROYALTY_SHARE = 0.3;
95
+ /**
96
+ * The floor under `PatchAnchor.verifier_share` (item 325): the fraction of the seller's side of each sale that is
97
+ * divided equally among the attestations that count toward the knowledge's quorum. Verification is a GPU minute and
98
+ * a gigabyte of someone else's body per item; before this it earned nothing anywhere in the product.
99
+ */
100
+ export declare const NETWORK_MIN_VERIFIER_SHARE = 0.05;
101
+ /** Hard ceiling on the verification fee, whatever a config or a peer-written anchor claims. */
102
+ export declare const MAX_VERIFIER_SHARE = 0.5;
103
+ /** How many wrong answers one attestation carries back to the author (item 155). */
104
+ export declare const ATTESTATION_MAX_FAILURES = 5;
105
+ /** Truncation for the prompt / expected / actual strings in `Attestation.failures` (item 155). */
106
+ export declare const ATTESTATION_PROMPT_MAX = 200;
107
+ export declare const ATTESTATION_GOT_MAX = 120;
108
+ /** A challenge takes a knowledge off sale everywhere: it has to say why, in at least this many characters (item 328). */
109
+ export declare const CHALLENGE_MIN_REASON = 20;
110
+ /**
111
+ * How long one address's challenge holds a knowledge before the same address may file another on it (item 328). A
112
+ * challenge is free and stops every sale, so without this one node could keep a rival off sale for ever by re-filing.
113
+ */
114
+ export declare const CHALLENGE_COOLDOWN_MS: number;
115
+ /** Effective lineage share for one sale: what the ANCHOR promised, floored at the network minimum (item 191). */
116
+ export declare function effectiveRoyaltyShare(anchor: {
117
+ royalty_share?: number;
118
+ } | undefined, configured?: number): number;
119
+ /** Effective verification share for one sale: what the ANCHOR promised, floored at the network minimum (item 325). */
120
+ export declare function effectiveVerifierShare(anchor: {
121
+ verifier_share?: number;
122
+ } | undefined, configured?: number): number;
123
+ /** Where an anchor came from: registered by the operator (default when absent) or taught by a visitor. */
124
+ export type PatchOrigin = 'operator' | 'teach';
125
+ /**
126
+ * Licences a training set (and the knowledge built from it) may carry (lineage design §6.4). The list is closed: an
127
+ * unknown string is refused at publish (`bad_license`) rather than written into an immutable record nobody can read.
128
+ * - CC0 / CC-BY / ODC-By parent → any child licence (attribution travels through `parents[]`);
129
+ * - CC-BY-SA parent → the child must be CC-BY-SA with dataset access at least the parent's;
130
+ * - Proprietary parent → a child may build on top (the parent earns the lineage share) but ships delta-only: no
131
+ * inherited rows in its blob and no inherited benchmark samples on the record.
132
+ */
133
+ export declare const DATASET_LICENSES: readonly ["CC0-1.0", "CC-BY-4.0", "CC-BY-SA-4.0", "ODC-By-1.0", "Proprietary"];
134
+ export type DatasetLicense = (typeof DATASET_LICENSES)[number];
135
+ export declare function isDatasetLicense(v: unknown): v is DatasetLicense;
136
+ /** Who may read a published training set (lineage design §6.1). Absent on an anchor = `private`. */
137
+ export declare const DATASET_ACCESS_LEVELS: readonly ["public", "derivative", "private"];
138
+ export type DatasetAccess = (typeof DATASET_ACCESS_LEVELS)[number];
139
+ /** Public, on-ledger description of a patch (anchor body). */
140
+ export interface PatchAnchor {
141
+ id: string;
142
+ name: string;
143
+ description: string;
144
+ author: string;
145
+ author_name?: string;
146
+ model: ModelIdentity;
147
+ patch_sha256: string;
148
+ size_bytes: number;
149
+ rows: number;
150
+ benchmark: BenchmarkSpec;
151
+ benchmark_hash: string;
152
+ price: string;
153
+ currency: 'AIN' | 'USDC' | 'CREDIT';
154
+ billing: BillingModel;
155
+ license?: string;
156
+ parents: string[];
157
+ parent_authors: string[];
158
+ branch?: string;
159
+ topic_path: string;
160
+ recipe?: PatchRecipe;
161
+ created_at: number;
162
+ /**
163
+ * The day the DATA this was trained on is true of — `YYYY-MM-DD`, declared by the publisher (item 267).
164
+ *
165
+ * `created_at` is when the file was registered and `listed_at` is the newest attestation, so a knowledge baked
166
+ * from yesterday's feed and registered this morning looked exactly as fresh as one baked an hour ago, and the
167
+ * only place the data's own date lived was the name string every daily publisher invented for themselves
168
+ * ("krx-codes-2026-09-03"). Optional, because most knowledge has no such day; absent on every anchor written
169
+ * before the field, which is why a reader must fall back to `created_at` and say which one it is showing.
170
+ */
171
+ as_of?: string;
172
+ /** Address-set sketch (MinHash-like) for cheap conflict pre-checks across peers. */
173
+ addr_sketch?: number[];
174
+ /** Deposit / bond for verification (청구항 19). */
175
+ bond?: string;
176
+ /**
177
+ * The lineage share this knowledge promises its ancestors: the fraction of every sale that is divided among the
178
+ * authors it was built on (item 191). Written into the anchor at createDraft — never read from the SELLING node's
179
+ * config, which the seller controls — as `max(NETWORK_MIN_ROYALTY_SHARE, this node's market.royaltyShare, every
180
+ * parent anchor's declared share)`, so a derivative can raise what its parents promised but never lower it.
181
+ * Absent on anchors written before the field: readers fall back to `max(NETWORK_MIN_ROYALTY_SHARE, config)`.
182
+ */
183
+ royalty_share?: number;
184
+ /**
185
+ * The verification share this knowledge promises the verifiers that attested it: the fraction of the seller's side
186
+ * of every sale divided equally among the attestations that count toward its quorum (item 325). Same rule as
187
+ * `royalty_share`: written at createDraft, floored at NETWORK_MIN_VERIFIER_SHARE, never taken from the seller's
188
+ * config at settle time.
189
+ */
190
+ verifier_share?: number;
191
+ /** 'test' anchors (e2e suites on a shared dev chain) are hidden from catalogs unless explicitly requested. */
192
+ visibility?: 'public' | 'test';
193
+ /** Data providers credited (and paid) for this patch — ≤ MAX_CONTRIBUTORS entries; absent on operator-registered anchors. */
194
+ contributors?: Contributor[];
195
+ /** 'teach' for visitor-taught knowledge; absent/'operator' for knowledge registered by the node operator. */
196
+ origin?: PatchOrigin;
197
+ /**
198
+ * Teach mode v2 / lineage: provenance of the training set this knowledge was built from. Hashes and counts on the
199
+ * record; the bytes live in the content-addressed dataset blob store and are served under `access`
200
+ * (lineage design §5.1, §6 — revises teachable-dataset-design D12: ≤ 32 trained questions are public on the record
201
+ * in any case, as benchmark samples). Absent `access` = `private` (every anchor written before the lineage fields).
202
+ */
203
+ dataset?: AnchorDataset;
204
+ /**
205
+ * What this knowledge did to its bases (lineage design §5.1). Absent = "declared parent — not trained on top"
206
+ * (every pre-lineage anchor: `parents[]` is credit and royalty only, apply order stays last-wins).
207
+ */
208
+ derivation?: PatchDerivation;
209
+ /**
210
+ * The table state the body was trained against (claim 55): an ordered stack of knowledges that must be applied
211
+ * BELOW this one. Absent = stand-alone build (today's semantics). `export: 'squash'` carries the parent rows itself
212
+ * and has an empty stack.
213
+ */
214
+ base?: PatchBase;
215
+ }
216
+ export type DerivationKind = 'extend' | 'update' | 'contradict' | 'merge' | 'transfer';
217
+ export interface DerivationBase {
218
+ patch_id: string;
219
+ patch_sha256: string;
220
+ dataset_sha256?: string;
221
+ rows: number;
222
+ }
223
+ export interface PatchDerivation {
224
+ kind: DerivationKind;
225
+ /** ⊆ parents */
226
+ bases: DerivationBase[];
227
+ added_rows: number;
228
+ changed_rows: number;
229
+ removed_rows: number;
230
+ /** merge only */
231
+ policy?: 'keep_a' | 'keep_b' | 'manual';
232
+ /** merge only */
233
+ tier?: 'union' | 'retrain' | 'rebuild';
234
+ }
235
+ export interface PatchBase {
236
+ /** ordered; the table state the delta was trained against */
237
+ stack: {
238
+ patch_id: string;
239
+ patch_sha256: string;
240
+ }[];
241
+ export: 'delta' | 'squash';
242
+ /** sha256 over sorted (addr int64 LE ‖ bf16(before) bytes) of this knowledge's rows */
243
+ pre_state_sha256: string;
244
+ }
245
+ export interface AnchorDataset {
246
+ sha256: string;
247
+ rows: number;
248
+ source: TeachDatasetSource;
249
+ /** who may read the training set (§6.1); absent = 'private' */
250
+ access?: DatasetAccess;
251
+ /** one of DATASET_LICENSES (§6.4) */
252
+ license?: string;
253
+ /** the training sets this one was built from (⊆ parents) */
254
+ parents?: {
255
+ patch_id: string;
256
+ sha256: string;
257
+ rows: number;
258
+ }[];
259
+ /** leaf = sha256(canonical row); lets a private parent's rows be proven by inclusion */
260
+ merkle_root?: string;
261
+ }
262
+ /** Generation recipe R = (corpus template, benchmark, hyper-params) — what is portable across models. */
263
+ export interface PatchRecipe {
264
+ corpus_template?: string;
265
+ hyperparams?: Record<string, unknown>;
266
+ teacher_student?: boolean;
267
+ /** Teach mode: the trained `Q:/A:` renderings (kept OUT of the anchor body; recipe/blob only). */
268
+ sentences?: string[];
269
+ /** Teach mode: contrast sentences trained alongside so unrelated prompts stay unchanged. */
270
+ contrast?: string[];
271
+ /** Teach mode: held-out paraphrases used for the generalisation check. */
272
+ held_out?: string[];
273
+ /** Model the recipe was produced on (id_M), for local-run instructions. */
274
+ model_id?: string;
275
+ /** Teach mode probe result after training. */
276
+ probe?: {
277
+ hits: number;
278
+ total: number;
279
+ heldout_hits?: number;
280
+ };
281
+ /** Teach mode v2: which dataset (exact bytes + revision) this lesson was trained from — enough to re-train it. */
282
+ dataset?: {
283
+ sha256: string;
284
+ rows: number;
285
+ revision: number;
286
+ source: TeachDatasetSource;
287
+ name?: string;
288
+ };
289
+ /** Lineage: the knowledges loaded into the table before step 1 (in order), with the rows each contributed. */
290
+ parents?: {
291
+ patch_id: string;
292
+ sha256: string;
293
+ rows: number;
294
+ loaded?: boolean;
295
+ }[];
296
+ export?: 'delta' | 'squash';
297
+ pre_state_sha256?: string;
298
+ /** fact index → table addresses of its renderings (recipe.json only — never on the anchor). */
299
+ fact_addrs?: Record<number, number[]>;
300
+ }
301
+ export interface Attestation {
302
+ patch_id: string;
303
+ verifier: string;
304
+ verifier_name?: string;
305
+ patch_sha256: string;
306
+ benchmark_hash: string;
307
+ score: Record<string, string | number>;
308
+ passed: boolean;
309
+ collateral_nat?: number;
310
+ /** "vllm" (independent engine), "hook", or "hash-only" when no runtime was available. */
311
+ verified_on: string;
312
+ /** Restart-aware verification: number of reversions detected & re-applied (청구항 2(d)). */
313
+ restarts_detected?: number;
314
+ /**
315
+ * Up to ATTESTATION_MAX_FAILURES benchmark questions this run got WRONG, with what the model actually answered
316
+ * (item 155). Signed with the rest of the body: a FAIL that says only "0/2" gives the author nothing to fix, and
317
+ * the evidence existed — it was in the verifier's private event log and was thrown away on the way to the record.
318
+ * `got` is truncated to ATTESTATION_GOT_MAX chars; absent on hash-only attestations and on every record written
319
+ * before the field.
320
+ */
321
+ failures?: {
322
+ prompt: string;
323
+ expect: string;
324
+ got: string;
325
+ }[];
326
+ /**
327
+ * Which model server executed this benchmark (item 329). `instance` is a 16-hex fingerprint of the engine — its
328
+ * API origin, the served model id, and the engine's own start time when it reports one — so two verifier processes
329
+ * sharing ONE vLLM produce the SAME instance and the catalog can say "2 attestations, 1 model server" instead of
330
+ * "2 independent verifiers". Absent on hash-only attestations (nothing executed) and on pre-field records.
331
+ */
332
+ executor?: {
333
+ api: string | null;
334
+ model: string | null;
335
+ engine_started?: number;
336
+ instance: string;
337
+ };
338
+ /**
339
+ * false when this node already had the knowledge applied to the shared model, so the run had no un-patched
340
+ * baseline of its own (item 329). Such an attestation is recorded but never counted toward a quorum.
341
+ */
342
+ baseline?: boolean;
343
+ /**
344
+ * @deprecated Historical field. Builds up to 2026-09 copied `verifier.stake` in here and the UI called it a
345
+ * "deposit the verifier loses if it verified wrongly" — nothing was ever escrowed, transferred or slashed
346
+ * (item 127). New attestations omit it; readers must not present it as money at risk.
347
+ */
348
+ stake?: string;
349
+ /**
350
+ * What the run cost (item 340). Without it a 4-question run and a 40-question run on a 2,761-fact knowledge read
351
+ * identically to every buyer and to any payout rule built on top, which would price the cheapest possible run
352
+ * exactly like the careful one. `samples_available` is the anchor's whole question set; `samples_run` is what this
353
+ * verifier actually asked; `duration_ms` is the wall time of the measured section (probe, baseline, apply, score,
354
+ * restore). Absent on hash-only attestations and on every record written before the field.
355
+ */
356
+ duration_ms?: number;
357
+ samples_run?: number;
358
+ samples_available?: number;
359
+ /**
360
+ * A deliberate re-measurement of something this verifier had already attested (item 339) — after a model update, a
361
+ * buyer complaint, a doubt. It is NOT a challenge: it does not take the seller off sale. A recheck that FAILS
362
+ * withdraws this verifier's earlier PASS; one that passes is a visible confirmation.
363
+ */
364
+ recheck?: true;
365
+ /**
366
+ * How much of the body this verifier scored is its declared parents', address for address (item 303): parent id →
367
+ * rows this body shares with it, and `rows` is the body's own row count. A one-fact lesson that ships 2,992 of its
368
+ * base's rows is a resale, and only the node that holds both files can say so. Absent when this node did not hold
369
+ * a parent body to compare against.
370
+ */
371
+ rows_shared_with_parents?: Record<string, number>;
372
+ rows?: number;
373
+ sig: string;
374
+ created_at: number;
375
+ }
376
+ export interface Settlement {
377
+ patch_id: string;
378
+ seller: string;
379
+ buyer: string;
380
+ amount: string;
381
+ currency: string;
382
+ scheme: string;
383
+ tx_hash: string;
384
+ royalty: Record<string, string>;
385
+ /**
386
+ * Lineage the seller's node could not resolve when it priced this sale (item 310): parent id → the amount that
387
+ * ancestor's author was owed. The money is NOT in `royalty` and was NOT kept by the seller — the sale says out
388
+ * loud that a share of it has no payee yet, instead of silently paying the seller 100 %.
389
+ */
390
+ royalty_unresolved?: Record<string, string>;
391
+ billing: BillingModel;
392
+ created_at: number;
393
+ }
394
+ /**
395
+ * A settled buyer says the knowledge they paid for did not work, and the seller answers on the same record (item 347).
396
+ *
397
+ * /terms is honest that "refunds are at the seller's discretion and are not mediated by the protocol" and that a
398
+ * payment "is final once executed" — and non-delivery IS recoverable, because a settled buyer can always fetch the
399
+ * body with a signed header. What was unrecoverable, and unrecorded, is the one thing a buyer cannot get back:
400
+ * quality. The only lever was `patch challenge`, which spends other operators' GPU time, pays the challenger nothing,
401
+ * takes the seller off sale, and appears on no buyer surface — so a bad seller's record stayed clean.
402
+ *
403
+ * A dispute is NOT a challenge: it does not stop sales and it asks nobody to re-run a benchmark. It is a record that
404
+ * a sale was contested, counted per seller, with the seller's answer beside it.
405
+ */
406
+ export interface Dispute {
407
+ patch_id: string;
408
+ /** 'claim' by the buyer; 'answer' by the seller of the same settlement. */
409
+ role: 'claim' | 'answer';
410
+ author: string;
411
+ /** The settlement this is about — the buyer's proof they paid for it. */
412
+ settle_hash: string;
413
+ /** At least DISPUTE_MIN_REASON characters: what did not work. */
414
+ reason: string;
415
+ created_at: number;
416
+ sig: string;
417
+ }
418
+ /** A dispute has to say something: the same floor a challenge reason has. */
419
+ export declare const DISPUTE_MIN_REASON = 20;
420
+ export declare const DISPUTE_MAX_REASON = 1000;
421
+ export interface Challenge {
422
+ patch_id: string;
423
+ challenger: string;
424
+ /** Why the challenger thinks the benchmark no longer holds — at least CHALLENGE_MIN_REASON chars (item 328). */
425
+ reason: string;
426
+ /** @deprecated Historical field — see `Attestation.stake`. Nothing is escrowed; new challenges omit it. */
427
+ stake?: string;
428
+ created_at: number;
429
+ }
430
+ /**
431
+ * What a track costs to subscribe to, per period (finding 359).
432
+ *
433
+ * There was no subscription: `BranchInfo` carried name, description, context and ids and no terms at all, prices
434
+ * are per anchor, and a track owner who curates other people's knowledge received nothing for curating. So the
435
+ * most loyal customer was the most expensive one — every day of a daily track is a fresh full-price sale — and
436
+ * nobody was paid to keep a channel good. This is the CURATION fee, paid to the track's owner once per period; the
437
+ * knowledge on the track is still bought from whoever published it, because it is theirs.
438
+ */
439
+ export interface SubscriptionTerms {
440
+ /** What one period of curation costs, in `currency`. '0' is a free track that still has terms. */
441
+ price: string;
442
+ currency: string;
443
+ /** How long one payment lasts, in days. */
444
+ period_days: number;
445
+ }
446
+ export interface BranchInfo {
447
+ name: string;
448
+ description: string;
449
+ /** Context attribute mapping used by the gateway router (청구항 17-2), e.g. {jurisdiction: "KR"}. */
450
+ context: Record<string, string>;
451
+ owner: string;
452
+ patch_ids: string[];
453
+ /** The curation fee, set by the owner (finding 359). Absent = free to subscribe, as every track was before. */
454
+ terms?: SubscriptionTerms;
455
+ created_at: number;
456
+ /**
457
+ * `test` = a fixture track: hidden from /network, from `GET /api/branches` (unless `include_test`) and from the
458
+ * router, exactly as `PatchAnchor.visibility` already worked for anchors (item 269). The one page that sells
459
+ * "subscribe to a track" was 32 throwaway `e2e/*` rows and three real ones, and nothing could ever be taken off.
460
+ * Absent = `public`, so every track written before this field keeps reading as one.
461
+ */
462
+ visibility?: 'public' | 'test';
463
+ /** The owner is done with this track: kept on the record, hidden from the lists and never routed to (item 269). */
464
+ archived?: boolean;
465
+ }
466
+ export interface PeerInfo {
467
+ address: string;
468
+ public_key?: string;
469
+ name: string;
470
+ endpoint: string;
471
+ roles: NodeRole[];
472
+ ledger: 'local' | 'ain';
473
+ chain_id?: number;
474
+ model?: string;
475
+ branches: string[];
476
+ /**
477
+ * What this node has LOADED in its serving model right now, bottom first (item 234). `branches` records what a
478
+ * node once subscribed to; a router that sends traffic on that alone can pick a node serving the superseded bake,
479
+ * a rejected one, or nothing at all. Absent on records written before the field.
480
+ */
481
+ applied?: string[];
482
+ blobs: string[];
483
+ /** sha256 of published training sets held (sliced to 40, like `blobs`); a child node re-advertises the parent sets it fetched. */
484
+ datasets?: string[];
485
+ /** The build that is RUNNING (`VERSION` from the code), not the string config.json was written with. */
486
+ version: string;
487
+ /** When this node's binaries were last built/edited — the only honest answer to "which build is that?" (item 141). */
488
+ build?: string;
489
+ /** `version` of config.json: the schema version it was written by, kept for migrations. */
490
+ config_version?: string;
491
+ /**
492
+ * A per-START id, minted when the node process boots (item 139). Two endpoints presenting one ADDRESS is either a
493
+ * node that moved — same instance, new URL — or two nodes running on one identity, which silently breaks every
494
+ * download and attestation routed by address. Without this the two cases are indistinguishable.
495
+ */
496
+ instance?: string;
497
+ /**
498
+ * What this node offers the people who publish through it (item 307). The split a teacher is shown was the local
499
+ * operator's config value, take it or leave it, and there was no surface anywhere comparing what another node
500
+ * offers — the person contributing the data had no lever and no market. `teach` is the share of a sale this node
501
+ * pays the teacher; `royalty` and `verifier` are what its anchors promise ancestors and verifiers.
502
+ * Absent on a node that does not accept contributions, and on every record written before the field.
503
+ */
504
+ shares?: {
505
+ teach?: number;
506
+ royalty: number;
507
+ verifier: number;
508
+ };
509
+ /**
510
+ * The other half of this node's terms (item 368): how many independent attestations it requires before it calls
511
+ * anything verified, what it prices a knowledge at when the publisher names none, and whether it takes lessons
512
+ * from visitors at all. With `shares` and `ledger` this is everything a creator choosing where to publish, or a
513
+ * buyer wondering what their money splits into, has to compare — and none of it was published before.
514
+ * Absent on a node running an older build: a consumer must say "not published", never assume a default.
515
+ */
516
+ quorum?: number;
517
+ default_price?: string;
518
+ accepts_contributions?: boolean;
519
+ last_seen: number;
520
+ }
521
+ export type NodeRole = 'seller' | 'verifier' | 'serving' | 'gateway';
522
+ /** Generic signed ledger record (local-ledger mode). Content-addressed by `hash`. */
523
+ /** Every kind of record the ledger holds — the closed list `ainize ledger ls --kind` offers. */
524
+ export declare const RECORD_KINDS: readonly ["anchor", "attest", "settle", "challenge", "branch", "node", "supersede", "subscribe", "retire", "dispute", "price", "payout"];
525
+ export type RecordKind = (typeof RECORD_KINDS)[number];
526
+ export interface LedgerRecord<T = unknown> {
527
+ hash: string;
528
+ kind: RecordKind;
529
+ body: T;
530
+ author: string;
531
+ ts: number;
532
+ /** Hashes of records this one causally depends on (DAG). */
533
+ parents: string[];
534
+ sig: string;
535
+ }
536
+ /**
537
+ * One knowledge the buyer must ALSO hold for the quoted one to work (lineage design §12.5): an add-on trained on
538
+ * top of a base is useless without that base underneath, and its price is not part of the quoted price. Deepest
539
+ * ancestor first — the order they have to be loaded in.
540
+ */
541
+ export interface X402Required {
542
+ id: string;
543
+ name: string;
544
+ price: string;
545
+ currency: string;
546
+ author: string;
547
+ author_name?: string | null;
548
+ /** where that one is sold (its own anchor's gateway), when this node knows it */
549
+ gateway_url?: string | null;
550
+ /** how far below the quoted knowledge it sits (1 = its own base) */
551
+ depth: number;
552
+ /** false when the quoting node has never seen that anchor: its price is in no total and the buyer must find it */
553
+ known: boolean;
554
+ }
555
+ export interface X402Requirement {
556
+ scheme: 'ain-transfer' | 'local-credit';
557
+ network: string;
558
+ asset: string;
559
+ payTo: string;
560
+ maxAmountRequired: string;
561
+ resource: string;
562
+ description: string;
563
+ nonce: string;
564
+ expires_at: number;
565
+ /** For ain-transfer: the transfer key the payer must use so the seller can look up /transfer/$from/$to/$key. */
566
+ transfer_key?: string;
567
+ /** The bases this knowledge needs underneath it, deepest first — each one a separate purchase (finding 270). */
568
+ requires?: X402Required[];
569
+ /** `maxAmountRequired` + every `requires[]` price: what the whole family costs at list price. */
570
+ total?: string;
571
+ /** true when this body stands alone (no base stack, or a squash that carries its bases' rows). */
572
+ self_contained?: boolean;
573
+ /** The nonce is spent by the settlement that redeems it; a rejected attempt leaves it usable (finding 272). */
574
+ single_use?: boolean;
575
+ /**
576
+ * What is being sold, on the quote itself (finding 236). An x402 client is not an ainize node: it has the 402 and
577
+ * nothing else, so a script assembling a set from ids seen last week used to buy and stack retired versions with
578
+ * no way to know, and no agent could decide on lineage, licence or who is paid BEFORE paying.
579
+ *
580
+ * `status` is the seller's own catalogue status (`LISTED` | `SUPERSEDED`); `superseded_by` names the newer
581
+ * versions; `license` is the anchor's SPDX id; `lineage.standalone` is true when nothing is declared underneath;
582
+ * `split_preview` is the same `royaltyPlan` that will settle the sale, so the buyer sees the split before paying
583
+ * and can compare it with the one on the receipt afterwards.
584
+ */
585
+ status?: string;
586
+ superseded_by?: string[];
587
+ license?: string | null;
588
+ lineage?: {
589
+ parents: {
590
+ id: string;
591
+ author: string | null;
592
+ name: string | null;
593
+ }[];
594
+ standalone: boolean;
595
+ };
596
+ split_preview?: {
597
+ address: string;
598
+ name: string | null;
599
+ role: string;
600
+ amount: string;
601
+ }[];
602
+ }
603
+ export interface X402Payload {
604
+ scheme: 'ain-transfer' | 'local-credit';
605
+ network: string;
606
+ txHash: string;
607
+ from?: string;
608
+ to?: string;
609
+ amount?: string;
610
+ transfer_key?: string;
611
+ nonce?: string;
612
+ /** local-credit: HMAC proof issued by the facilitator. */
613
+ proof?: string;
614
+ }
615
+ /** Manifest returned as the gated x402 content (text) — verified via on-chain content_hash by ain-js. */
616
+ export interface PatchManifest {
617
+ id: string;
618
+ patch_sha256: string;
619
+ size_bytes: number;
620
+ rows: number;
621
+ model: ModelIdentity;
622
+ benchmark_hash: string;
623
+ /** Peers that advertise the blob. */
624
+ blob_urls: string[];
625
+ issued_to: string;
626
+ issued_at: number;
627
+ /** Bearer token for the blob endpoint, signed by the issuing node. */
628
+ download_token: string;
629
+ }
630
+ /**
631
+ * Sampling sent to the serving model on one generation path (D1 — runaway/degenerate answers).
632
+ * Every field is optional; an omitted field is simply not sent, so the server default applies.
633
+ * Measured on the shared e2e instance (PROBE A/B, 2026-09-01): a stop sequence is the only knob that
634
+ * lowered degeneration AND raised answer accuracy; repetition/frequency penalties left half the loops
635
+ * in place and made the model refuse legitimately repetitive questions, so they default to unset.
636
+ */
637
+ export interface SamplingOptions {
638
+ /** Stop sequences (vLLM `stop`). Chat default ["\n\n\n\n", "<think>"]; completion default ["\n\n", "<think>"]. */
639
+ stop?: string[];
640
+ /** Cap on generated tokens when the caller does not pass one. */
641
+ maxTokens?: number;
642
+ temperature?: number;
643
+ /** vLLM `repetition_penalty` (1 = off). Measured harmful at 1.1 — leave unset unless you re-measure. */
644
+ repetitionPenalty?: number;
645
+ /** vLLM `frequency_penalty` (0 = off). Lowers loops but costs correct answers. */
646
+ frequencyPenalty?: number;
647
+ /** vLLM `presence_penalty` (0 = off). */
648
+ presencePenalty?: number;
649
+ /** Post-generation degeneracy guard (repetition detector + truncation). Default on; `false` returns the raw text. */
650
+ guard?: boolean;
651
+ }
652
+ /** Per-path sampling. `verify` is deliberately absent: benchmark verification always generates on the pre-guard settings. */
653
+ export interface RuntimeSampling {
654
+ /** /v1/chat/completions — the path the web Live test uses. */
655
+ chat?: SamplingOptions;
656
+ /** /v1/completions — the operator's free-generation endpoint (verification and teach opt out explicitly). */
657
+ complete?: SamplingOptions;
658
+ }
659
+ export interface RuntimeStatus {
660
+ available: boolean;
661
+ api: string | null;
662
+ model: string | null;
663
+ hook: boolean;
664
+ repo: string | null;
665
+ applied: string[];
666
+ error?: string;
667
+ /** Raw upstream text of the last model-side failure (logs / diagnostics; `error` stays the friendly message). */
668
+ detail?: string;
669
+ }
670
+ export interface NodeConfig {
671
+ name: string;
672
+ dataDir: string;
673
+ port: number;
674
+ host: string;
675
+ publicUrl?: string;
676
+ roles: NodeRole[];
677
+ peers: string[];
678
+ ledger: {
679
+ kind: 'local' | 'ain';
680
+ ain?: {
681
+ providerUrl: string;
682
+ eventHandlerUrl?: string | null;
683
+ chainId: number;
684
+ appName: string;
685
+ };
686
+ };
687
+ identity: {
688
+ privateKey: string;
689
+ address: string;
690
+ publicKey: string;
691
+ };
692
+ operatorPasswordHash?: string;
693
+ runtime?: {
694
+ repo?: string;
695
+ api?: string;
696
+ hookApi?: string;
697
+ python?: string;
698
+ /** Patch-hook mailbox of the serving instance `api` points at (default <repo>/ple_patch). One directory per
699
+ * vLLM instance: it carries the apply/remove requests and the cross-process runtime lock, so two servers
700
+ * (e.g. the demo cluster on its own GPUs and a second instance) never write into each other's table. */
701
+ patchDir?: string;
702
+ /**
703
+ * Which GPUs the serving instance `api` addresses occupies, e.g. "4,5" (item 145). Nothing on the node can
704
+ * discover this — the model is behind an HTTP URL — and without it the teach trainer cannot be stopped from
705
+ * being pointed at the GPUs that serve every verification and live test. Unset = no cross-check is possible.
706
+ */
707
+ gpus?: string;
708
+ /** Sampling + degeneracy guard per generation path (D1). Omit for the measured defaults. */
709
+ sampling?: RuntimeSampling;
710
+ };
711
+ verifier?: {
712
+ quorum: number;
713
+ /**
714
+ * @deprecated Never escrowed. Kept so existing config.json files still validate; the node ignores it and
715
+ * neither attestations nor challenges carry it any more (item 127).
716
+ */
717
+ stake?: string;
718
+ /** false (the default): the author of an anchor cannot attest it — the write is refused and such records never count toward the quorum. */
719
+ allowSelfAttest: boolean;
720
+ intervalMs: number;
721
+ /** false = verify only on demand (`ainize patch verify` / POST /api/patches/:id/verify); no background rounds. Default true. */
722
+ auto?: boolean;
723
+ /**
724
+ * Stop attesting below this balance, on a chain that charges gas (item 341). An attestation is a write the
725
+ * VERIFIER signs and pays for, and `verifier.auto` would keep writing until the account was empty — at which
726
+ * point every other thing this node does on chain (announce, settle, payout) fails too. Ignored on the local
727
+ * ledger, which has no gas.
728
+ */
729
+ minBalance?: number;
730
+ /**
731
+ * Verify anchors published with `visibility: 'test'` (item 332). Default FALSE: on the demo chain 209 of 213
732
+ * anchors were hidden test listings nobody can buy, and every e2e run of every other workstream cost each
733
+ * verifier a download and a benchmark.
734
+ */
735
+ includeTest?: boolean;
736
+ /** Skip anchors priced below this (decimal string, item 332). Default '0' — verify everything, free items included. */
737
+ minPrice?: string;
738
+ /** At most this many items per rolling hour (item 332). Default 40; 0 disables background verification entirely. */
739
+ maxPerHour?: number;
740
+ /**
741
+ * Minutes of shared-model lock this node will spend verifying per rolling hour (items 332 / 333). Default 10 —
742
+ * node-b spent 54.9 min on one demo afternoon, all of it in front of its own visitors.
743
+ */
744
+ maxModelMinutesPerHour?: number;
745
+ /** Local-time window `{from: 'HH:MM', to: 'HH:MM'}` outside which no background verification starts (item 333). */
746
+ window?: {
747
+ from: string;
748
+ to: string;
749
+ } | null;
750
+ /**
751
+ * Keep a body after the attestation that needed it counted (item 336). Default FALSE: a verifier's disk grew to
752
+ * 932 MB of files it neither wrote nor bought. Bodies this node authored, bought or serves are never dropped.
753
+ */
754
+ retainBodies?: boolean;
755
+ };
756
+ market: {
757
+ currency: 'AIN' | 'CREDIT';
758
+ defaultPrice: string;
759
+ royaltyShare: number;
760
+ /**
761
+ * Share of the SELLER side of each sale paid to the verifiers whose attestations count for that knowledge
762
+ * (item 325). Written into every anchor this node creates and floored at NETWORK_MIN_VERIFIER_SHARE when it
763
+ * is read back, so a seller cannot publish knowledge that pays its verifiers nothing.
764
+ */
765
+ verifierShare?: number;
766
+ initialCredit: string;
767
+ /**
768
+ * How many addresses this node will ever hand `initialCredit` to (default 100). Local credit is issued by the
769
+ * node, not owned by the buyer: without a cap a fresh keypair is worth 100 CREDIT and any spend limit is one
770
+ * `ainize keys new` away (item 364). Every grant is recorded; past the cap a new address gets nothing.
771
+ */
772
+ creditGrants?: number;
773
+ };
774
+ /**
775
+ * What this node accepts from the gossip network (items 136/137). Peer exchange used to add every endpoint any
776
+ * peer advertised — no cap, no record of where it came from, no way to refuse — so an operator could not answer
777
+ * "who is my node talking to?" from config.json, and `peers rm` survived exactly one gossip round.
778
+ */
779
+ p2p?: {
780
+ /** Learn peers from peer exchange at all (default true). false = talk only to the configured list. */
781
+ acceptExchange?: boolean;
782
+ /** Ceiling on the peer table (default 50). Past it the least recently seen LEARNED peer is dropped. */
783
+ maxPeers?: number;
784
+ /** Drop a LEARNED peer after this many consecutive failed rounds (default 60; 0 = never). */
785
+ evictAfterFailures?: number;
786
+ /** Drop a LEARNED peer this many days after it was last seen (default 7; 0 = never). */
787
+ staleDays?: number;
788
+ };
789
+ /**
790
+ * HTTP server knobs. `trustProxy` is Express's `trust proxy` setting: `false` (default) → `req.ip` is the TCP peer, so a
791
+ * client cannot pick its own address with X-Forwarded-For (per-IP quotas, bans and rate limits key on `req.ip`).
792
+ * Behind a reverse proxy set it to the hop count (`1`), `'loopback'`, or the proxy's IP/CIDR list.
793
+ */
794
+ server?: {
795
+ trustProxy?: boolean | number | string | string[];
796
+ };
797
+ /**
798
+ * Retention of the node's own bookkeeping (item 128). `events.retentionDays` is how long raw rows of the `events`
799
+ * table are kept before the hourly purge removes them — the demand counters are materialised at write time, so
800
+ * nothing measured is lost with them. Default 90 days.
801
+ */
802
+ events?: {
803
+ retentionDays: number;
804
+ };
805
+ /** Teach mode (visitor-taught knowledge). Absent in configs written before teach mode → `teachConfig()` fills the defaults. */
806
+ teach?: TeachConfig;
807
+ gossipIntervalMs: number;
808
+ version: string;
809
+ /** Show anchors marked visibility:'test' (e2e suites) in this node's catalog. */
810
+ includeTestAnchors?: boolean;
811
+ }
812
+ /** Teach-mode policy and trainer settings (`config.json` → `teach`; defaults in `DEFAULT_TEACH_CONFIG`). */
813
+ export interface TeachConfig {
814
+ /** Master switch — every visitor teach route answers 403 `teaching_disabled` while false. */
815
+ enabled: boolean;
816
+ /** What happens when a visitor publishes: operator review (default), automatic announce, or never. */
817
+ publish: 'review' | 'auto' | 'never';
818
+ factsPerJob: number;
819
+ jobsPerKeyPerDay: number;
820
+ jobsPerIpPerDay: number;
821
+ queueMax: number;
822
+ /** Default `Contributor.share` frozen into the anchor at publish (fraction of the seller remainder after lineage). */
823
+ contributorShare: number;
824
+ /** Private READY drafts expire after this many days without save/publish. */
825
+ draftTtlDays: number;
826
+ /** 'gradient' runs train/teach.py in the trainer container; 'stub' copies a fixture npz (CI/e2e, no GPU). */
827
+ backend: 'gradient' | 'stub';
828
+ /**
829
+ * With `backend: 'stub'`: never touch the serving model — preflight answers and CHECKING are simulated
830
+ * (a prompt that already contains the answer counts as "already known"; `LOCALITY_FAIL` in a fact fails the locality gate).
831
+ * For CI / e2e nodes without a model server. Ignored for the gradient backend.
832
+ */
833
+ stubOffline?: boolean;
834
+ trainer: {
835
+ container: string;
836
+ script: string;
837
+ gpus: string;
838
+ maxSteps: number;
839
+ timeoutMs: number;
840
+ minFreeGpuMb: number;
841
+ idleStopMin: number;
842
+ };
843
+ /** Locality gate: fixed prompts whose greedy answers must stay identical for at least `minSame` of them. */
844
+ locality: {
845
+ prompts: string[];
846
+ minSame: number;
847
+ };
848
+ /** Teach mode v2 — uploaded/collected datasets (design §6.4). */
849
+ dataset: TeachDatasetLimits;
850
+ /** How many questions one lesson may train. Derived at runtime from measured gradient runs; these are the bounds. */
851
+ rowsPerJob: {
852
+ floorGradient: number;
853
+ floorStub: number;
854
+ ceiling: number;
855
+ safetyFactor: number;
856
+ };
857
+ /** The three effort presets. `lr` is fixed for all three — nobody has measured that changing it helps. */
858
+ effort: {
859
+ quick: TeachEffortPreset;
860
+ balanced: TeachEffortPreset;
861
+ thorough: TeachEffortPreset;
862
+ lr: number;
863
+ };
864
+ /** CHECKING budget — independent of dataset size, so a 1000-question lesson holds the runtime lock no longer than an 8-question one. */
865
+ check: {
866
+ callBudget: number;
867
+ sampleRows: number;
868
+ chatFormRows: number;
869
+ parentSamplesMax: number;
870
+ lockTargetMs: number;
871
+ lockAbortMs: number;
872
+ /**
873
+ * How long a lesson waits for a BUSY shared model before it is saved unchecked (item 244). A model OUTAGE has had
874
+ * a 15-minute grace since the beginning; a busy runtime was retried for ever, so a 3 a.m. bake could sit behind
875
+ * verification of its own yesterday's version with a terminal that said nothing. Default 30 min.
876
+ */
877
+ lockGraceMs: number;
878
+ };
879
+ /** Interactive preflight sampling. */
880
+ preflight: {
881
+ sampleRows: number;
882
+ perCall: number;
883
+ };
884
+ /** Total questions the queue may hold across all waiting lessons. */
885
+ queuedRowsMax: number;
886
+ /**
887
+ * Teaching keys this node does not ration (item 246): the daily lesson limit is meant to stop a stranger filling
888
+ * the GPU, and it locked the operator out of their OWN node after one failed bake and one retry — with no reset
889
+ * time anywhere. The node's own identity is always trusted; add the keys you teach with here.
890
+ */
891
+ trustedKeys?: string[];
892
+ /**
893
+ * Run the live side-effect check even when the trainer is the demo stub (item 247). Default false: a stub writes a
894
+ * PLACEHOLDER body, so the ~4.5 minutes of shared model the check costs measure nothing — the held lock is the only
895
+ * real thing about the run, and the lesson ends `NEEDS_MORE · taught 0/18` on a page that says nothing was trained.
896
+ * A test rig with a fake model server sets this, because the check path is what it asserts; a node pointed at a
897
+ * production vLLM should not.
898
+ */
899
+ checkStubLessons?: boolean;
900
+ /**
901
+ * Feature flag `teach.lineage` (lineage design §18): while false the node refuses `base_ids` on a teach job and the
902
+ * web hides "Build on this" / the basket base row / `--on`. Off until the runtime stack (L2) and the on-top trainer
903
+ * (L3) are verified end to end on the gradient backend; the dataset blob, its access levels and `dataset get` do
904
+ * not depend on it.
905
+ */
906
+ lineage?: boolean;
907
+ }
908
+ export interface TeachEffortPreset {
909
+ maxSteps: number;
910
+ evalEvery: number;
911
+ }
912
+ export interface TeachDatasetLimits {
913
+ /** Upload byte cap (operator ceiling 20 MB); the QUESTION cap must always bite first so the message is readable. */
914
+ maxBytes: number;
915
+ /** Parse ceiling — beyond this the parser stops and says so. */
916
+ maxSourceLines: number;
917
+ /** Accepted questions stored per dataset. */
918
+ maxRows: number;
919
+ /** New datasets per teaching key per day. */
920
+ perKeyPerDay: number;
921
+ /** Datasets retained per key. */
922
+ keptPerKey: number;
923
+ /** Questions TRAINED per key per day. */
924
+ rowsPerKeyPerDay: number;
925
+ rowsPerIpPerDay: number;
926
+ bytesPerKeyPerDay: number;
927
+ /** `ready` datasets are swept this many days after their last job finished. */
928
+ ttlDays: number;
929
+ /** `staged` datasets never used by a job are swept after this many hours. */
930
+ stagedTtlHours: number;
931
+ /** In-memory per-IP create limiter (like `policyHits`). */
932
+ createsPerIpPerMin: number;
933
+ /** Above this many questions, publishing needs a rights/PII declaration. */
934
+ declarationRows: number;
935
+ }
936
+ /** How a dataset came to exist. `derived` = materialised from a v1 job's inline facts; `sample` = a node-shipped example. */
937
+ export type TeachDatasetSource = 'chat' | 'upload' | 'derived' | 'sample';
938
+ /** `staged` = parsed, never trained; `ready` = usable; `in_use` = a job is running against it; `deleted` = tombstone. */
939
+ export type TeachDatasetStatus = 'staged' | 'ready' | 'in_use' | 'deleted';
940
+ /**
941
+ * The durable artifact the whole v2 teach UI is organised around: one canonical `rows.jsonl` on the node, owned by a
942
+ * teaching key, hashed, versioned, and re-trainable. Both doors (chat basket / file upload) produce one of these.
943
+ */
944
+ export interface TeachDataset {
945
+ id: string;
946
+ owner_address: string;
947
+ name: string;
948
+ status: TeachDatasetStatus;
949
+ source: TeachDatasetSource;
950
+ sha256: string;
951
+ revision: number;
952
+ rows: number;
953
+ invalid_rows: number;
954
+ size_bytes: number;
955
+ source_bytes?: number;
956
+ source_name?: string;
957
+ format?: TeachDatasetFormat;
958
+ encoding?: string;
959
+ layout?: string;
960
+ delimiter?: string;
961
+ has_header?: boolean;
962
+ columns?: Record<string, string | number>;
963
+ summary: TeachDatasetSummary;
964
+ parent_dataset?: string;
965
+ /** Lineage (design §5.3): the published KNOWLEDGE this set was copied out of, its set's sha, and how many rows are still its. */
966
+ parent_patch?: string;
967
+ parent_dataset_sha?: string;
968
+ inherited_rows?: number;
969
+ retention: 'keep' | 'delete_after_training';
970
+ job_ids: string[];
971
+ created_at: number;
972
+ updated_at: number;
973
+ expires_at?: number;
974
+ deleted_at?: number;
975
+ }
976
+ export type TeachDatasetFormat = 'jsonl' | 'json' | 'csv' | 'tsv' | 'txt';
977
+ /** Counts over the SOURCE rows — nothing is silently dropped, so every rejection has a bucket here. */
978
+ export interface TeachDatasetSummary {
979
+ source_rows: number;
980
+ accepted: number;
981
+ fixed: number;
982
+ rejected: number;
983
+ duplicates: number;
984
+ conflicts: number;
985
+ blocked: number;
986
+ too_long: number;
987
+ empty: number;
988
+ not_parsed: number;
989
+ /** Accepted questions past `dataset.maxRows` — counted, never silently truncated. */
990
+ over_cap: number;
991
+ /** Advisory only (design §8.5): accepted questions that share their last three tokens with ≥ 2 others. */
992
+ shared_ending: number;
993
+ /**
994
+ * Accepted questions that look like personal information (an e-mail, a phone number, a resident registration number,
995
+ * a card number that passes Luhn). They train, and they block publishing the training set above `private`
996
+ * (lineage design §6.5). Absent in reports written before the check existed.
997
+ */
998
+ pii?: number;
999
+ langs: Record<TeachDatasetLang, number>;
1000
+ /**
1001
+ * How many report entries were carried over from an earlier revision (rows refused when the file was read that the
1002
+ * last edit did not resolve). They are already counted in `rejected` and in their own bucket; this says how many of
1003
+ * those numbers are about the original file rather than the current bytes. Absent before the carry rule existed.
1004
+ */
1005
+ carried?: number;
1006
+ }
1007
+ export type TeachDatasetLang = 'hangul' | 'latin' | 'han' | 'kana' | 'other';
1008
+ /**
1009
+ * Per-source-row status. `ok`, `fixed` and `pii` enter rows.jsonl (a `pii` row trains, but keeps the training set
1010
+ * from being published above `private` until it is removed); `over_cap` is an accepted question that did not fit
1011
+ * this node's per-dataset cap.
1012
+ */
1013
+ export type TeachRowStatus = 'ok' | 'fixed' | 'pii' | 'duplicate' | 'conflict' | 'too_long' | 'empty' | 'blocked' | 'not_parsed' | 'over_cap';
1014
+ /** Kinds of personal information the parser looks for (lineage design §6.5). */
1015
+ export type TeachPiiKind = 'email' | 'phone' | 'rrn' | 'card';
1016
+ /** Row statuses that mean "this question is in rows.jsonl" (the helper every filter should use instead of listing the two or three by hand). */
1017
+ export declare const ACCEPTED_ROW_STATUSES: readonly TeachRowStatus[];
1018
+ export declare const isAcceptedRowStatus: (s: string | undefined) => boolean;
1019
+ /** One entry per SOURCE row — accepted or not. `index` is the position in rows.jsonl, null when the row was not accepted. */
1020
+ export interface TeachDatasetRow {
1021
+ index: number | null;
1022
+ /** 1-based LOGICAL source row (a quoted CSV newline is one row, not two). */
1023
+ line: number;
1024
+ status: TeachRowStatus;
1025
+ prompt?: string;
1026
+ answer?: string;
1027
+ alt_prompt?: string;
1028
+ note?: string;
1029
+ /** 'answer_flattened' | 'whitespace_collapsed' | 'controls_stripped' | 'qa_prefix_stripped' | 'note_truncated' */
1030
+ fixes?: string[];
1031
+ /** Never blocks training. */
1032
+ advisory?: 'shared_ending'[];
1033
+ /** Only with `status: 'pii'` — what was found (the row still trains; it blocks publishing above `private`). */
1034
+ pii?: TeachPiiKind[];
1035
+ /**
1036
+ * Provenance of an inherited question (lineage design §5.2): `from = '<parent knowledge>#<row index>'` on a row
1037
+ * copied unchanged from the training set this one was forked from, `replaces` on a row whose answer was changed.
1038
+ * The rows table renders them as the *from {name}* chip and the Mine / Inherited / Changed filters.
1039
+ */
1040
+ from?: string;
1041
+ replaces?: string;
1042
+ /** e.g. 'conflicts with line 41', 'answer is 240 characters (40 over the 200 limit)' */
1043
+ detail?: string;
1044
+ /**
1045
+ * A refused row CARRIED FORWARD from an earlier revision of this dataset (design §11). An edit rewrites the set from
1046
+ * its accepted rows, so a row the parser refused when the file was read is not in the new bytes; it is kept in the
1047
+ * report anyway, because "nothing is silently dropped" has to hold across revisions too. `line` is still its line in
1048
+ * the file that was uploaded — never a position in the current set — which is why the table labels it differently.
1049
+ */
1050
+ carried?: true;
1051
+ /** ≤ 200 chars, only for not_parsed. */
1052
+ raw?: string;
1053
+ lang?: TeachDatasetLang;
1054
+ }
1055
+ /** What a job records about its input (`job.dataset`). A v1 job renders with `id: null` and `source: 'derived'`. */
1056
+ export interface TeachDatasetRef {
1057
+ id: string | null;
1058
+ sha256: string | null;
1059
+ revision?: number;
1060
+ rows: number;
1061
+ source: TeachDatasetSource;
1062
+ name?: string;
1063
+ trained_rows: number;
1064
+ selected_indexes?: number[];
1065
+ /** Live-model check coverage when the dataset was too big to check whole. */
1066
+ sampled?: {
1067
+ checked: number;
1068
+ of: number;
1069
+ };
1070
+ deleted?: true;
1071
+ }
1072
+ /** Effort preset a job was trained with (design §D6: presets change `max_steps` and nothing else the visitor can see). */
1073
+ export type TeachEffort = 'quick' | 'balanced' | 'thorough';
1074
+ export interface TeachTrainingSpec {
1075
+ effort: TeachEffort;
1076
+ max_steps: number;
1077
+ eval_every: number;
1078
+ lr: number;
1079
+ rows_limit?: number;
1080
+ row_offset?: number;
1081
+ check_side_effects: boolean;
1082
+ use_alt: boolean;
1083
+ /** Positions in the dataset this lesson trained, in order: `job.facts[i]` is `dataset.rows[selected_indexes[i]]`. */
1084
+ selected_indexes?: number[];
1085
+ }
1086
+ /**
1087
+ * Are these the same address?
1088
+ *
1089
+ * An AIN/Ethereum address is checksummed — the same address is written `0xAbC…` in one record and `0xabc…` in
1090
+ * another, and `===` between the two forms is false. Comparisons of this kind were spread across the node, the
1091
+ * catalogue and the verifier as three private copies plus a scattering of raw `===`, which is how a verifier
1092
+ * ended up unable to recognise its own earlier attestation. One definition, and it lives here because `types.ts`
1093
+ * imports nothing and so is reachable from a browser bundle too.
1094
+ */
1095
+ export declare const sameAddr: (a: string | undefined | null, b: string | undefined | null) => boolean;
1096
+ //# sourceMappingURL=types.d.ts.map