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.

An unrelated PyPI distribution named tnc exists; TNC publishes as tnc-provenance to avoid ambiguity.

For installed use on Windows PowerShell, prefer the collision-free command:

tncprov assertions article.html

PowerShell's NetTCPIP module defines tnc as an alias for Test-NetConnection, which shadows the installed tnc.exe. The package still provides tnc for shells where that name is unambiguous, and source checkouts can continue to use uv run tnc ....

See it work

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

uv run tnc assertions tests/fixtures/article_v1.html

Output from the current version:

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.

Try it from a source checkout

TNC is not yet published to PyPI. The current supported usage is from a source checkout.

Requirements:

  • Python 3.12 or newer
  • uv

From the project root:

uv sync --locked

Then run:

uv run tnc assertions tests/fixtures/article_v1.html

or parse the article into source spans:

uv run tnc parse tests/fixtures/article_v1.html

To use your own saved article:

uv run tnc parse "C:\path\to\saved article.html"

The included fixture requires no API key or article download. 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.

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

Run the test suite from the repository root:

uv run pytest -q

Tests cover parsing, CLI behavior, assertions, provenance, temporal behavior, replay fixtures, and frozen-body integrity. A passing suite verifies those checks, not the truth of the underlying reporting.

Some native Windows tests skip on non-Windows platforms. Non-doc PRs are validated by the full Windows CI suite.

Install pre-commit as a uv tool once, then install the repository hook:

uv tool install pre-commit
pre-commit install

To run the text-hygiene checks manually across the repository:

pre-commit run --all-files

Before committing a change, also inspect the diff:

git diff
git diff --check

PRs that change only docs/** and/or lowercase Markdown files use the docs-only CI route; other changes run the full Windows suite. See the Windows test reliability inventory for the routing rule and reliability notes.

Do not apply automatic formatting to frozen corpus objects.

Release files for tnc-provenance 0.1.1

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.1
File Size Uploaded
tnc_provenance-0.1.1.tar.gz 206.5 kB Details

Built distribution (wheel)

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

Total release size: 478.3 kB

Release files / tnc_provenance-0.1.1.tar.gz

Download URL tnc_provenance-0.1.1.tar.gz
Size 206.5 kB
Tags Source
SHA-256 checksum
How to use checksums
6fb897e9789a2d4231c6732c20654f98babc4403287fca29e2abae16866c9bc0
BLAKE2b-256 checksum
How to use checksums
7b5ad0c11f1fddcf33fce516e7d10fd62f907efb2292399c35187372517002f5
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.1-py3-none-any.whl

Download URL tnc_provenance-0.1.1-py3-none-any.whl
Size 271.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8d40fda66663fd945ac3d8f2406523daedc3c08fb1f47cb01044742e57e63868
BLAKE2b-256 checksum
How to use checksums
dd0ec6ad65f7a2a1f0d711462519d8ecc012bf562de5c30d877160ff40940228
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

0.1.2

2 release files

This release

0.1.1 This release

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