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
32 changes: 32 additions & 0 deletions .github/workflows/llmxive-real-call-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,38 @@ jobs:
- name: Install package and dev deps
run: pip install -e ".[dev]"

# The publisher real-call test (SC-006) and any compile-dependent
# e2e test need a real TeX toolchain: the llmxive.cls full compile
# runs lualatex + bibtex + fontspec. Without TeX Live the publisher's
# `_compile_full` fails, the deposit never happens, and the test can't
# reach `posted`. Install lualatex + the package set llmxive.cls pulls
# in (fontspec, geometry, xcolor, microtype, adjustbox, tabularray,
# tcolorbox, caption, booktabs, listings, natbib, hyperref, fancyhdr,
# fontawesome5, tikz, algorithms, …) via the texlive-* meta-packages.
- name: Install TeX Live (lualatex + bibtex) for paper compiles
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
texlive-luatex texlive-latex-recommended texlive-latex-extra \
texlive-fonts-recommended texlive-fonts-extra texlive-science \
texlive-bibtex-extra texlive-pictures texlive-plain-generic \
texlive-lang-english fonts-noto-core
lualatex --version | head -1
bibtex --version | head -1

# Install the house fonts (Fraunces serif + JetBrains Mono) so
# fontspec resolves them and the real-call compile renders the true
# llmXive style. The class falls back to TeX Gyre Pagella / Inconsolata
# via \IfFontExistsTF when these are absent, but the published PDF
# should match production.
- name: Install llmXive house fonts
run: |
mkdir -p "$HOME/.fonts"
cp papers/.style/fonts/*.ttf "$HOME/.fonts/"
fc-cache -f >/dev/null
fc-list | grep -iE "fraunces|jetbrains" | head || \
echo "WARN: house fonts not registered (class will fall back)"

# FR-031 / T114: Per-PR pre-checks BEFORE running real-call tests.
# If any of these fail, the gate fails fast — saving real-LLM minutes.
- name: Prompt existence check (every prompt referenced by registry exists and parses)
Expand Down
31 changes: 10 additions & 21 deletions tests/real_call/test_publisher_zenodo_sandbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,29 +137,18 @@ def test_publisher_sandbox_e2e_first_publication() -> None:
)
result = agent.run(ctx)

# Stage advanced.
# Stage advanced to `posted`. The CI runner installs TeX Live + the
# house fonts (see the workflow) so the publisher's full llmxive.cls
# compile + real Zenodo Sandbox publish runs for real here, exactly
# as it does locally. If it does NOT reach `posted`, that's a genuine
# failure — surface the agent's outcome + reason in the message
# rather than skipping.
proj = project_state.load(pid, repo_root=_REPO)
assert proj is not None
# The publisher is deterministic and verified end-to-end LOCALLY
# (~10s: full llmxive.cls compile + real Zenodo Sandbox publish).
# When the real publish can't complete in THIS environment, the
# agent records a FAILED outcome and leaves the stage at
# paper_accepted. The two environmental gaps that hit the CI
# real-call runner are: (1) no TeX Live / house fonts for the
# llmxive.cls full compile (the runner installs neither — the
# implementer e2e fixture deliberately uses \documentclass{article}
# to avoid this), and (2) Zenodo Sandbox being transiently
# unreachable. Mirror the missing-creds skip above and treat an
# un-posted result as a skip-with-diagnostic rather than a hard
# failure; publisher LOGIC is covered by tests/unit/test_publisher.py
# and the real sandbox path is exercised locally.
if proj.current_stage != Stage.POSTED:
pytest.skip(
"sandbox publish could not complete in this environment "
f"(outcome={result.outcome.value!r}, "
f"reason={result.failure_reason!r}) — verified locally."
)
assert proj.current_stage == Stage.POSTED
assert proj.current_stage == Stage.POSTED, (
f"publisher did not reach 'posted' "
f"(outcome={result.outcome.value!r}, reason={result.failure_reason!r})"
)

# Publication metadata written; DOI is sandbox-prefixed.
pub = pub_state.load(pid, repo_root=_REPO)
Expand Down
Loading