Status: Accepted Date: 2026-04-09 Deciders: Architect, DevOps agent (root-cause isolation), Orchestrator Related Feature: Feature 128 — Executive Threat Architecture Infographic
Feature 128 introduced a backward-compatibility test harness (tests/scripts/test_backward_compatibility.py, T024) that must guarantee the tachi PDF generation pipeline produces byte-identical output for 5 unmodified example projects before and after the feature's additive changes. The harness compares a fresh pipeline run against committed examples/*/security-report.pdf.baseline files using cmp. If any byte differs, the test fails.
During Wave 2 baseline generation (T003c), the DevOps agent discovered that running the extraction + Typst pipeline twice against identical inputs produces non-byte-identical PDFs. Root-cause isolation revealed that Typst's PDF generator embeds wall-clock timestamps in:
- PDF metadata:
/ModDateand/CreationDatein the document dictionary - XMP metadata:
xmp:CreateDate,xmp:ModifyDate,xmp:MetadataDatestream entries - Derived fields:
xmpMM:InstanceID(derived from the creation timestamp)
All non-metadata bytes — page streams, fonts, images, cross-reference tables — are identical between runs. Only the timestamp-derived fields differ. This is a documented property of Typst's default behavior, not a bug in the tachi pipeline.
Without a fix, test_backward_compatibility.py could never pass, and the backward-compatibility guarantee for Feature 128 could not be asserted.
We adopt SOURCE_DATE_EPOCH=1700000000 (the reproducible-builds.org standard environment variable) as the fixed-value convention for all baseline generation and all backward-compatibility test runs.
Scope:
- Baseline generation (F-128 Wave 2,
examples/*/security-report.pdf.baseline): setSOURCE_DATE_EPOCH=1700000000beforetypst compile. - Backward-compatibility test (
tests/scripts/test_backward_compatibility.py): setSOURCE_DATE_EPOCH=1700000000in the subprocess environment before invoking the pipeline. - Production usage is UNCHANGED: real users running
/tachi.security-reportcontinue to get PDFs with wall-clock timestamps. The environment variable is set only on the test path.
Value: 1700000000 = 2023-11-14 22:13:20 UTC. Any fixed value would work; the specific number is arbitrary but must be consistent between baseline generation and test runs.
- Industry standard:
SOURCE_DATE_EPOCHis the reproducible-builds.org convention honored by gcc, cargo, Python setuptools, Debian packaging, and Typst. Adopting a well-known convention is lower risk than inventing a bespoke mechanism. - Zero source-code changes: The fix lives entirely in test fixtures and CI wrappers.
scripts/extract-report-data.py,main.typ,templates/tachi/security-report/*.typ, and all tachi runtime code are untouched. No maintenance burden on the runtime pipeline. - Preserves byte-identical comparison semantics: The test can still use
cmpto detect real regressions in page content, layout, or structure. It does not weaken the backward-compatibility guarantee — it removes only the environmental noise (wall-clock timestamps) that was masking the signal. - Production behavior unchanged: Real users of
/tachi.security-reportget PDFs with accurate creation timestamps, which is the correct default for security reports (timestamp provenance matters for audit). - Verified empirically: The DevOps agent ran the full pipeline twice with
SOURCE_DATE_EPOCH=1700000000and confirmed all 5 example PDFs become byte-deterministic across runs. Without the env var, the same two runs produce differing PDFs. - Composable with other determinism guarantees:
scripts/extract-report-data.pyalready produces byte-identical JSON/Typst data for identical inputs (Feature 071, ADR-017).SOURCE_DATE_EPOCHextends that same guarantee to the final Typst compile step.
Pros:
- Full control over the comparison surface
- No environment variable dependency
Cons:
- Requires modifying
scripts/extract-report-data.pyor adding a post-processing step - Couples tachi to a specific PDF library for metadata manipulation
- Higher review surface and maintenance burden
- Risks breaking on future Typst upgrades that reshape metadata
Why Not Chosen: High complexity for a test-path-only concern. Invasive changes to runtime code for a developer-only test contract violates the separation between runtime and test infrastructure.
Pros:
- No environment variable required
- Allows production-like PDFs in baselines
Cons:
- Requires custom PDF parsing tooling to identify "content" vs "metadata" bytes
- Weakens the backward-compatibility guarantee — any future PDF library update could change metadata location or format, silently masking real regressions
- The line between "metadata" and "content" is PDF-specification-dependent and fragile
Why Not Chosen: Weakens the test guarantee and adds custom tooling that would become maintenance burden. cmp-based byte-exact comparison is the strongest contract possible, and SOURCE_DATE_EPOCH preserves it.
Pros:
- No committed binary baseline files
- Baselines always match the current upstream state
Cons:
- Couples the test to git history and network access
- Local test runs become slow and fragile (checkout, build, discard)
- Obscures test intent (baseline is no longer reviewable in PR diffs)
Why Not Chosen: Violates the F-128 Decision 1 choice (committed .baseline files) which was already approved for repeatability, self-containment, and traceability. This alternative replaces one problem with several worse ones.
- Backward-compatibility test is stable across developer laptops, CI runners, and post-merge audits
- Real regressions are detected immediately (page content changes, layout drift, structural changes)
- Zero runtime code changes — production PDFs remain fully timestamped
- Establishes a reusable convention: any future test that needs deterministic PDF output can set the same environment variable
- Composable with the Feature 071 extraction determinism guarantee (ADR-017)
- Tests must remember to set
SOURCE_DATE_EPOCHbefore invoking the pipeline (documented in test fixture setup; failures are loud and immediate) - Baseline PDFs embed a fake timestamp (2023-11-14) rather than their true generation date — noted in the
.baselinefile naming convention and PR descriptions - Future contributors adding new
.baselinefiles must use the same fixed epoch value (convention documented intests/scripts/README.mdand the Tech Stack doc)
tests/scripts/test_backward_compatibility.pysetsSOURCE_DATE_EPOCHat fixture scope, not in each test function — single point of truth- Baseline generation is manually gated (
make test-baseline-regenerateor equivalent); contributors cannot accidentally commit a non-deterministic baseline because the test itself would immediately fail .baselinefiles are reviewed in PR diffs via size + checksum; any unintended change surfaces during code review
- F-128 Decision 1: Baseline PDF Storage via committed
.baselinefiles — this ADR provides the determinism prerequisite for that choice to work - F-128 Decision 3: Original SOURCE_DATE_EPOCH escalation and devops root-cause analysis (captured in
specs/128-prd-128-executive/decisions.md) - ADR-017: Deterministic Infographic Extraction — extraction-side determinism; this ADR is the compile-side counterpart
- ADR-014: Gemini API as Optional, Best-Effort Image Generation — baseline determinism applies only to the 5 examples without the new executive-architecture JPEG; the 6th example (agentic-app) is intentionally regenerated
- reproducible-builds.org SOURCE_DATE_EPOCH specification
- Typst documentation on reproducible builds
specs/128-prd-128-executive/decisions.md— Decision 3 for root-cause analysis and empirical verificationtests/scripts/test_backward_compatibility.py— the consuming test harnessexamples/*/security-report.pdf.baseline— the committed baselines this decision enables
Status Note: Accepted 2026-04-09 during Feature 128 implementation. No superseding decisions anticipated — reproducible-builds is a stable industry convention and Typst support is upstream-maintained.