/** * @copyright Sister Software * @license AGPL-3.0 * @author Teffen Ellis, et al. * * End-to-end corpus build (Phase 1 task #10 in the plan). * * `buildCorpus(opts)` orchestrates every stage of the pipeline: * * 1. **Adapter runs** — drives every adapter in turn (via `runAdapter`), writing * `//canonical.jsonl` shards. * 2. **Synthesis** — optional. For each canonical row, every applicable augmentation in the row's * country-default policy emits an augmented row alongside the original. * 3. **Alignment** — every row (original + augmented) is aligned via `alignRow`. Successes go to * `labeled.jsonl`; quarantines are appended to `quarantine.jsonl` with reasons. * 4. **Splits** — `splitRows` partitions labeled `source_id`s into train/val/test by locality holdout. * Manifest written to `splits/SPLIT_MANIFEST.json` + per-split `train.txt` / `val.txt` / * `test.txt`. * 5. **Parquet shards** — `writeShards` streams labeled rows into 1M-row `.parquet` shards per split * under `corpus-v/{train,val,test}/part-NNNN.parquet` (SNAPPY-compressed, 50k-row * row groups), with per-shard checksums + per-stage manifest in * `corpus-v/MANIFEST.json`. * 6. **Top-level manifest** — `/MANIFEST.json` ties every per-stage manifest together with * a top-level corpus_version, built_at, and aggregate counts. * * Output layout: * * ``` * / * MANIFEST.json * intermediate/ * /canonical.jsonl # one per adapter * labeled.jsonl # post-alignment, pre-shard * quarantine.jsonl # rows that failed alignment * splits/ * SPLIT_MANIFEST.json * train.txt / val.txt / test.txt * corpus-v/ * MANIFEST.json * train/part-NNNN.parquet * val/part-NNNN.parquet * test/part-NNNN.parquet * ``` * * The intermediate files live alongside the final shards for reproducibility + debugging. Operators * can `rm -rf intermediate/` after the build if disk is tight; the final `corpus-v/` is * self-contained. */ import { type AdapterRunManifest } from "@mailwoman/corpus/runner"; import type { AdapterOptions, CorpusAdapter } from "@mailwoman/corpus/types"; import { type ShardManifest, type SplitManifest } from "@mailwoman/corpus/utils"; /** * Stage tags surfaced to `onProgress`. */ export type BuildStage = "adapter-run" | "align" | "split" | "shard" | "manifest"; /** * Per-invocation options for `buildCorpus`. */ export interface BuildCorpusOptions { /** * Root output directory. All build artifacts land beneath it. */ outputDir: string; /** * Corpus version (e.g. `"0.1.0"`). Stamped onto every row + into the output dir name. */ corpusVersion: string; /** * Adapters to drive, in order. Defaults to `defaultAdapterRegistry.list()`. Pass an explicit list to filter (e.g. * `[wofAdminAdapter]` for a smoke run). */ adapters?: readonly CorpusAdapter[]; /** * Per-adapter `AdapterOptions` — looked up by adapter id. Adapters whose id is missing from this map are skipped (and * noted in the manifest). */ adapterInputs: Record; /** * Enable synthesis pass. Default `true`. Set `false` for fixture-driven smoke tests. */ synthesize?: boolean; /** * Forwarded to `writeShards`. Default 1_000_000. */ rowsPerShard?: number; /** * Progress hook. Errors thrown abort the build. */ onProgress?: (stage: BuildStage, message: string) => void; /** * License kinds to PURPOSELY exclude from this build (#26). Compiled patterns (see `compileLicenseExcludes` / * `SHARE_ALIKE_PATTERN` in `license.ts`); a row whose `license` matches any is dropped at ingest. Default (omitted) * includes EVERYTHING — exclusion is a deliberate act, not a silent default. A proprietary-weights build passes the * share-alike set (`--exclude-share-alike`). */ excludeLicenses?: readonly RegExp[]; } /** * Top-level manifest tying every stage together. */ export interface BuildCorpusManifest { corpus_version: string; built_at: string; adapters: AdapterRunManifest[]; skipped_adapters: string[]; splits: { counts: SplitManifest["counts"]; holdouts: SplitManifest["holdouts"]; }; shards: { counts: ShardManifest["counts"]; total_rows: number; }; quarantine_count: number; total_aligned_rows: number; /** * Resolved license set across all INCLUDED rows (license string → row count), + the count dropped by * `excludeLicenses` (#26). The model card derives its data-attribution table from `licenses`. */ licenses: Record; excluded_by_license: number; } /** * Drive the full corpus build to completion. * * Memory profile: the function maintains an in-memory `Map` to bridge the align → shard hand-off. * For Phase 1 fixture-scale runs (≤ 10⁴ rows) this is trivial. For real 5M+ runs, the map fits comfortably in a few * hundred MB; the canonical.jsonl and labeled.jsonl payloads stream and never sit in memory. */ export declare function buildCorpus(opts: BuildCorpusOptions): Promise; //# sourceMappingURL=build.d.ts.map