|
| 1 | +# SPDX-License-Identifier: MPL-2.0 |
| 2 | +# SPDX-FileCopyrightText: 2026 hyperpolymath |
| 3 | +# |
| 4 | +# Session record — 2026-07-29 — Coq proof gate wired + stranded work rescued |
| 5 | +# |
| 6 | +# Human-readable companions: |
| 7 | +# docs/ci/COQ-PROOF-GATE.adoc (the gate: design, gotchas, falsifiers) |
| 8 | +# dev-notes/affinescript-sitrep-2026-07-29.md (estate-local, not in this repo) |
| 9 | + |
| 10 | +[metadata] |
| 11 | +schema = "a2ml/session-record/v1" |
| 12 | +session-date = "2026-07-29" |
| 13 | +session-topic = "wire the formal/ Coq proof gate into CI; rescue feature work from a deleted checkout" |
| 14 | +repo = "hyperpolymath/affinescript" |
| 15 | +human-companion = "docs/ci/COQ-PROOF-GATE.adoc" |
| 16 | +prs = [708, 709, 711] |
| 17 | + |
| 18 | +# ── Outcome 1: the Coq proof gate ────────────────────────────────────── |
| 19 | +# 20 machine-checked proofs existed in formal/ with a real fail-closed |
| 20 | +# runner in formal/justfile, but NO workflow invoked them. Now gated. |
| 21 | + |
| 22 | +[proof-gate] |
| 23 | +workflow = ".github/workflows/coq-proof-gate.yml" |
| 24 | +corpus-path = "formal/" |
| 25 | +corpus-size = 20 |
| 26 | +source-of-truth = "formal/justfile" |
| 27 | +list-parsed-not-copied = true |
| 28 | +fail-closed = true |
| 29 | +prover-in-ci = "8.20.1" |
| 30 | +prover-documented = "8.18" |
| 31 | +prover-pin-reconciled = false |
| 32 | +container-digest = "sha256:e50d77c4c5a9aa0d76ae1b343d79c5f922da3a75054b79c5dc635895438e4674" |
| 33 | +all-proofs-axiom-free = true |
| 34 | +assumptions-result = "Closed under the global context" |
| 35 | +tracking-issue = 513 |
| 36 | + |
| 37 | +[[proof-gate.falsifier]] |
| 38 | +id = "unwired-proof-file" |
| 39 | +method = "add formal/ZZ_Falsifier.v not named in formal/justfile" |
| 40 | +fires = true |
| 41 | +guards = "completeness" |
| 42 | + |
| 43 | +[[proof-gate.falsifier]] |
| 44 | +id = "axiom-dependent-theorem" |
| 45 | +method = "prove a goal via `Axiom cheat : forall P : Prop, P`" |
| 46 | +fires = true |
| 47 | +guards = "Print Assumptions / grep Axioms:" |
| 48 | + |
| 49 | +# Two container faults, each cost one red CI run. Both are properties of |
| 50 | +# coqorg/* images under GitHub Actions and will recur on any new Coq job. |
| 51 | + |
| 52 | +[[proof-gate.gotcha]] |
| 53 | +id = "entrypoint-overridden" |
| 54 | +symptom = "coqc: not found" |
| 55 | +cause = "coqorg installs Coq into the `coq` user's opam switch and exposes it via ENTRYPOINT; GitHub Actions overrides the entrypoint for job containers" |
| 56 | +remedy = "add /home/coq/.opam/*/bin to GITHUB_PATH, globbed not hard-coded, failing loudly if absent" |
| 57 | + |
| 58 | +[[proof-gate.gotcha]] |
| 59 | +id = "shell-fell-back-to-dash" |
| 60 | +symptom = "set: Illegal option -o pipefail" |
| 61 | +cause = "GitHub used `sh -e {0}` despite the image shipping bash 5.2" |
| 62 | +remedy = "declare defaults.run.shell: bash explicitly" |
| 63 | + |
| 64 | +# ── Outcome 2: rescue of stranded work ───────────────────────────────── |
| 65 | +# An estate reorg renamed the working checkout to *.DUPLICATE-superseded-* |
| 66 | +# and then DELETED it mid-session. It held 9 commits present nowhere else. |
| 67 | +# The rename judged duplicates by directory identity, not by git rev-list. |
| 68 | + |
| 69 | +[rescue] |
| 70 | +trigger = "checkout renamed *.DUPLICATE-superseded-2026-07-27 then deleted mid-session" |
| 71 | +misjudgement = "duplicate decided by directory identity rather than `git rev-list` — the directory marked superseded held 9 unpushed commits; the one kept held 0" |
| 72 | +estate-wide = "the same rename was reported backwards in all 8 affected repos" |
| 73 | +commits-at-risk = 9 |
| 74 | +commits-recovered-to-main = 3 |
| 75 | +recovered-via = "git bundle taken before deletion" |
| 76 | +cherry-pick-needed = false |
| 77 | +cherry-pick-avoided-because = "the 3 feature commits were a contiguous linear chain whose base parent was origin/main, so branching preserved original SHAs, authorship and dates" |
| 78 | +pr = 708 |
| 79 | + |
| 80 | +[[rescue.commit]] |
| 81 | +sha = "220d7ca" |
| 82 | +kind = "feature" |
| 83 | +subject = "docs: resolve INT-02 satellite scope deferral" |
| 84 | +closes = 489 |
| 85 | + |
| 86 | +[[rescue.commit]] |
| 87 | +sha = "70ca15e" |
| 88 | +kind = "feature" |
| 89 | +subject = "feat(dom): browser host parity execution harness (INT-11)" |
| 90 | + |
| 91 | +[[rescue.commit]] |
| 92 | +sha = "e959636" |
| 93 | +kind = "feature" |
| 94 | +subject = "feat(cadre): scaffold router navigation runtime wrapper (INT-09)" |
| 95 | + |
| 96 | +# ── Outcome 3: sweep damage found and reverted (uncommitted only) ────── |
| 97 | + |
| 98 | +[[sweep-damage]] |
| 99 | +id = "gitattributes-language-declaration-deleted" |
| 100 | +file = ".gitattributes" |
| 101 | +detail = "the uncommitted tree deleted `*.affine text eol=lf linguist-language=AffineScript` — the single line making GitHub recognise 493 .affine files as the project's own language, and enforcing LF on them" |
| 102 | +state = "reverted-in-working-tree" |
| 103 | +severity = "high" |
| 104 | +advice = "never `git commit -a` in this repo while an estate sweep is active" |
| 105 | + |
| 106 | +[[sweep-damage]] |
| 107 | +id = "gitignore-foreign-template-entries" |
| 108 | +file = ".gitignore" |
| 109 | +detail = "11 additions from another repo's template: composer/*.beam, composer/build/, /target/, *.db*, .cache/, /exports/*. Neither composer/ nor target/ exists; ai-cli-crash-capture/ is TRACKED (5 files) so ignoring it is a no-op" |
| 110 | +state = "reverted-in-working-tree" |
| 111 | +severity = "low" |
| 112 | + |
| 113 | +[[sweep-damage]] |
| 114 | +id = "patch-ecosystem-py-escape-corruption" |
| 115 | +file = "docs/patch_ecosystem.py" |
| 116 | +detail = "arrived via the `merge rogue duplicate repository` commit. Its search strings contain literal BEL/TAB/CR/BS where \\a \\t \\r \\b were interpreted by a non-raw Python string — `affinescript` reads as `ffinescript`, `readBytes` as `eadBytes`. The strings can never match the file, so the script runs, exits 0, and changes nothing" |
| 117 | +state = "still-present-on-main" |
| 118 | +severity = "medium" |
| 119 | +fingerprint = "a leading letter missing after a would-be backslash escape; grep the estate for this shape — it produces scripts that appear to succeed" |
| 120 | + |
| 121 | +# ── Outcome 4: main was left red by a partial merge ──────────────────── |
| 122 | + |
| 123 | +[incident-partial-merge] |
| 124 | +pr-that-broke-main = 709 |
| 125 | +detail = "PR #709 squash-merged the pre-fix revision of the workflow; the verified fix (af7c38c) was on the branch but not in the squash, so main received a gate that fails with `coqc: not found`" |
| 126 | +red-since = "ed4e223" |
| 127 | +repair-pr = 711 |
| 128 | +repair-verified = "workflow_dispatch green on the branch: 20/20 proofs, completeness guard passed, no axioms" |
| 129 | +lesson = "after a squash merge, re-check that the merged tree contains the fix — a green PR check can belong to a superseded commit" |
| 130 | + |
| 131 | +# ── Method notes worth not re-deriving ───────────────────────────────── |
| 132 | + |
| 133 | +[[method-note]] |
| 134 | +id = "always-fetch-before-judging-divergence" |
| 135 | +detail = "a stale remote-tracking ref reported `ahead 16`; after `git fetch` the true figure was 9. Origin had already absorbed 7 via PRs." |
| 136 | + |
| 137 | +[[method-note]] |
| 138 | +id = "a-red-run-is-not-a-red-branch" |
| 139 | +detail = "resolve which commit a CI run belongs to before calling a branch red; a failure observed in a stale duplicate checkout belonged to a superseded commit while main was green." |
| 140 | + |
| 141 | +[[method-note]] |
| 142 | +id = "bundle-verify-is-not-restore" |
| 143 | +detail = "`git bundle verify` proves internal consistency, not that the bundle restores what you wanted. Clone it and assert the expected SHA." |
0 commit comments