Skip to main content

TNC

TNC is a command-line tool for turning saved news articles into traceable source spans and extracting source-attributed assertions from them. It also includes tools for comparing source relationships and for gated historical replay. It is intended for researchers and fact-checkers working with saved news archives.

TNC does not decide whether a news claim is true. It also does not automatically determine that two publishers are independent sources.

Install

TNC is published on PyPI as tnc-provenance. (The name tnc on PyPI belongs to an unrelated project; pip install tnc installs that project, not this one.)

Windows (PowerShell):

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install tnc-provenance

Linux / macOS:

python -m venv .venv
.venv/bin/pip install tnc-provenance

With uv (any platform), if you already use uv:

uv venv
uv pip install tnc-provenance

The venv examples above are the recommended pattern on Windows because pip places tncprov.exe in a Scripts directory that is not on PATH by default. Calling the installed executable through the venv path always works. If your environment is already managed — Conda, a system Python with a configured PATH, an activated venv — a plain pip install tnc-provenance will work there too.

Command name

The package installs two identical console commands: tnc and tncprov.

On Windows PowerShell, use tncprov. PowerShell's NetTCPIP module defines tnc as an alias for Test-NetConnection, and PowerShell resolves aliases before executables on PATH. Bare tnc in PowerShell runs the networking cmdlet, not TNC. tncprov has no collision on any platform.

On Linux, macOS, cmd.exe, and any shell without a tnc alias, either command works.

See it work

The included example article first reports three injuries and later updates that number to five.

Windows:

.\.venv\Scripts\tncprov.exe assertions tests\fixtures\article_v1.html

Linux / macOS:

.venv/bin/tncprov assertions tests/fixtures/article_v1.html

Output:

Admitted: 2
  Officials said three people were injured.
    Source spans: 2
  Officials said five people were injured.
    Source spans: 6
Rejected: 0

Each number after Source spans: is a zero-based source-span ordinal. If an assertion references multiple spans, their ordinals are comma-separated; the field is not a count.

This preserves both the earlier statement and the later update rather than collapsing them into one claim.

What TNC does

TNC currently provides three main workflows:

  • Parse saved article HTML into traceable source spans. Structural types include headings, paragraphs, quotes, corrections, update notices, list items, table cells, and captions.
  • Extract supported assertions from those spans. Assertions are admitted only when their source coordinates and verbatim support validate.
  • Run gated historical replay. Archived evidence can be evaluated against capture time, review state, and replay policy before a historical snapshot is released.

The first two workflows operate directly on local HTML files. Historical replay has a stricter trust model and is described separately below.

Using your own article

Pass a local file path:

.\.venv\Scripts\tncprov.exe parse "C:\path\to\saved article.html"
.\.venv\Scripts\tncprov.exe assertions "C:\path\to\saved article.html"

The input must be a local UTF-8 HTML file using a supported article structure. URLs, PDFs, screenshots, and plain-text files are not inputs to these commands. The examples in this README require no API key or article download.

For local parse and assertions runs, TNC records the parsing time as an observation time. That does not establish when the article was first published or historically available.

Source spans

A source span is an ordered, immutable piece of article text.

TNC recognizes these structural types:

  • paragraph
  • heading
  • quote
  • caption
  • list_item
  • table_cell
  • correction
  • update_notice

tnc parse prints tab-separated ordinal, structural type, and normalized text. The ordinal is the coordinate used by extracted assertions, not an HTML line number. For example, Source spans: 6 means the assertion is supported by source-span ordinal 6.

To inspect one span directly:

uv run tnc parse tests/fixtures/article_v1.html --span 6

Omit --span to show all spans. If the ordinal does not exist, TNC reports an error.

Assertions

Run:

uv run tnc assertions path\to\article.html

The current extractor deliberately recognizes a narrow attribution pattern:

<speaker> <operator> <proposition>

Supported source-text operators are:

  • reported
  • confirmed
  • denied
  • estimated
  • alleged
  • expected
  • said

The current source-text mapping is:

  • said → REPORTED (the extracted predicate remains said)

An assertion is admitted when its source coordinates exist and its recorded verbatim support is present in those source spans.

Admission does not mean TNC verified that the proposition is true. Rejected candidates are listed with reasons; unsupported or ambiguous wording may be skipped rather than guessed. Only the first sentence of each span is considered. Sentence detection has limited punctuation rules, including support for common titles and decimal numbers; ambiguous initials and dotted abbreviations cause the span to be skipped.

Source relationships and provenance

TNC also contains a provenance pipeline for examining relationships between documents. The Python API measures overlap separately from the relationship rules; it is not currently exposed as a tnc provenance CLI command.

Existing document-level judgments are:

  • explicitly_cites
  • likely_derived_from
  • reprint_of

The classifier may also return no judgment. No judgment does not establish that two sources are independent.

Reviewed shared_source_evidence can account for common wire-service, syndication, or underlying-authority material without treating similar wording as proof that one publisher copied another. When supplied, it prevents overlap alone from triggering reprint or derivation labels, even for identical wording; an explicit citation still takes priority. Without that annotation, the existing overlap rules remain in effect.

Callers must supply reviewed evidence to infer_source_relation or measure_provenance_signals. The API does not automatically load review files or infer lineage from a wire-service name. The reviewed comparisons are recorded in the casualty provenance review and its pair annotations.

For a complete CLI-to-Python example using those frozen inputs, see the source-provenance walkthrough.

Historical replay

Historical replay is an advanced, fail-closed workflow.

Historical replay requires a configured review store; the included examples return MISSING_REVIEW until one is set up.

The repository currently includes archived ABC captures and machinery that checks exact saved body hashes, archive index evidence, capture-time constraints, review state, transition configuration, and release receipts.

The source-hosted CLI intentionally starts with no trusted review authority. Real included captures therefore remain blocked with MISSING_REVIEW rather than being released automatically. Archive presence alone is not promoted into an approved historical claim.

Example:

uv run tnc historical-replay --document abc-early --version abc-early-archive-20130521120016 --time 2013-05-21T12:00:16Z

A real capture without trusted review currently returns an unverified result. Passing the synthetic replay tests does not establish that the saved live articles were available at a particular historical time.

See the historical replay CLI documentation for the complete trust and release model.

Limits

TNC is intentionally conservative.

It does not:

  • determine whether a proposition is true;
  • infer source independence automatically;
  • fetch articles from URLs or accept non-HTML input such as PDFs, screenshots, or plain text;
  • treat archive capture as proof of first publication time;
  • release historical evidence without the required review state;
  • act as a general natural-language claim extractor.

The current assertion extractor uses deliberately limited grammatical and sentence-boundary rules. An empty extraction result does not mean an article contains no claims.

Project map

Location Purpose
src/tnc/ CLI entry points and top-level package integration
src/tnc/ingestion/ Saved content, article parsing, and ingestion
src/tnc/spans/ Source spans, assertions, state transitions, and replay
src/tnc/provenance/ Source relationships, review, admission, and historical evidence logic
tests/fixtures/ Small deterministic examples and replay fixtures
tests/golden/ Expected parsed output used to detect changes
corpus/tib_run_a/ Frozen Moore tornado reporting, archive evidence, and review material

Frozen corpus objects are evidence and should not be reformatted or modified casually. Their hashes identify their exact bytes. See the corpus guide for acquisition history, availability uncertainty, and review requirements.

Help

uv run tnc --help
uv run tnc parse --help
uv run tnc assertions --help
uv run tnc historical-replay --help
Message or symptom What to check
uv is not recognized Ensure uv is installed and available in the current terminal.
Project configuration cannot be found Run commands from the checkout containing pyproject.toml.
File cannot be opened Check the path and quote it if it contains spaces.
File cannot be decoded or layout is unsupported Use UTF-8 HTML with a supported article structure; try an included fixture first.
No source span with that ordinal Parse without --span to see the available ordinals.
Admitted: 0 The extractor may not support the wording; inspect the parsed text.

Input and argument errors return a nonzero exit code. In PowerShell, $LASTEXITCODE shows the exit code of the command that just ran.

Acknowledgments

Development of TNC was assisted by AI coding tools including ChatGPT (OpenAI), DeepSeek, and Gemini (Google). The project's design decisions, review, and validation are SolarPluto's responsibility.

Development

TNC is developed from a source checkout using uv.

Clone and sync the locked environment:

git clone https://github.com/SolarPluto/TNC
cd TNC
uv sync --locked

Run any command from the source checkout via uv run:

uv run tnc assertions tests/fixtures/article_v1.html
uv run tnc parse tests/fixtures/article_v1.html

Run the test suite:

uv run pytest -q

Tests cover parsing, CLI behavior, assertions, provenance, temporal behavior, replay fixtures, and frozen-body integrity.

Release files for tnc-provenance 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tnc-provenance 0.1.2
File Size Uploaded
tnc_provenance-0.1.2.tar.gz 206.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tnc-provenance 0.1.2
File Interpreter ABI Platform
tnc_provenance-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 478.4 kB

Release files / tnc_provenance-0.1.2.tar.gz

Download URL tnc_provenance-0.1.2.tar.gz
Size 206.5 kB
Tags Source
SHA-256 checksum
How to use checksums
a1297255a9fe0476402df001c8d1e7a46e931f8da8cc4ccc689dda089b1ca5ca
BLAKE2b-256 checksum
How to use checksums
78b40a83e7d9b4437814ae5f2abfaf8a14ea042af384f35e8114ce0cda205161
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / tnc_provenance-0.1.2-py3-none-any.whl

Download URL tnc_provenance-0.1.2-py3-none-any.whl
Size 271.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6cd09fb1ba07083a1be765f06a558d6509f3dfb845a39f729911fbf974a2310a
BLAKE2b-256 checksum
How to use checksums
57f61937eaa9afb7e80699ad37ef20ef04c9df3e2e85a623029c3abdf1b72486
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page