{"schemaVersion":1,"id":"https://lucioduran.com/projects/citable-publication","url":"https://lucioduran.com/projects/citable-publication","title":"Citable Publication","description":"Deterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.","language":"en","datePublished":"2026-10-21","dateModified":"2026-10-21","contentFormat":"text/markdown","content":"[Projects](<https://lucioduran.com/projects>) / Citable Publication\n\n# Citable Publication\n\nDeterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.\n\nAuthor: [Lucio Durán](<https://lucioduran.com/>) · Python 3.13.7 · License: [MIT](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)\n\nPage published: 2026-10-21 · Page updated: 2026-10-21\n\n[Repository](<https://github.com/lucioduran/citable-publication>) · [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)\n\n## Problem and relevance to agents\n\nA 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.\n\nTo 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.\n\n## Architecture\n\n1. **Input contract.** A validated JSON corpus becomes an immutable model. Each document declares a canonical HTTPS URL and each section has a stable identifier.\n2. **Three representations.** The same model generates HTML, Markdown and JSON. A manifest records paths, media types, byte counts and SHA-256 hashes.\n3. **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.\n4. **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.\n\n- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)\n- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)\n\n## What this demonstrates\n\n- Data contracts and citable references, with deterministic generation from a shared source.\n- Integrity checks that detect content loss, missing files and schema drift before promoting a publication.\n- Reproducible evaluation through fault injection, a clean control, an explicit comparison and inspectable results.\n\n## Published results\n\nResults 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.\n\nOriginal 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.\n\n### Control comparison\n\n| Measurement | Canonical URL only | Full gate |\n| --- | --- | --- |\n| Clean controls accepted | 1 / 1 | 1 / 1 |\n| Injected faults rejected | 3 / 18 | 18 / 18 |\n| Injected faults missed | 15 / 18 | 0 / 18 |\n\nThese 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.\n\nThe 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>).\n\n## Reproduce\n\nNo runtime dependencies, model calls or paid services. Build and verification commands print JSON reports; successful verification exits with code 0.\n\nUse 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.\n\n### Build and verify\n\n```\ngit clone https://github.com/lucioduran/citable-publication.git\ncd citable-publication\ngit checkout 1a265730b7e0acdd3d326bd3fb7704f71e15edec\npython -m citable_publication build --corpus examples/corpus.json --output dist/first-release\npython -m citable_publication verify --corpus examples/corpus.json --output dist/first-release\npython -m experiments.reproduce --output build/reproduction.json\n```\n\n## Scope and limitations\n\n- This is an independent implementation inspired by lucioduran.com requirements. It does not audit or certify the live website.\n- 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.\n- Exact byte comparison also rejects harmless formatting changes. The verifier and renderer share code: a shared bug may escape the gate.\n- Markdown tables and HTML anchors depend on reader support. SHA-256 identifies bytes, not authorship or factual truth.\n- 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.\n- The corpus is loaded into memory. Untrusted input needs external size limits; a language declaration is not language detection.\n\n- [How this website publishes and exposes its content](<https://lucioduran.com/access>)\n\n## Sources and revision\n\nValues 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.\n\n- Reviewed revision: [` 1a265730b7e0acdd3d326bd3fb7704f71e15edec `](<https://github.com/lucioduran/citable-publication/commit/1a265730b7e0acdd3d326bd3fb7704f71e15edec>)\n- Revision recorded by the experiment: [` 150b2d3f5059bf0cef5cd7dde441896539ad4d6e `](<https://github.com/lucioduran/citable-publication/commit/150b2d3f5059bf0cef5cd7dde441896539ad4d6e>)\n- Report timestamp (UTC): 2026-10-21T20:48:30.875583+00:00\n- Corpus SHA-256: ` 059916d1c6d4fbbf15df7fb65ddefe39d2f892bb0caeae494037c04a5675959c `\n\n- [README](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/README.md>)\n- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)\n- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)\n- [Example corpus](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/examples/corpus.json>)\n- [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)\n- [Clean publication report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json>)\n- [MIT license](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)","headings":[{"level":1,"text":"Citable Publication","url":"https://lucioduran.com/projects/citable-publication#title"},{"level":2,"text":"Problem and relevance to agents","url":"https://lucioduran.com/projects/citable-publication#problem"},{"level":2,"text":"Architecture","url":"https://lucioduran.com/projects/citable-publication#architecture"},{"level":2,"text":"What this demonstrates","url":"https://lucioduran.com/projects/citable-publication#demonstrates"},{"level":2,"text":"Published results","url":"https://lucioduran.com/projects/citable-publication#results"},{"level":3,"text":"Control comparison","url":"https://lucioduran.com/projects/citable-publication#results-comparison"},{"level":2,"text":"Reproduce","url":"https://lucioduran.com/projects/citable-publication#reproduce"},{"level":3,"text":"Build and verify","url":"https://lucioduran.com/projects/citable-publication#reproduce-verification"},{"level":2,"text":"Scope and limitations","url":"https://lucioduran.com/projects/citable-publication#scope"},{"level":2,"text":"Sources and revision","url":"https://lucioduran.com/projects/citable-publication#sources"}],"sections":[{"heading":"Citable Publication","level":1,"url":"https://lucioduran.com/projects/citable-publication","content":"[Projects](<https://lucioduran.com/projects>) / Citable Publication"},{"heading":"Citable Publication","level":1,"url":"https://lucioduran.com/projects/citable-publication#title","content":"Deterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.\n\nAuthor: [Lucio Durán](<https://lucioduran.com/>) · Python 3.13.7 · License: [MIT](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)\n\nPage published: 2026-10-21 · Page updated: 2026-10-21\n\n[Repository](<https://github.com/lucioduran/citable-publication>) · [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)"},{"heading":"Problem and relevance to agents","level":2,"url":"https://lucioduran.com/projects/citable-publication#problem","content":"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.\n\nTo 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."},{"heading":"Architecture","level":2,"url":"https://lucioduran.com/projects/citable-publication#architecture","content":"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.\n2. **Three representations.** The same model generates HTML, Markdown and JSON. A manifest records paths, media types, byte counts and SHA-256 hashes.\n3. **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.\n4. **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.\n\n- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)\n- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)"},{"heading":"What this demonstrates","level":2,"url":"https://lucioduran.com/projects/citable-publication#demonstrates","content":"- Data contracts and citable references, with deterministic generation from a shared source.\n- Integrity checks that detect content loss, missing files and schema drift before promoting a publication.\n- Reproducible evaluation through fault injection, a clean control, an explicit comparison and inspectable results."},{"heading":"Published results","level":2,"url":"https://lucioduran.com/projects/citable-publication#results","content":"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.\n\nOriginal 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."},{"heading":"Control comparison","level":3,"url":"https://lucioduran.com/projects/citable-publication#results-comparison","content":"| Measurement | Canonical URL only | Full gate |\n| --- | --- | --- |\n| Clean controls accepted | 1 / 1 | 1 / 1 |\n| Injected faults rejected | 3 / 18 | 18 / 18 |\n| Injected faults missed | 15 / 18 | 0 / 18 |\n\nThese 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.\n\nThe 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>)."},{"heading":"Reproduce","level":2,"url":"https://lucioduran.com/projects/citable-publication#reproduce","content":"No runtime dependencies, model calls or paid services. Build and verification commands print JSON reports; successful verification exits with code 0.\n\nUse 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."},{"heading":"Build and verify","level":3,"url":"https://lucioduran.com/projects/citable-publication#reproduce-verification","content":"```\ngit clone https://github.com/lucioduran/citable-publication.git\ncd citable-publication\ngit checkout 1a265730b7e0acdd3d326bd3fb7704f71e15edec\npython -m citable_publication build --corpus examples/corpus.json --output dist/first-release\npython -m citable_publication verify --corpus examples/corpus.json --output dist/first-release\npython -m experiments.reproduce --output build/reproduction.json\n```"},{"heading":"Scope and limitations","level":2,"url":"https://lucioduran.com/projects/citable-publication#scope","content":"- This is an independent implementation inspired by lucioduran.com requirements. It does not audit or certify the live website.\n- 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.\n- Exact byte comparison also rejects harmless formatting changes. The verifier and renderer share code: a shared bug may escape the gate.\n- Markdown tables and HTML anchors depend on reader support. SHA-256 identifies bytes, not authorship or factual truth.\n- 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.\n- The corpus is loaded into memory. Untrusted input needs external size limits; a language declaration is not language detection.\n\n- [How this website publishes and exposes its content](<https://lucioduran.com/access>)"},{"heading":"Sources and revision","level":2,"url":"https://lucioduran.com/projects/citable-publication#sources","content":"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.\n\n- Reviewed revision: [` 1a265730b7e0acdd3d326bd3fb7704f71e15edec `](<https://github.com/lucioduran/citable-publication/commit/1a265730b7e0acdd3d326bd3fb7704f71e15edec>)\n- Revision recorded by the experiment: [` 150b2d3f5059bf0cef5cd7dde441896539ad4d6e `](<https://github.com/lucioduran/citable-publication/commit/150b2d3f5059bf0cef5cd7dde441896539ad4d6e>)\n- Report timestamp (UTC): 2026-10-21T20:48:30.875583+00:00\n- Corpus SHA-256: ` 059916d1c6d4fbbf15df7fb65ddefe39d2f892bb0caeae494037c04a5675959c `\n\n- [README](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/README.md>)\n- [Design and guarantees](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md>)\n- [Input contract](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md>)\n- [Example corpus](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/examples/corpus.json>)\n- [Fault injection report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json>)\n- [Clean publication report](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json>)\n- [MIT license](<https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE>)"}],"links":[{"text":"Projects","url":"https://lucioduran.com/projects"},{"text":"Lucio Durán","url":"https://lucioduran.com/"},{"text":"MIT","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE"},{"text":"Repository","url":"https://github.com/lucioduran/citable-publication"},{"text":"Fault injection report","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json"},{"text":"Design and guarantees","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md"},{"text":"Input contract","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md"},{"text":"Clean publication report","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json"},{"text":"How this website publishes and exposes its content","url":"https://lucioduran.com/access"},{"text":"1a265730b7e0acdd3d326bd3fb7704f71e15edec","url":"https://github.com/lucioduran/citable-publication/commit/1a265730b7e0acdd3d326bd3fb7704f71e15edec"},{"text":"150b2d3f5059bf0cef5cd7dde441896539ad4d6e","url":"https://github.com/lucioduran/citable-publication/commit/150b2d3f5059bf0cef5cd7dde441896539ad4d6e"},{"text":"README","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/README.md"},{"text":"Example corpus","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/examples/corpus.json"},{"text":"MIT license","url":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE"}],"structuredData":[{"@context":"https://schema.org","@graph":[{"@type":"WebPage","@id":"https://lucioduran.com/projects/citable-publication#page","url":"https://lucioduran.com/projects/citable-publication","name":"Citable Publication","description":"Deterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.","inLanguage":"en","datePublished":"2026-10-21","dateModified":"2026-10-21","author":{"@id":"https://lucioduran.com/#person"},"mainEntity":{"@id":"https://lucioduran.com/projects/citable-publication#software"}},{"@type":"SoftwareSourceCode","@id":"https://lucioduran.com/projects/citable-publication#software","name":"Citable Publication","description":"Deterministic HTML, Markdown and JSON publishing from one corpus, with integrity verification before release and reproducible faults.","url":"https://lucioduran.com/projects/citable-publication","codeRepository":"https://github.com/lucioduran/citable-publication","programmingLanguage":"Python","runtimePlatform":"Python 3.13.7","license":"https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/LICENSE","version":"1a265730b7e0acdd3d326bd3fb7704f71e15edec","author":{"@type":"Person","@id":"https://lucioduran.com/#person","name":"Lucio Durán","url":"https://lucioduran.com"},"isAccessibleForFree":true,"citation":["https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/README.md","https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/design.md","https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/docs/contract.md","https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/examples/corpus.json","https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/reproduction.json","https://github.com/lucioduran/citable-publication/blob/1a265730b7e0acdd3d326bd3fb7704f71e15edec/results/publication.json"]},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Projects","item":"https://lucioduran.com/projects"},{"@type":"ListItem","position":2,"name":"Citable Publication","item":"https://lucioduran.com/projects/citable-publication"}]}]}],"contentHash":"f15b5b661fc5d9b939410ef3c2a847b440167b4f1c29505c0072b274addf9830","provenance":{"method":"Deterministic serialization of the server-rendered main element","source":"https://lucioduran.com/projects/citable-publication","hashAlgorithm":"sha256","hashScope":"JSON document fields before contentHash and provenance","sourceHTMLBytes":40324,"contentBytes":7361}}
