Skip to content
Merged
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

All notable changes to this project are documented in this file.

## Unreleased

### Documentation
- **`README.md` no longer presents a scalar `source.url` where the live schema requires a list, and its documentation index now includes the shipped Fullmap, Development, and Changelog pages.** The quick-start configuration uses the valid list form, and the navigation links now cover the corresponding site surfaces.
- **`docs/installation.md` no longer omits the `distill` extra or blur the distinction between recording and exporting distillation data.** The extras table and preflight guidance now document `distill`, while `agent --distill` is identified as zero-additional-dependency recording and `distill-export` as the step requiring the extra.
- **`docs/configuration/table.md` no longer omits the `exclude_prefixes` and `exclude_regex` resolution filters.** Their exact, case-sensitive matching, regex constraints, and unresolved-row behavior are now documented for subject, object, and qualifiers.
- **`docs/api/fullmap.md` no longer omits the `exclude_prefixes` and `exclude_regex` parameters or their position in resolution.** The signatures, filtering semantics, and examples now match the live `resolve()` API.
- **`docs/api/qc.md` no longer omits `fullmap_audit()`'s phase callback.** The `on_phase` signature, emitted phase labels, and build-progress use are now documented.
- **`docs/api/lib.md` no longer implies that `resolve_many()` exposes the full resolution context.** Its comparison now names `exclude_prefixes` and `exclude_regex` among the parameters unavailable to the convenience API.
- **`docs/api/utils.md` no longer calls the whole log directory a loguru sink.** It now distinguishes `log.LOGASSERT` and `.tablassert/log/` from the loguru sink file stored within that directory.
- **`llms.txt` no longer carries stale extras, CLI, graph-field, module, workflow, or documentation indexes.** Its entries now enumerate the live commands and optional extras, current implementation surface, MkDocs pages, and the root `CHANGELOG.md` pointer.
- **`docs/agent.md` no longer describes lower-bound dependencies as exact pins or omits the latest agent flags.** The dependency tables now quote the live requirements, and the compact reminder includes `--distill` and `--task-model` while keeping `docs/cli.md#agent` authoritative.
- **`CONTRIBUTING.md` no longer describes stale test counts, CI sharding, hook-install behavior, or an incomplete project layout.** Its quality gates, pre-commit instructions, CI dependency set, and layout now match the live configuration and workflows.
- **`docs/index.md` no longer omits shipped navigation surfaces.** The landing-page list now includes Fullmap, Agent, Development, and Changelog alongside the existing sections.
- **`tests/test_docs_source_of_truth.py` now guards the corrected documentation against drift.** It derives checks from the live schemas, CLI, optional extras, source modules, workflows, MkDocs navigation, and contributor tooling instead of allowing the same mismatches to return silently.
- **The documentation pass deliberately leaves two follow-ups rather than claiming them fixed.** The dead `errors.DOCS_URL` target and the still-undocumented coded error messages require separate remediation.
## 17.0.1 - 2026-09-09

### Fixed
Expand Down
13 changes: 8 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ src/tablassert/ Python package and CLI
rust/src/ PyO3 Rust extension exposed as tablassert.rs
tests/ Python tests and fixtures
docs/ MkDocs site
examples/ Runnable examples (autonomous agent walkthrough)
.github/ CI and docs workflows, issue and PR templates
Makefile Local task runner mirroring the stable commands
mkdocs.yml Documentation navigation and theme settings
pyproject.toml Python metadata, dependencies, pytest/ruff settings
rust/Cargo.toml Rust crate metadata and dependencies
Expand Down Expand Up @@ -100,16 +103,16 @@ What the gates cover:

- **Ruff linting and formatting.** The current tree enforces core pycodestyle/pyflakes safety checks plus stale-suppression detection. It also enforces an expanded rule set covering common bug patterns (bugbear), simplifications, Python-version upgrades, pytest style, import order, and comprehensions. Treat `uv run ruff check .` and `uv run ruff format --check .` as the stable interface rather than relying on individual rule codes.
- **Pyright.** Type checking runs through `uv run pyright`; the project is tightening this as a strict-inference ratchet over time.
- **Python tests.** The suite is offline and runs in parallel by default via [pytest-xdist](https://pypi.org/project/pytest-xdist/) (`-n auto` in `pyproject.toml`): over 600 tests in ~20-30 seconds, reporting around 90% coverage in the default CI environment (`--extra qc`). Disable parallelism for a single serial run with `pytest -n 0`. CI runs the suite as a single job rather than sharding it across runners: roughly 21 of every 36 seconds is fixed overhead (interpreter start, imports, xdist worker spin-up, coverage init) rather than test execution, so splitting the suite costs more in per-runner setup than it recovers.
- **Rust tests.** `cargo test --manifest-path rust/Cargo.toml` currently runs 46 Rust unit tests for the extension.
- **Python tests.** The suite is offline and runs in parallel by default via [pytest-xdist](https://pypi.org/project/pytest-xdist/) (`-n auto` in `pyproject.toml`'s addopts, which also enable `--cov` so coverage is reported inline); expect roughly 20-30 seconds for a full local run. Disable parallelism for a single serial run with `pytest -n 0`. CI installs the `ci` dependency group with the `qc` and `log` extras (`--no-default-groups --group ci --extra qc --extra log`) and runs the suite as a single job rather than sharding it across a matrix of runners: most of a run is fixed overhead (interpreter start, imports, xdist worker spin-up, coverage init) rather than test execution, so splitting the suite would cost more in per-runner setup than it recovers.
- **Rust tests.** `cargo test --manifest-path rust/Cargo.toml` runs the extension's Rust unit tests.
- **Rust style and lints.** `cargo fmt --check` enforces formatting; clippy runs all targets with warnings denied.

## Pre-commit hooks

Install hooks after setup. The `--install-hooks` flag matters: the config registers a **pre-push** stage as well as pre-commit, and without it only the pre-commit hooks are wired up.
Install hooks after setup. A bare `pre-commit install` wires up both stages: the config declares `default_install_hook_types: [pre-commit, pre-push]`, so no `--hook-type` flags are needed.

```bash
uv run pre-commit install --install-hooks
uv run pre-commit install
```

Hooks are split across two stages so that committing stays cheap while the checks that most often break CI still run before anything leaves your machine.
Expand All @@ -128,7 +131,7 @@ On every **push**, the whole-repo gates:

The ruff hooks cover the **whole tree**, matching CI's `ruff check .`. They used to be scoped to `src/` and `tests/`, which meant `examples/` could only ever fail in CI.

The full pytest suite and `cargo test` are deliberately in neither stage; they rebuild the Rust extension, and CI shards them across four runners far faster than a local serial run. Use `make check` when you want everything locally.
The full pytest suite and `cargo test` are deliberately in neither stage: they rebuild the Rust extension, which is too slow and too stateful for a commit/push hook, and CI already runs them on every pull request -- the Python suite as a single job, deliberately not sharded across a matrix. Use `make check` when you want everything locally.

## Running subsets

Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ template:
source:
kind: text
local: ./gene-disease.csv
url: https://example.com/data.csv
url: [https://example.com/data.csv]
row_slice: [1, auto]
delimiter: ","
statement:
Expand Down Expand Up @@ -119,8 +119,9 @@ CSV/TSV/Excel sources; optional extras add runtime and pipeline capabilities:
| `rt` | CPU-compatible Polars runtime | `pip install "tablassert[rt]"` |
| `aria2` | bundled aria2c downloader for `build-fullmap --aria2c` (Linux/Windows wheels only) | `pip install "tablassert[aria2]"` |
| `qc` | four-stage QC audit (exact → fuzzy → abbreviation → SapBERT embeddings) | `pip install "tablassert[qc]"` |
| `agent` | autonomous agent (smolagents, litellm, PDF context) | `pip install "tablassert[agent]"` |
| `agent` | autonomous agent (smolagents, litellm, article/table context) | `pip install "tablassert[agent]"` |
| `optimize` | GEPA prompt optimization for `agent --optimize` (dspy) | `pip install "tablassert[optimize]"` |
| `distill` | distillation dataset export (`tablassert distill-export`, HF `datasets`) | `pip install "tablassert[distill]"` |
| `log` | loguru-backed file/progress logging (rotation, enqueue) | `pip install "tablassert[log]"` |

QC is opt-in at build time (`build-kg --qc`). Reaching a feature whose extra is not installed never
Expand Down Expand Up @@ -156,9 +157,12 @@ no LazyFrame setup or NLP preprocessing required. See the
- **[Tutorial](https://skyeav.github.io/Tablassert/tutorial/)**: step-by-step example with synthetic data
- **[CLI Reference](https://skyeav.github.io/Tablassert/cli/)**: complete command-line flag reference
- **[Use Case Gallery](https://skyeav.github.io/Tablassert/examples/)**: real-world configuration patterns
- **[Fullmap](https://skyeav.github.io/Tablassert/fullmap/)**: building and querying the entity-resolution database
- **[Configuration](https://skyeav.github.io/Tablassert/configuration/graph/)**: graph and table configuration reference
- **[Agent](https://skyeav.github.io/Tablassert/agent/)**: the autonomous agent pipeline
- **[API Reference](https://skyeav.github.io/Tablassert/api/fullmap/)**: core functions documentation
- **[Development](https://skyeav.github.io/Tablassert/development/)**: dev environment setup and contributor workflow
- **[Changelog](https://skyeav.github.io/Tablassert/changelog/)**: release history

## Developing

Expand Down
18 changes: 9 additions & 9 deletions docs/agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ pip install "tablassert[agent]"
pip install "tablassert[agent,optimize]"
```

The extra pins:
The extra requires (lower bounds, so any newer version satisfies it):

| Package | Version | Role |
| Package | Requirement | Role |
| --- | --- | --- |
| `smolagents` | `==1.26.0` | `CodeAgent` ReAct loop, `OpenAIModel`/`LiteLLMModel`, tools |
| `litellm` | (any) | optional fallback / rate-limiting model backend |
| `smolagents` | `smolagents>=1.26.0` | `CodeAgent` ReAct loop, `OpenAIModel`/`LiteLLMModel`, tools |
| `litellm` | `litellm>=1.93.0` | optional fallback / rate-limiting model backend |

The `[optimize]` extra (only needed for `agent --optimize`) pins:
The `[optimize]` extra (only needed for `agent --optimize`) requires (a lower bound):

| Package | Version | Role |
| Package | Requirement | Role |
| --- | --- | --- |
| `dspy` | `==3.2.1` | `dspy.GEPA` black-box prompt optimization |
| `dspy` | `dspy>=3.2.1` | `dspy.GEPA` black-box prompt optimization |

## PMC-AWS data source

Expand Down Expand Up @@ -148,8 +148,8 @@ tablassert agent PMC11708054 PMC12345678 \
The required target is `--configuration-file`/`-f`; it supplies the fullmap, graph identity, RIG,
artifact metadata, and existing table list. Flags: `--max-steps`/`-ms`, `--min-rows`/`-mr`,
`--map-threshold`/`-mt`, `--max-improve-iters`/`-mi`, `--state-dir`/`-sd`, `--backend {openai,litellm}`/`-b`, plus `--local`/`-l`, `--reflexion`,
`--judge-model`, `--judge-threshold`, `--biolink-threshold`, and the `--optimize`/`-o` prompt-optimization flags
(`--instructions-file`, `--instructions-out`, `--max-metric-calls`, `--dataset`).
`--judge-model`, `--judge-threshold`, `--biolink-threshold`, the `--distill`/`-d`/`-dt` recording flag, and the `--optimize`/`-o` prompt-optimization flags
(`--instructions-file`, `--instructions-out`, `--max-metric-calls`, `--dataset`, `--task-model`).
The [CLI reference: `agent`](cli.md#agent) is the authoritative flag table; the list here is a compact
reminder.

Expand Down
20 changes: 18 additions & 2 deletions docs/api/fullmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def resolve(
taxon: Optional[str] = None,
prioritize: Optional[list[Categories]] = None,
avoid: Optional[list[Categories]] = None,
exclude_prefixes: Optional[list[str]] = None,
exclude_regex: Optional[list[str]] = None,
log: bool = True,
section_hash: Optional[str] = None,
config_file: Optional[str] = None,
Expand Down Expand Up @@ -56,6 +58,18 @@ Optional list of Biolink categories to exclude from results.

Example: `[Categories.GENE]` prevents gene mappings.

**`exclude_prefixes: Optional[list[str]]`**

Optional list of CURIE namespace prefixes to drop from the results, mirroring the `NodeEncoding.exclude_prefixes` config field. A prefix is the text before the first `:` of a resolved CURIE (e.g., `"OMIM"` for `"OMIM:100100"`); every candidate whose prefix is listed is dropped. Matching is exact and case-sensitive.

Example: `["OMIM", "MONDO"]` drops all OMIM- and MONDO-namespaced candidates.

**`exclude_regex: Optional[list[str]]`**

Optional list of case-sensitive regex patterns (Polars/Rust dialect), mirroring the `NodeEncoding.exclude_regex` config field; any resolved CURIE matching one of the patterns is dropped. An empty or whitespace-only pattern is rejected at config-validation time because it would match every CURIE.

Example: `["^CHEBI:"]` drops all CHEBI candidates.

**`log: bool` (default: `True`)**

Controls unmatched-value logging. When enabled, unresolved terms are logged with section/config/column context.
Expand Down Expand Up @@ -105,8 +119,10 @@ The function:
- Category frequency (if `column_context=True`)

3. **Filters by:**
- Taxon ID (if specified)
- Category avoidance (if specified)
- Taxon ID (if `taxon` specified)
- Category avoidance (if `avoid` specified)
- Excluded CURIE prefixes (if `exclude_prefixes` specified)
- Excluded CURIE regex patterns (if `exclude_regex` specified)

4. **Retains the best ranking tier** per input string: duplicate rows for the same CURIE collapse, while distinct CURIEs tied across every ranking heuristic are returned as separate rows

Expand Down
2 changes: 1 addition & 1 deletion docs/api/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ for row in result:
| **Path resolution** | Resolved internally via `fullmap_db_path()` | Caller must pass the resolved redb path |
| **Output** | `list[dict[str, Any]]` | `pl.LazyFrame` |
| **Logging** | Uses default (`log=True`) | Configurable |
| **Context params** | `column_context` exposed; `section_hash`, `config_file`, `tag` not exposed | Fully configurable |
| **Context params** | `column_context` exposed; `section_hash`, `config_file`, `tag`, `exclude_prefixes`, `exclude_regex` not exposed | Fully configurable |
| **Use case** | Standalone batch lookups, scripting, notebooks | Internal pipeline integration |

`resolve_many()` is designed for ad-hoc and programmatic use: scripts, notebooks, and one-off lookups. For pipeline integration where you need full control over logging, context metadata, and lazy evaluation, use `resolve()` directly.
Expand Down
5 changes: 5 additions & 0 deletions docs/api/qc.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def fullmap_audit(
config_file: str,
out: str = "passed",
log: bool = True,
on_phase: Optional[Callable[[str], None]] = None,
) -> pl.LazyFrame
```

Expand Down Expand Up @@ -53,6 +54,10 @@ Rows with `out=True` passed QC, `out=False` failed.

Controls whether failed QC rows are logged.

**`on_phase: Optional[Callable[[str], None]]`**

Optional callback fired at the start of each QC cascade stage with exactly one of the phase labels `qc:exact`, `qc:fuzzy`, `qc:abbrev`, or `qc:sapbert` (`qc:abbrev` fires only when Stage 3 runs, and `qc:sapbert` only when Stage 4 does). `build-kg` passes one to drive per-section QC progress; `None` disables phase reporting.

**`section_hash: str` / `config_file: str`**

Context fields used in QC failure logs for traceability.
Expand Down
2 changes: 1 addition & 1 deletion docs/api/utils.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The single parent working directory. All runtime artifacts live beneath it.

Intermediate parquet storage for compiled subgraphs (`.tablassert/store/`). Created on import.

The loguru sink (`.tablassert/log/tablassert.log`, `log.LOGASSERT`) and the cached SapBERT model (`.tablassert/sapbert/`, `qc.MODEL`) are likewise derived from `BASE`.
The log directory (`log.LOGASSERT`, `.tablassert/log/`) holding the loguru sink file `.tablassert/log/tablassert.log`, and the cached SapBERT model (`.tablassert/sapbert/`, `qc.MODEL`) are likewise derived from `BASE`.

## mkhash()

Expand Down
Loading
Loading