avoigt1121 Claude Opus 5 commited on
Commit
310b6e9
Β·
1 Parent(s): b676112

fix: main shipped unresolved conflict markers; guard against a repeat

Browse files

`main` carried literal `<<<<<<< HEAD` / `=======` / `>>>>>>>` markers in
memory.md and deployed them to the live Space. Introduced by b676112, a
cherry-pick of the hermetic-suite commit (dbaeaa3) that hit an append-only
collision, was committed unresolved, and was pushed.

Two things made it hard to spot:

- b676112's message describes different work ("verify: routing leg passes;
dispatch blocked by private-Space 404") while its diff is the hermetic
suite. Searching the log for the socket guard does not find it.
- The code half landed correctly. conftest's guard and test_hermetic.py are
complete and right on main; only the prose merge broke. Tests were green
the entire time, because nothing tests prose.

Resolution: both colliding entries kept in chronological order. An
append-only log has no real conflict, only an ordering question.

Also corrected a statement main was making about itself. That cherry-pick
carried a TODO item reading "*This branch's* RESERVED.md is stale β€” it stops
at 0005". True where it was written; false on main, whose ledger correctly
shows 0006 + 0007 published and next free 0008. Rewritten to keep the lesson
(read `git show main:docs/adr/RESERVED.md`, never your working copy) without
the false claim.

NOT carried over from that branch's follow-up (52bb514): its narrative
records a rebase onto main, but main received a merge (80b5e01); and it flags
pancreas_cptac_gdc / pdac_msk_2024 as missing source_import_date, which is
not true here β€” all six artifacts on main carry it, verified, because the
merge re-curated all six rather than trusting a textual JSON merge. Importing
it would have written a history that did not happen and a closed backlog item.

New: test_no_unresolved_conflict_markers_are_committed, over git ls-files.
Prose is the only part of this repo nothing verifies β€” code has tests,
artifacts have `src.curate --check`, licences have the review table. Verified
against the real failure: restoring b676112's memory.md fails the test on all
three marker lines.

Tests: 167 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Files changed (3) hide show
  1. TODO.md +8 -5
  2. memory.md +41 -3
  3. tests/test_hermetic.py +42 -0
TODO.md CHANGED
@@ -229,11 +229,14 @@ the design doc's M0–M4 is the intent behind it β€” see that doc's Β§0).
229
  - [ ] Optional: promote the stub-vs-restructure choice to an ADR if it proves contested.
230
  **Next free is 0008** β€” `main` has 0006 (variantΓ—subtype join) *and* 0007 (re-curation
231
  cadence) published. Claim in `RESERVED.md` on `main`, alone, first.
232
- - [ ] ⚠️ **This branch's `docs/adr/RESERVED.md` is stale β€” it stops at 0005 and says "next free
233
- 0006", both of which are wrong.** It is the per-lane-copy failure the ledger's own postmortem
234
- describes: the shared-row conflict cannot fire between branches, so `ls docs/adr/` and the
235
- local ledger will both hand you a burned number. Check with
236
- `git show main:docs/adr/RESERVED.md` before claiming, and rebase this branch.
 
 
 
237
 
238
  ## Open questions
239
 
 
229
  - [ ] Optional: promote the stub-vs-restructure choice to an ADR if it proves contested.
230
  **Next free is 0008** β€” `main` has 0006 (variantΓ—subtype join) *and* 0007 (re-curation
231
  cadence) published. Claim in `RESERVED.md` on `main`, alone, first.
232
+ - [x] ⚠️ **ADR-ledger near-miss (the fourth), resolved.** A working branch's
233
+ `docs/adr/RESERVED.md` stopped at 0005 and said "next free 0006" while `main` had already
234
+ burned 0006 *and* 0007. `main`'s ledger is correct β€” 0006 + 0007 published, **next free
235
+ 0008** β€” so nothing was mis-numbered. Kept because the near-miss is the lesson: this is the
236
+ per-lane-copy failure the ledger's own postmortem describes, and the shared-row conflict
237
+ cannot fire between branches, so `ls docs/adr/` and your local ledger will both hand you a
238
+ burned number. **Read `git show main:docs/adr/RESERVED.md` before claiming, never your
239
+ working copy.**
240
 
241
  ## Open questions
242
 
memory.md CHANGED
@@ -839,7 +839,6 @@ by running the suite with `socket.connect` blocked outright β€” **111 tests pass
839
  all** (the three UI test modules still touch it, but that is Gradio's mocked-OAuth HF call at
840
  import in a local dev env, not our code and not present on a Space).
841
 
842
- <<<<<<< HEAD
843
 
844
  ---
845
 
@@ -866,7 +865,6 @@ misled again. One contract, with instructions when you miss it.
866
  Ordering is gate-first: an unauthenticated caller gets `denied` and learns nothing about our
867
  inputs β€” pinned by `test_argument_errors_are_reported_only_after_the_auth_gate`. 132 tests (7 new,
868
  alongside the denial-diagnosis guards they mirror).
869
- =======
870
  ---
871
 
872
  ## 2026-07-28 β€” Hermetic is now *enforced*, and the whole suite is hermetic
@@ -940,7 +938,6 @@ reading `SHOWCASE_STATUS.md` before updating it β€” the same habit that caught c
940
  work β€” `gradio[oauth]==6.18.0` (the `oauth` extra is required or the UI modules fail to import at
941
  all), plus the rest of `requirements.txt` and pytest. Previously the memory said to borrow
942
  `DecoupleRpy_Agent/.venv`.
943
- >>>>>>> dbaeaa3 (tests: enforce hermeticity with a socket guard; last 3 network-touching modules closed)
944
 
945
  ---
946
 
@@ -974,3 +971,44 @@ credential operation for a human. Worth noting the order of failure for whoever
974
  `HF_TOKEN` unset the symptom is a 404 (invisible private repo); once set, the next thing exercised
975
  is the allow-list β€” and the identity it resolves to must be on `ALLOWED_IDS` here
976
  (`anne-voigt,cpelz741` today).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
839
  all** (the three UI test modules still touch it, but that is Gradio's mocked-OAuth HF call at
840
  import in a local dev env, not our code and not present on a Space).
841
 
 
842
 
843
  ---
844
 
 
865
  Ordering is gate-first: an unauthenticated caller gets `denied` and learns nothing about our
866
  inputs β€” pinned by `test_argument_errors_are_reported_only_after_the_auth_gate`. 132 tests (7 new,
867
  alongside the denial-diagnosis guards they mirror).
 
868
  ---
869
 
870
  ## 2026-07-28 β€” Hermetic is now *enforced*, and the whole suite is hermetic
 
938
  work β€” `gradio[oauth]==6.18.0` (the `oauth` extra is required or the UI modules fail to import at
939
  all), plus the rest of `requirements.txt` and pytest. Previously the memory said to borrow
940
  `DecoupleRpy_Agent/.venv`.
 
941
 
942
  ---
943
 
 
971
  `HF_TOKEN` unset the symptom is a 404 (invisible private repo); once set, the next thing exercised
972
  is the allow-list β€” and the identity it resolves to must be on `ALLOWED_IDS` here
973
  (`anne-voigt,cpelz741` today).
974
+
975
+ ---
976
+
977
+ ## 2026-07-28 β€” Repaired `main`: conflict markers were committed and deployed
978
+
979
+ `main` carried **literal `<<<<<<< HEAD` / `=======` / `>>>>>>>` markers in `memory.md`**, and they
980
+ went out to the live Space. Introduced by `b676112`, which was a cherry-pick of the hermetic-suite
981
+ commit (`dbaeaa3`) that hit an append-only collision in `memory.md`, was committed unresolved, and
982
+ was pushed. Two further things about that commit are worth knowing, because both make it hard to
983
+ find again:
984
+
985
+ - **Its message describes different work.** It reads "verify: routing leg passes; dispatch blocked
986
+ by private-Space 404", but its diff is the hermetic suite β€” `tests/conftest.py` (+109),
987
+ `tests/test_hermetic.py` (+69), plus TODO/memory. Searching the log for the socket guard will
988
+ not find it.
989
+ - **The code half landed fine.** The socket guard and `test_hermetic.py` are correct and complete
990
+ on `main`; only the prose merge was broken. So this was cosmetically invisible β€” tests pass with
991
+ conflict markers sitting in `memory.md`, because nothing tests prose.
992
+
993
+ **Repair:** kept both colliding entries (machine-endpoint argument errors, and hermetic
994
+ enforcement) in chronological order β€” an append-only log has no genuine conflict, only an ordering
995
+ question.
996
+
997
+ **Also corrected a statement `main` was making about itself.** That cherry-pick carried over a
998
+ TODO item reading "*This branch's* `RESERVED.md` is stale β€” it stops at 0005". True of the branch
999
+ it was written on; **false on `main`**, whose ledger correctly shows 0006 + 0007 published and next
1000
+ free 0008. Rewritten to keep the lesson (check `git show main:docs/adr/RESERVED.md`, never your
1001
+ working copy β€” the per-lane-copy failure means the shared-row conflict cannot fire) without the
1002
+ false claim.
1003
+
1004
+ **Deliberately NOT carried over** from that branch's follow-up commit (`52bb514`): its narrative
1005
+ records a *rebase* onto main, but `main` received a **merge** (`80b5e01`) instead, and it flags a
1006
+ gap β€” `pancreas_cptac_gdc` / `pdac_msk_2024` missing `source_import_date` β€” that **does not exist
1007
+ here**. All six artifacts on `main` carry it (verified), because the merge re-curated all six
1008
+ rather than trusting git's textual merge of the JSON. Importing that entry would have written a
1009
+ history that did not happen and a backlog item already closed.
1010
+
1011
+ **The generalizable bit:** prose is the only part of this repo nothing verifies. Code has tests,
1012
+ artifacts have `--check`, licences have the review table β€” `memory.md` and `TODO.md` have nothing,
1013
+ so a broken merge in them survives a fully green suite and ships. Worth a lint step (grep the tree
1014
+ for conflict markers) if it happens twice.
tests/test_hermetic.py CHANGED
@@ -67,3 +67,45 @@ def test_ui_modules_import_without_network(module):
67
  suite is supposed to have stopped having. Importing them here proves the seam still holds.
68
  """
69
  __import__(module)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  suite is supposed to have stopped having. Importing them here proves the seam still holds.
68
  """
69
  __import__(module)
70
+
71
+
72
+ # --------------------------------------------------------------------------- #
73
+ # Unresolved conflict markers β€” the one class of breakage nothing else catches
74
+ # --------------------------------------------------------------------------- #
75
+ def test_no_unresolved_conflict_markers_are_committed():
76
+ """No tracked file may contain a merge-conflict marker.
77
+
78
+ This exists because it happened: `main` shipped `memory.md` with literal `<<<<<<< HEAD`
79
+ markers to the live Space, and the suite stayed green the whole time. Code has tests,
80
+ artifacts have `src.curate --check`, licences have the review table β€” **prose has nothing**,
81
+ so a botched merge in `memory.md` or `TODO.md` is invisible to everything except a reader.
82
+
83
+ Checking tracked files via git (rather than walking the tree) keeps the venv, caches and
84
+ curated scratch out of it, and means a file is covered the moment it is added.
85
+ """
86
+ import subprocess
87
+ from pathlib import Path
88
+
89
+ root = Path(__file__).resolve().parents[1]
90
+ tracked = subprocess.run(
91
+ ["git", "-C", str(root), "ls-files", "-z"],
92
+ capture_output=True, text=True, check=True,
93
+ ).stdout.split("\0")
94
+
95
+ # Split so this file's own strings are not a match when it scans itself.
96
+ markers = ("<" * 7, "=" * 7, ">" * 7)
97
+ offenders = []
98
+ for name in filter(None, tracked):
99
+ path = root / name
100
+ if not path.is_file() or path.suffix in {".png", ".jpg", ".ico"}:
101
+ continue
102
+ try:
103
+ lines = path.read_text(encoding="utf-8").splitlines()
104
+ except (UnicodeDecodeError, OSError):
105
+ continue # binary or unreadable β€” not prose, not our concern
106
+ for n, line in enumerate(lines, 1):
107
+ # A marker is only a marker at the START of a line, which is what git writes.
108
+ if any(line.startswith(m) for m in markers) and path.name != Path(__file__).name:
109
+ offenders.append(f"{name}:{n}: {line[:60]}")
110
+
111
+ assert not offenders, "unresolved conflict markers committed:\n" + "\n".join(offenders)