<!-- Canonical: https://lucioduran.com/projects/citable-publication
Language: en
Content-SHA256: f15b5b661fc5d9b939410ef3c2a847b440167b4f1c29505c0072b274addf9830
-->

[Projects](<https://lucioduran.com/projects>) / Citable Publication

# Citable Publication

Deterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.

Author: [Lucio Durán](<https://lucioduran.com/>) · Python 3.13.7 · License: [MIT](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)

Page published: 2026-10-21 · Page updated: 2026-10-21

[Repository](<https://github.com/lucioduran/citable-publication>) · [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)

## Problem and relevance to agents

A correct canonical URL does not guarantee that an agent receives complete content. An export can lose code, truncate a table or change its JSON schema without changing that URL. Citable Publication defines a publication contract and rejects files that diverge from it.

To cite a source, an agent needs to retrieve the right passage and preserve its context. This project addresses a specific part of that problem: preserving content and references across formats and detecting drift before publication.

## Architecture

1. **Input contract.** A validated JSON corpus becomes an immutable model. Each document declares a canonical HTTPS URL and each section has a stable identifier.
2. **Three representations.** The same model generates HTML, Markdown and JSON. A manifest records paths, media types, byte counts and SHA-256 hashes.
3. **Verification against the source.** The verifier regenerates expected bytes from the original corpus. It does not treat the manifest as its authority: changing a file and updating its hash still causes rejection.
4. **Gated publication.** Output is built in a staging directory, verified and renamed to the destination. A new destination is required and errors are reported per file and document.

- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)
- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)

## What this demonstrates

- Data contracts and citable references, with deterministic generation from a shared source.
- Integrity checks that detect content loss, missing files and schema drift before promoting a publication.
- Reproducible evaluation through fault injection, a clean control, an explicit comparison and inspectable results.

## Published results

Results published by the author in the repository. Both validators use the same corpus of three original synthetic documents. The baseline checks only HTML canonical URLs; the full gate verifies the publication against its source.

Original output is restored before each case and each mutation is checked for changed bytes. The six fault classes affect canonical URLs, JSON schema versions, Markdown code, HTML tables, missing JSON and an emptied manifest.

### Control comparison

| Measurement | Canonical URL only | Full gate |
| --- | --- | --- |
| Clean controls accepted | 1 / 1 | 1 / 1 |
| Injected faults rejected | 3 / 18 | 18 / 18 |
| Injected faults missed | 15 / 18 | 0 / 18 |

These are 18 cases in a fixed matrix, not 18 fault classes or an effectiveness estimate for arbitrary websites. The empty manifest repeats the same global failure three times. This measures correctness, not speed, ranking or the probability that a model cites a source.

The clean report covers 3 documents and 10 files, including the manifest. [Clean publication report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json>).

## Reproduce

No runtime dependencies, model calls or paid services. Build and verification commands print JSON reports; successful verification exits with code 0.

Use Python 3.13.7 and an output directory that does not yet exist. Keep reports outside the published directory. The revision is pinned to the code and sources discussed here. A local run will record its own environment metadata and timestamp.

### Build and verify

```
git clone https://github.com/lucioduran/citable-publication.git
cd citable-publication
git checkout 1a265730b7e0acdd3d326bd3fb7704f71e15edec
python -m citable_publication build --corpus examples/corpus.json --output dist/first-release
python -m citable_publication verify --corpus examples/corpus.json --output dist/first-release
python -m experiments.reproduce --output build/reproduction.json
```

## Scope and limitations

- This is an independent implementation inspired by lucioduran.com requirements. It does not audit or certify the live website.
- The corpus supports English documents with literal paragraphs, code blocks, rectangular tables and sections. Images, lists, rich text and multilingual documents are unsupported. This project page is translated.
- Exact byte comparison also rejects harmless formatting changes. The verifier and renderer share code: a shared bug may escape the gate.
- Markdown tables and HTML anchors depend on reader support. SHA-256 identifies bytes, not authorship or factual truth.
- A trusted single-writer filesystem is required. Staging does not provide concurrent deployment exclusion or power-loss durability. Serving content and cache invalidation are outside scope.
- The corpus is loaded into memory. Untrusted input needs external size limits; a language declaration is not language detection.

- [How this website publishes and exposes its content](<https://lucioduran.com/access>)

## Sources and revision

Values on this page come from the linked report. They are not live measurements. The report records the executed revision; the reviewed revision includes the subsequent publication of that report.

- Reviewed revision: [` 1a265730b7e0acdd3d326bd3fb7704f71e15edec `](<https://github.com/lucioduran/citable-publication/commit/1a265730b7e0acdd3d326bd3fb7704f71e15edec>)
- Revision recorded by the experiment: [` 150b2d3f5059bf0cef5cd7dde441896539ad4d6e `](<https://github.com/lucioduran/citable-publication/commit/150b2d3f5059bf0cef5cd7dde441896539ad4d6e>)
- Report timestamp (UTC): 2026-10-21T20:48:30.875583+00:00
- Corpus SHA-256: ` 059916d1c6d4fbbf15df7fb65ddefe39d2f892bb0caeae494037c04a5675959c `

- [README](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/README.md>)
- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)
- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)
- [Example corpus](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/examples/corpus.json>)
- [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)
- [Clean publication report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json>)
- [MIT license](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)
