Release v0.78.2 — reproducible Windows test gate, encoding-corruption guard, Python SDK packaging fix
Date: 2026-05-07
Tag: v0.78.2
Summary
Audit-remediation patch on the v0.78.0 line. Three coordinated fixes plus one CI-hygiene tighten:
- Reproducible default test gate.
pnpm testnow runs green on Windows with no--maxWorkers=1override and no other flag overrides, on bothapps/editorandapps/apifile-mode. Mirrors the existingvitest.file.config.tsWindows-singleFork pattern in the default Vitest configs so the parallel-worker contention that surfaced inlogin-identity.test.tsx,ChartNodeView.test.tsx,template-labels.route.test.ts, andauth-scopes.test.tsis gone for default runs as well. - U+FFFD encoding guard.
scripts/check-encoding.shnow detects U+FFFD replacement characters (not just Latin-1 mojibake) and runs in CI as a fail-fast lint stage. Cleaned 14 U+FFFD bytes across 4 tracked files (comment-divider corruption introduced by an editor pipeline that silently substituted for bytes it could not decode). - Python SDK packaging fix. Renamed
packages/sdk-python/docuforge/→packages/sdk-python/pulp_engine/so the importable module matches the PyPI distribution name (pulp-enginewith hyphen →pulp_enginewith underscore per Python identifier rules). Replaced 21 invalidfrom pulp-engine import ...andfrom docuforge import ...lines across 14 SDK files. Added apython3 -m compileallCI guard that catches the next syntax-level regression at PR time. Local editable-install round-trip verified:pip install -e packages/sdk-python && python -c "from pulp_engine import PulpEngineClient"resolves. - Tag-glob hygiene.
release.ymland the two SDK publish workflows now skip-rc*,-alpha*,-beta*tags. Pushingv0.78.2-rc1previously triggered three release-style workflows that all failed at the version-consistency guardrail (harmless red-X noise); rc tags are now purely informational.
See docs/audits/2026-05-07-rating-7.8.md (or audit context conversation) for the rationale tying these to the audit’s Release Blockers and Polish rows.
No contract changes. No new features. No OpenAPI / SDK regen needed.
What landed
Reproducible Windows test gate (Workstream A)
apps/api/vitest.config.ts— addedpool: 'forks'andpoolOptions.forks.singleFork: process.platform === 'win32', mirroring the existingvitest.file.config.tspattern. Windows timeouts also bumped (testTimeout: 60_000,hookTimeout: 30_000) to match file-mode.apps/editor/vitest.config.ts— samesingleFork: process.platform === 'win32'shape.- Linux retains parallel forks; no throughput regression on the existing CI gate.
- Local Windows verification (no flag overrides): editor
pnpm testpasses 95 files / 1318 tests, apipnpm test:filepasses 73 files / 1241 tests. CIci-windowsjob goes green end-to-end.
Encoding-corruption guard (Workstream F)
scripts/check-encoding.sh— extended PATTERNS to include literal U+FFFD (\xef\xbf\xbd) alongside the existing Latin-1 mojibake patterns. Excluded.astro/and_generated_docs/(gitignored build mirrors that aren’t authoritative)..github/workflows/ci.yml— wiredbash scripts/check-encoding.shas an early lint stage, beforepnpm lint. Catches future U+FFFD reintroductions at PR time.- 14 U+FFFD bytes replaced with U+2500 (box-drawing horizontal) across:
apps/api/src/lib/render-queue-tracker.ts(3 bytes in a comment divider)apps/api/src/routes/audit-events/audit-events.routes.ts(6 bytes across 2 dividers)- docs/deployment-guide.md (3 bytes in the prod-config divider — the one the audit specifically called out)
packages/pdf-renderer/src/renderer.ts(2 bytes in a layer-2 divider)
Python SDK packaging fix (Workstream B)
git mv packages/sdk-python/docuforge → packages/sdk-python/pulp_engine(history preserved, similarity 96–100% per file).packages/sdk-python/pyproject.toml—[tool.hatch.build.targets.wheel] packages = ["pulp_engine"]and the sdistincludelist updated to match. PyPI distribution name stayspulp-engine(legal hyphen). Wheel filename becomespulp_engine-0.78.2-py3-none-any.whlper PEP 427.- 21 import +
mock.patch()string replacements across 14 SDK files:from pulp-engine import→from pulp_engine import,from docuforge import→from pulp_engine import,"pulp-engine.resources.batch.*"→"pulp_engine.resources.batch.*". - Stale
docuforge/pulp-engineworkaround comments removed fromtests/conftest.py,tests/test_errors.py, anddocs/api-errors.md. The “usedocuforgefor now” note in api-errors.md was a v0.78.0-era forward-looking marker; the rename obsoletes it. - docs/sdk-generation-guide.md directory path corrected:
packages/sdk-python/pulp-engine/→packages/sdk-python/pulp_engine/. - docs/release-v0.61.0.md python example fixed (was
from pulp-engine import Pulp Engine— never compiled even at original publication). - New CI guard at
.github/workflows/ci.yml:python3 -m compileall packages/sdk-python/pulp_engine packages/sdk-python/testsruns right after the encoding check. Shell-independent and recursive — won’t miss a file like a glob would. ~5s on the existing Linux runner. - Per memory/project_v075_6_shipped.md (no PyPI publish has actually shipped for any v0.75.X+), this rename is not breaking for any live user.
Tag-glob hygiene
.github/workflows/release.yml,.github/workflows/publish-sdk-typescript.yml,.github/workflows/publish-sdk-python.yml— added negation patterns to theon.push.tagsblock:tags: - "v*.*.*" - "!v*-rc*" - "!v*-alpha*" - "!v*-beta*"- Verified empirically: pushing
v0.78.2-rc1triggered 3 workflows (Release / Publish TS / Publish Python — all failed at version-consistency or auth, no actual publish attempted). Pushingv0.78.2-rc2after this fix triggered zero new release-style runs.
Per-template-rate-limit test fix (intermediate, surfaced during rc validation)
apps/api/src/__tests__/per-template-rate-limit.test.ts— bumped the “resets counter after window expires” test from a 1ms window / 5ms wait to a 50ms window / 100ms wait. The original timing was wall-clock fragile under Windows singleFork (three sequential synchronous.check()calls could span >1ms, so the bucket expired between them and the exhaust assertion flipped toallowed=true). No production code change.
Why no SDK / OpenAPI churn
The Python SDK rename changes the importable module name and the on-disk source layout, but the wire shapes, error envelopes, and OpenAPI spec are untouched. Existing TypeScript SDK callers see no change at all (the TS SDK rename observation in the audit was a separate doc-naming concern; the @pulp-engine/sdk package and its directory packages/sdk-typescript/ keep their current names).
PyPI / npm Trusted Publisher entries remain a one-time registry-side configuration carried over from v0.78.0; nothing in this release attempts publishes that didn’t previously work.
Verification
- Local (Windows, on the rc2 tag tree):
bash scripts/check-encoding.sh,python -m compileall packages/sdk-python/pulp_engine packages/sdk-python/tests,pnpm lint,pnpm typecheck,pnpm build,pnpm --filter @pulp-engine/editor test,pnpm --filter @pulp-engine/api test:file— all green with no flag overrides. - CI on
1d73a2e(the rc2 commit): 9/9 jobs green, includingci-windowsfile-mode + installer smoke andDocker build + smoke test. - Editable install round-trip:
pip install -e packages/sdk-python && python -c "from pulp_engine import PulpEngineClient, PulpEngineError, PaginatedResult, BinaryResult, PptxResult, paginate"succeeds. SDK pytest: 62 passed.
Known residual
- Coverage gate runtime drift on Linux CI. The rc2 run’s Coverage gate took longer than the prior fe5852e baseline (slow runner, not a code regression). The gate still passed. Worth tracking if the trend continues.
- Per-template-rate-limit test:file flake on Windows local runs. A single transient failure surfaced during the local verification recipe on the rc2 tree but did not reproduce on a second run. This is environmental (Windows wall-clock variance under singleFork) and is a separate test from the one fixed in c786733; logged as a follow-up to investigate which test was the actual flake.
- Audit blockers C–F deferred to follow-up patches per the internal audit-remediation plan: OpenAPI version + route-security drift (Workstream C), HA Redis/S3 automated checks (Workstream D), complexity hotspot first-carve (Workstream E). v0.78.2’s scope was reproducible-gate + Python SDK + hygiene only.