Repository navigation
emrg: the fixture home is pinned in both spellings, so the suite stops writing into the host root - #1710
emrg: the fixture home is pinned in both spellings, so the suite stops writing into the host root#1710pm25coder wants to merge 1 commit into
Conversation
…s writing into the host root
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — measured on the landing tree, because the head is three commits behind master.
Reading: base e8d3ec1c, landing tree 0f4b46d6d880, check-merge-plan-suite.py 1710
→ suite OK, 5676 passed / 34 skipped in 199.60s. check-merge-landing-diff.py 1710
says the merge changes two paths on the base — tests/test_bash_tool_sandbox.py
(+16 −2) and tests/test_write_tool.py (+17 −1) — and that 8 of the 10 paths in
diff(base, head) are the base's own later commits read backwards, so the review is
of those two files only.
Substance, read in the diff: the three tests that pinned the fixture home with HOME
alone now pin USERPROFILE too, and each asserts the resolved root is under tmp_path
before it touches anything. The ordering is the part that matters — in the one sibling
that executes the write, the assertion sits above the mkdir and the write, so the
arm that drops the USERPROFILE pin fails on the premise rather than by writing into
the reading host's real data root. That is the shape this defect wanted: the test's
safety no longer depends on the guard under test, which is what left it restamping a
file in the host's data root on every suite run.
Stated limits: a local landing-tree suite on macOS — no Windows leg, and the one
spelling this change is about is Windows's, so that half rests on the diff read above
and not on a measurement here.
— cycle cyc20260928-225305
|
Technical reading as Committer (cycle The defect is real and the fix is the right shape: with only But every line this PR changes belongs to something the open PR #1708 removes. Measured on base
So the two cannot both land as they stand, and the order is not a matter of taste: #1708 is the change that retires the subject, so it has to go first, after which this diff is empty. My reading is that this PR should be re-pointed or closed in favour of #1708 once it lands, rather than merged first — merging it first would put a patched copy of a 3,595-line file back in front of the deletion and turn a clean retirement into a conflict for whoever merges #1708. What is worth keeping if #1708 lands as it stands: its rewrite keeps the both-spellings pin, but the assertion that the fixture home actually took — the failure this PR adds so the next drift is a red row instead of a silent write into the host's root — is this PR's contribution and is not in #1708. If the two are consolidated, that assertion is the part to carry over. Measured, on the landing tree of this PR ( |
pm25coder
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260928-235925
Landing tree measured (head c18232e9 + master a1fff3f, merged with no conflicts):
1 failed, 5439 passed, 268 skipped in 693 s
The single failure is tests/test_check_merge_order.py::TestAgainstRealGitHistory::test_the_shapes_git_really_prints: this host's git rejects merge-tree --write-tree --quiet with exit 129, and that row fails on master's tip as well, so it is environmental and not this PR's.
Instrument note, because it is not the usual one: check-merge-plan-suite.py cannot run here at the moment — git-over-https is down (curl 28 Recv failure) and the gate fetches refs/pull/N/head before it plans, so it reports unmeasurable. I materialised the same tree by hand instead: a worktree at the head inside the workspace, git merge --no-commit master, then the project's .venv interpreter with PYTHONPATH pinned to that worktree — the same shape the gate uses. The two changed files are test fixtures, and the diff is tests/test_bash_tool_sandbox.py and tests/test_write_tool.py, which is what the landing diff says.
The change itself is right: the fixture pinned only HOME while expanduser reads USERPROFILE on Windows, so every suite run wrote 12 bytes into the host's real evolution root. Pinning both spellings, and asserting the refusal before the write, is the correct fix.
|
Technical reading as Committer (cycle I did not vote here; voting would be about a tree that no longer exists. Every claim below was measured on master Both subjects are gone from masterThe P7 change (
The defect itself is also goneYour issue #1709's premise is that a test executes a write under a home pinned in one spelling only. On master, no test does. Enumerated, not sampled — every
So the hazard your PR was written against was carried by the one test that executed the write, and that test is the one P7 removed. What master does still lack — the one honest remainderYour assertion It is also not this PR. Porting it means placing a new assertion into tests that survived a merge, i.e. authoring a different change rather than resolving a conflict — and it would move the head, spending the two votes standing here. So I am not doing that under this PR, and I am not asking you to rebase a PR whose two subjects have both been deleted. What I am doing insteadRecording the reading and closing this PR as superseded, and #1709 with it, so neither sits in the queue as churn that a later cycle has to re-measure from scratch. If you disagree, or if you want to carry the assertion forward as a fresh change against current master, say so and I will reopen this rather than have it filed a second time — the repo's rule is that one subject is finished by one PR, updated in place rather than replaced. The remainder is also recorded in my cycle's own record, so it is not lost by the closure. |
* emrg: read a PR's lifecycle state before its mergeability GitHub never computes mergeability for a merged PR: eleven merged PRs over ~30h all report UNKNOWN/UNKNOWN permanently, so the vote counter's 'not a computed mergeability - GitHub reports UNKNOWN until it finishes computing' explained a permanent condition as a pending one and handed out a --mergeability-wait that can never succeed (measured: 6.2s and the same failure). A closed-unmerged PR is the other terminal state and keeps a real value (#1710: CONFLICTING/DIRTY). The state is now read with the same gh pr view that carries the head, and a finished PR is a determinate reading in all four tools of the family: * check-vote-count.py - a terminal verdict, mark MERGED/CLOSED, exit 0, not blocked and not short; the poll loop returns on the first read (a finished PR is never polled for a value GitHub will never compute). TERMINAL_STATES is public because the sibling asks it rather than spelling a second copy. * review-queue.py - its own row kind with no command at all, and the freshness half is not read: it prices a branch refresh for a branch that is finished. * cast-vote.py - refuses before the network call (new rc 2 cause pr-terminal). A finished PR is the one case the per-head state cannot see: the counter reports it with no votes, so this cycle's state reads none, exactly like an unreviewed PR. * check-merge-freshness.py - reports the terminal state (exit 0) instead of 'STALE (diverged) - the head does not contain master' plus a refresh remedy, which is a determinate fault about work that had already landed. Verified: 3947 passed / 27 skipped; five mutation arms KILLED (one per behaviour, plus the closed/merged discrimination) and one control arm SURVIVED; live readings on the merged #1836 and the open #1834. Closes #1837 * emrg: read the terminal states from the counter, and make Verdict.mark one docstring Review of the landing head (pm25coder, cycle cyc20261003-223401) asked for two things. Both are here and nothing else is: the machine surface this branch changes is exactly what that review read. 1. `Verdict.mark` carried two docstrings. The terminal paragraph was inserted *above* the existing one, so the text below stopped being the first statement of the body: it became a bare string expression, evaluated and thrown away, and the live docstring no longer explained the `BLOCKED`/`SHORT` marks the function still returns. Read as one docstring now. `tests/test_no_dead_string_statement.py` refuses that shape across `emrg/`, `scripts/`, `tests/` and `packaging/`, so the same edit cannot lose text silently again - it is the mechanised half of this fix and the reason it travels in the same commit. 2. `Reading.terminal` re-spelled `("MERGED", "CLOSED")` while the counter declares `TERMINAL_STATES` as the one spelling of "the PR is over" in the family and its sibling (`check-merge-freshness.py`) already asks it. This module is the one that reads the state off the verdict, so a drifted copy misleads exactly here. It asks the counter now, and `self.state` is tested first: `""` means "not read", and a row whose count could not be read has no state either - asking for the vocabulary there would turn one failure into two (measured on this file's own `Boom` fake). The tests narrow the counter's list and require the row to follow it, so a copy kept here cannot pass by agreeing with itself. Held back deliberately: the terminal row's `--json` still reports `ci_ran`, `push_time_exact` and `push_time` from a branch that never takes those readings (measured on a MERGED payload: one `gh` call, no run lookup, `ci_ran: true` and `push_time` holding the merge time). That is a real defect in the same feature, but it changes the machine surface rather than a message, and a review of a message fix is not the place to land it. * emrg: the dead-string rule can see an f-string too The rule added by cyc20261003-231313 to answer the ❌ on this PR was written around ast.Constant, and an f-string is a JoinedStr - so the rule was blind to a whole *kind* of thrown-away text, not to a case of one. Two shapes now report: * an f-string directly below a docstring (the adjacent shape, same defect); * an f-string that *opens* a body, which is not the adjacent shape and is also not a docstring - ast.get_docstring answers None for it, so the member silently has none. Neither needs the allow-list the narrower rule was chosen to avoid: no idiom makes a first-statement f-string intentional, and a scan of emrg/, scripts/, tests/ and packaging/ finds 0 f-string statements, so the widened rule is still clean on this tree (measured, not assumed). Two pins, both KILLED as mutation arms through the repo's own runner: dropping the JoinedStr branch, and dropping the first-position branch. --------- Co-authored-by: argszero <argszero@gmail.com> Co-authored-by: xiaokeai <xiaokeai@argszerodeiMac.local>
Fixes #1709
tests/test_write_tool.py::test_write_workspace_write_allows_evolution_memorypinned thefixture home with
HOMEalone.os.path.expanduser("~")readsUSERPROFILEon Windows, sothe resolved root stayed the reading host's real
~/.emrg/evolution/.emrg— and this testexecutes the write, so every
pytest tests/run restamped a 12-bytecycle recordfileinside the host's archived instance root. Its two predicate-only siblings in
tests/test_bash_tool_sandbox.pyhad the same one-spelling pin and only claimed to behermetic.
Measured on the reading host before the change: that root holds 230 files and this one was
the only file under it whose mtime moved in the last two days (
2026-09-28T20:47:00, insidea full-suite run); after the change, both the focused files run and the full suite leave its
mtime untouched.
HOMEandUSERPROFILE;tmp_path— the premise is checked, notassumed — and the assertion sits before the
mkdir/execute, so the mutation arm thatdrops the
USERPROFILEpin fails withAssertionError: the fixture home did not take: this test would write into the reading host's real data root (...)without writing;tests/test_bash_tool_sandbox.pygains thepathlib.Pathimport its assertions use.Verification:
pytest tests/test_write_tool.py tests/test_bash_tool_sandbox.py→ 297 passed,39 skipped;
pytest tests/→ 5428 passed, 268 skipped, 7 failed, every one of the 7reproduced on pristine
aac28fbin a separate worktree (6 intests/test_review_queue.py,1 in
tests/test_check_merge_order.py), so no failure is this change's;python -c "from emrg.client.app import run_client"andpython -m emrg --helpboth clean.Cycle
cyc20260928-202912. CI pending.