Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions insights/QA_2026-10-31_D08_POSTMERGE_AUDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# D08 — actual post-merge artifact audit and setup-stage discrepancy

Date: 2026-10-31. Base main `6d15d86344ab1281391d3ea1b458dc18ae443985`, open PRs and `AGENTS.md` reviewed. #40 (merge `a671ebc26bdde180602a8df3fa99f8651e1bced5`) and #52 (merge `1e3a1e7131bd6e8d9c9d9d9c93ae5c9203c0f455`) are closed/merged. Only D-owned paths modified.

## Independently executed readbacks (not inherited status)

- Directly downloaded `qa-miktex-windows-server` artifact 13044230534 for push-main run 41203529698, checked ZIP SHA-256 `0c6f7a1af3871ab7078d104272c6a1fe221f1bb095747f5468abd58776430eb1`, 44 files. `miktex-qa.json`: exact commit/source head `6d15d86344ab1281391d3ea1b458dc18ae443985`; four results PASS (hand-authored primitive baseline, strict missing-library, strict Lua-only, real N1 app Session-generated source). It explicitly says physical Win10/M1/M4, mouse, help, GUI themes: NOT_RUN.
- Real executable and installer from setup/QA: MiKTeX-XeTeX 4.16 (MiKTeX 25.12), official 25.12 installer SHA `14b42dd9f4b4a7813a8bfd69c8f99316c2888cc4ee26f631f397e163d85d6c62`, private TEXMF roots, `AutoInstall=0` readback, explicit disabled installer in direct XeLaTeX command. `packages-before.txt` and `packages-after.txt` **byte-identical**, exactly 9130 lines.
- Extracted all six actual PDFs and independently ran `pdfinfo`, `pdftotext -enc UTF-8`, `pdffonts`; every PDF is one page, Cyrillic `Примитивы TikZ` or `Геометрия_1 & оптика 25%` and math glyphs `𝛼`/`𝛽` are present, embedded DejaVuSerif/LatinModernMath recorded. All six reported PDF SHA-256 values match PDF bytes; all N1 source SHA-256 values match archived generated `.tex` bytes before/after. Missing-library and graphdrawing Lua-only log errors have exact source-specific diagnostics and `No pages of output`; no corresponding PDFs in ZIP.
- Detected benign copy nuance: top-level `proof with spaces Кириллица/direct-tex.log` is a **UTF-8 reserialization** of `direct/main.log`; SHA in QA correctly refers to original `direct/main.log`, not the normalized copy. Did not count this as a hash failure.
- Real defect: `setup-stage.json` remained `INCOMPLETE` at the earlier `package-metadata-validated` checkpoint after actual success. Unlike provenance/PDF checks, stage metadata is false/stale for completed setup. Need terminal stage and strict QA readback, plus installed-package postcondition, not a weakening of acceptance.

## D08 correction and proof status

The D08 branch updates `scripts/tools/qa_setup_miktex.ps1` terminal checkpoint after setup.json, verifies every declared package is now installed, adds `setup_stage_complete()` to the existing XeLaTeX QA report, and adds reject cases in Python stdlib tests. All changes grouped in one D-only commit with this insight and D08 plan. **Modified exact-head hosted MiKTeX, Rust and D QA are PENDING** until their respective workflow logs/artifacts complete. Do not transfer verified main SHA status to new D08 HEAD. No physical user-host or GUI acceptance claimed.
17 changes: 17 additions & 0 deletions plans/QA_2026-10-31_D08_POSTMERGE_MIKTEX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# D08 — exact-main MiKTeX acceptance and terminal setup evidence

Date: 2026-10-31. Read fresh `main` SHA `6d15d86344ab1281391d3ea1b458dc18ae443985`, open PRs (#48/#50/#54/#55), `AGENTS.md`, D06 plan and insight, and actual workflow/artifacts before changes. Work only on D-owned scripts, tests and QA documentation; D06 #40 and D07 #52 are already merged, so do not attempt to rewrite closed PRs. This is a narrow fail-closed correction to the **existing real MiKTeX pipeline**, not a standalone TeX fixture.

## Independently checked post-merge main

[Run 41203529698](https://github.com/i-shutov/tikzarium/actions/runs/41203529698) on exact **push-main** `6d15d86344ab1281391d3ea1b458dc18ae443985`, hosted Windows Server 2022 x64: SUCCESS, one genuine MiKTeX 25.12 job. [Artifact 13044230534](https://github.com/i-shutov/tikzarium/actions/runs/41203529698/artifacts/13044230534) downloaded and inspected, 44 members, ZIP SHA-256 `0c6f7a1af3871ab7078d104272c6a1fe221f1bb095747f5468abd58776430eb1`. Report `commit_sha` and `source_head_sha` both equal main (no synthetic PR merge). Installer hash `14b42dd9f4b4a7813a8bfd69c8f99316c2888cc4ee26f631f397e163d85d6c62`, private effective roots, `AutoInstall=0`, `--disable-installer`, and engine `MiKTeX-XeTeX 4.16 (MiKTeX 25.12)` proven by setup/engine evidence. Canonical package inventories 9130/9130 lines, byte-identical. Actual six one-page PDFs independently examined with Poppler: text and mathematical italic Greek extract correctly, DejaVuSerif/LatinModernMath embedded. The N1 producer is `tikzarium-app --bin n1-authoring-proof`, using C primitive catalogue; source SHA recorded and unchanged through CLI/direct engine. Lua-only and missing-library both nonzero, required diagnostics and no PDF. Rust [41203529736](https://github.com/i-shutov/tikzarium/actions/runs/41203529736) 3/3 and D QA [41203529679](https://github.com/i-shutov/tikzarium/actions/runs/41203529679) 7/7 also SUCCESS.

## Genuine evidence defect (discovered in independent archive)

The post-merge artifact's `setup-stage.json` **still says** `stage=package-metadata-validated, status=INCOMPLETE` despite terminal `setup.json` and four QA results passing. It is an unfinalized *progress checkpoint*, not a MiKTeX setup failure. Consumers must never mistake this stale status for a current setup verdict. D08 updates the existing setup script to atomically publish `stage=setup-complete, status=SETUP_COMPLETE` only after `setup.json` has been written, and makes the existing real PDF test require an exact, matching terminal checkpoint. Also rechecks `isInstalled=true` for all nine declared packages after explicit missing-only installs (not merely successful exit), without auto-install or global state. Add stdlib negative regressions; previous source/glyph/error/embedded-font/package-inventory gates unchanged.

**Current D08 branch is NOT accepted until its own exact-SHA real MiKTeX CI, new archived setup checkpoint and all six actual PDF proofs have been inspected.** Do not inherit main PASS to modified D08 SHA. No additional full workflow runs for one-file micro-commits; group script/tests/docs into a single commit.

## Acceptance boundaries

Hosted Windows Server CI_ONLY; **physical Windows 10 x64** with independently installed external MiKTeX is `NOT_RUN`. M1/M4 with external XeLaTeX and real egui mouse F1/hover/code pane/themes/screenshots are `NOT_RUN` and owned by independent target-host/B/E/F acceptance, not N1 Session emulation. R4 licensed contents not imported; O027/O028/O030/O047 remain open. No changes to A/B/C production files, MiKTeX installer or user TeX configuration.
20 changes: 19 additions & 1 deletion scripts/tools/qa_miktex_vertical.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ def miktex_engine(version: str) -> bool:
return "miktex" in version.casefold() and "xetex" in version.casefold()


def setup_stage_complete(stage: dict, setup: dict) -> bool:
"""Require terminal, provenance-matched setup; never accept stale INCOMPLETE."""
installer = setup.get("installer_sha256")
engine = setup.get("xelatex_path")
return (isinstance(stage, dict) and stage.get("schema_version") == 1
and stage.get("stage") == "setup-complete"
and stage.get("status") == "SETUP_COMPLETE"
and isinstance(installer, str) and bool(installer)
and isinstance(engine, str) and bool(engine)
and stage.get("installer_sha256") == installer
and stage.get("xelatex_path") == engine
and stage.get("auto_install_config_readback") == "0")


def poppler_version(tool: str, transcript: str) -> bool:
"""A real Poppler auditor, not MiKTeX's same-named TeX shim."""
return bool(re.search(rf"(?m)^{re.escape(tool)} version [0-9]+(?:[.][0-9]+)+", transcript))
Expand Down Expand Up @@ -336,7 +350,11 @@ def main(argv: list[str] | None = None) -> int:
or setup.get("auto_install_disabled") is not True
or Path(setup.get("user_install", "")).resolve() != prefix):
raise RuntimeError("Isolated MiKTeX setup provenance or auto-install-off proof absent")
stage = json.loads(args.setup_record.with_name("setup-stage.json").read_text(encoding="utf-8-sig"))
if not setup_stage_complete(stage, setup):
raise RuntimeError("MiKTeX private setup-stage is incomplete or provenance-mismatched")
report["setup"] = setup
report["setup_stage"] = stage
report["pdf_tools"] = select_poppler(args.poppler_dir)
if os.environ.get("TIKZARIUM_XELATEX", "").casefold() != str(engine).casefold():
raise RuntimeError("CLI must be explicitly pointed to this MiKTeX XeLaTeX binary")
Expand All @@ -348,7 +366,7 @@ def main(argv: list[str] | None = None) -> int:
root / "extensions/fixtures/graphdrawing-lua.tex",
"lua-only", "lua-only", output, engine))
report["results"].append(n1_positive(root, output, engine, cli, args.n1_proof.resolve()))
except (OSError, RuntimeError, subprocess.TimeoutExpired) as exc:
except (OSError, RuntimeError, json.JSONDecodeError, subprocess.TimeoutExpired) as exc:
report["fatal"] = f"{type(exc).__name__}: {exc}"
finally:
report["accepted"] = not report.get("fatal") and len(report["results"]) == 4 and all(
Expand Down
19 changes: 19 additions & 0 deletions scripts/tools/qa_setup_miktex.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,18 @@ $packageVersionFile = Join-Path $recordDir 'explicit-package-versions.txt'
foreach ($package in $packages) {
$info = (& $miktexExe packages info --template '{id}|{version}|{timePackaged}|{isInstalled}' $package 2>&1 | Out-String).Trim()
if ($LASTEXITCODE -ne 0) { throw "Cannot inspect installed package version for $package" }
# A successful explicit install is not a proof that *each* dependency is now installed.
# Reject unknown/duplicate/malformed post-provision metadata, not just absent TeX files.
$installedRows = @($info -split '(?:\r\n|\r|\n)' |
Where-Object { $_ -match ('^' + [regex]::Escape($package) + '\|') })
if ($installedRows.Count -ne 1) {
throw "MiKTeX post-provision package metadata missing/ambiguous for $package"
}
$installedFields = @($installedRows[0].Trim() -split '\|', 4)
if ($installedFields.Count -ne 4 -or $installedFields[0] -cne $package -or
$installedFields[3] -cne 'true') {
throw "MiKTeX declared package $package is not confirmed installed after provisioning"
}
"$package => $info" | Out-File -FilePath $packageVersionFile -Append -Encoding utf8
}

Expand Down Expand Up @@ -155,4 +167,11 @@ $setupRecord = @{
ci_host = 'windows-2022'; target_windows10 = 'NOT_RUN'; physical_mac_arm = 'NOT_RUN'
}
$setupRecord | ConvertTo-Json -Depth 5 | Out-File -FilePath (Join-Path $recordDir 'setup.json') -Encoding utf8
# Terminal status is for the *setup stage*, not the XeLaTeX/PDF QA job.
# An incomplete checkpoint must not survive a successfully committed setup.json.
@{ schema_version = 1; stage = 'setup-complete'; status = 'SETUP_COMPLETE'
installer_sha256 = $downloadedHash; xelatex_path = $xelatex
auto_install_config_readback = $configValue; host = 'windows-2022'
physical_windows10 = 'NOT_RUN' } |
ConvertTo-Json | Set-Content -LiteralPath (Join-Path $recordDir 'setup-stage.json') -Encoding utf8
Write-Host "MiKTeX private XeLaTeX: $xelatex"
20 changes: 19 additions & 1 deletion scripts/tools/test_qa_miktex_vertical.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from pathlib import Path
import unittest

from qa_miktex_vertical import MISSING_LIBRARY, PRIMITIVE_TOKENS, N1_TOOLS, miktex_engine, n1_state_contract, poppler_version, tex_failure
from qa_miktex_vertical import MISSING_LIBRARY, PRIMITIVE_TOKENS, N1_TOOLS, miktex_engine, n1_state_contract, poppler_version, setup_stage_complete, tex_failure


class MiKTeXVerticalContract(unittest.TestCase):
Expand All @@ -21,6 +21,22 @@ def test_miktex_version_must_be_xetex(self):
self.assertFalse(miktex_engine("XeTeX 3.14159 (TeX Live 2026)"))
self.assertFalse(miktex_engine("MiKTeX-pdfTeX 4.0"))

def test_terminal_setup_provenance_rejects_stale_or_mismatched_checkpoint(self):
setup = {"installer_sha256": "0" * 64, "xelatex_path": r"D:\private\xelatex.exe"}
stage = {"schema_version": 1, "stage": "setup-complete",
"status": "SETUP_COMPLETE", "installer_sha256": setup["installer_sha256"],
"xelatex_path": setup["xelatex_path"], "auto_install_config_readback": "0"}
self.assertTrue(setup_stage_complete(stage, setup))
for changed in (
{"status": "INCOMPLETE"}, {"stage": "package-metadata-validated"},
{"installer_sha256": "1" * 64}, {"xelatex_path": r"C:\TeXLive\xelatex.exe"},
{"auto_install_config_readback": "1"}, {"schema_version": 0},
):
with self.subTest(changed=changed):
self.assertFalse(setup_stage_complete({**stage, **changed}, setup))
self.assertFalse(setup_stage_complete({}, setup))
self.assertFalse(setup_stage_complete(stage, {**setup, "xelatex_path": ""}))

def test_lua_negative_requires_complete_message_and_absence_pdf(self):
message = "You need to run LuaTeX to use the grap\nh drawing library."
self.assertTrue(tex_failure("lua-only", 1, message, False))
Expand Down Expand Up @@ -53,6 +69,8 @@ def test_private_index_refresh_is_fail_closed_and_precedes_package_install(self)
self.assertIn("package-metadata-before-install.txt", setup)
self.assertIn("private-package-index-refreshed", setup)
self.assertNotIn("packages update @packages", setup)
self.assertIn("MiKTeX declared package $package is not confirmed installed", setup)
self.assertIn("stage = 'setup-complete'; status = 'SETUP_COMPLETE'", setup)

def test_n1_session_contract_rejects_missing_ownership_and_undo(self):
source = (r"\newcommand{\UserPath}{\path (0,0);}"
Expand Down
Loading