From 8f1ac0c96acd3db4502677c2400b79deade77da0 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 30 Aug 2026 13:40:15 -0400 Subject: [PATCH] ci: transport the candidate baseline as verifiable base64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Run 4964 passed the control (1121 normalised lines, schemas identical) but its candidate print was silently truncated. `cat` of the ~33KB generated file stopped mid-line inside sa.Column('mime', sa.String(length=128) and the runner carried straight on to the next traced command with the step still green. The captured text was 484 lines and 29 tables, and looked entirely plausible — which is exactly what makes it dangerous: a schema definition cut in half is still syntactically suggestive, and nothing in the log says it was cut. Now emitted as base64 at a fixed 120-column width, followed by a sha256, a byte count and a base64 line count. Short lines instead of long ones, and more importantly the receiving end can PROVE it got the whole file rather than trusting that it did. Also found in that output, and the reason the candidate could never have been committed as-is: it references pgvector.sqlalchemy.vector.VECTOR(dim=1152) for head_training_run.weights and image_record.siglip_embedding, but autogenerate does not add the corresponding import. The file would die with NameError on the first run. That is the fourth item on the list of things the generator cannot be trusted with, alongside the two CREATE EXTENSIONs and the HNSW index. --- .forgejo/workflows/baseline.yml | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/.forgejo/workflows/baseline.yml b/.forgejo/workflows/baseline.yml index 96e193e..d7b4b66 100644 --- a/.forgejo/workflows/baseline.yml +++ b/.forgejo/workflows/baseline.yml @@ -131,13 +131,32 @@ jobs: mkdir -p /tmp/versions_held mv alembic/versions/*.py /tmp/versions_held/ 2>/dev/null || true DB_NAME=fc_gen alembic revision --autogenerate -m "baseline" || true - # Printed in full rather than uploaded. ci-requirements.md records - # that this runner cannot do actions/upload-artifact@v4+, and the - # repo dropped the action entirely in 2026-05; the job log is the - # retrieval channel that is actually proven here. - echo "===== BEGIN CANDIDATE BASELINE =====" - cat alembic/versions/*.py + # Printed rather than uploaded: ci-requirements.md records that this + # runner cannot do actions/upload-artifact@v4+, and the repo dropped + # the action entirely in 2026-05, so the job log is the retrieval + # channel actually proven here. + # + # base64, not the raw file. A plain `cat` of the ~33KB candidate was + # TRUNCATED MID-LINE by the runner on run 4964 — it stopped inside + # `sa.Column('mime', sa.String(length=128)` and carried straight on + # to the next traced command, with the step still green. A silent + # cut in the middle of a schema definition is the worst possible + # failure here, because the truncated text still looks like a + # plausible file. + # + # base64 at a fixed narrow width gives many short lines instead of + # few long ones, and — the actual point — a checksum and a line + # count that make truncation DETECTABLE rather than invisible. + set +x + F=$(ls alembic/versions/*.py | head -1) + B64=$(base64 -w 120 "$F") + echo "===== BEGIN CANDIDATE BASELINE (base64) =====" + echo "$B64" echo "===== END CANDIDATE BASELINE =====" + echo "candidate-sha256: $(sha256sum "$F" | cut -d' ' -f1)" + echo "candidate-bytes: $(wc -c < "$F")" + echo "candidate-b64-lines: $(echo "$B64" | wc -l)" + set -x # Put the tree back exactly as it was; this job never mutates state. rm -f alembic/versions/*.py mv /tmp/versions_held/*.py alembic/versions/ 2>/dev/null || true