⚠️The invocation on PKG-09's card and in the tool's own docstring runs only half the check.
The container runs as uid 0 against a checkout owned by the operator, and git refuses: fatal: detected dubious ownership in repository at '/w/goodwe-addon'. _git returns non-zero, last_version_change() returns None, and the silent-no-op check — the reason PKG-09 exists — reports SKIPPED.
Measured on the documented command: ⚠️ SKIPPED: ... INCONCLUSIVE, not clean / NOT CLEARED. With --user $(id -u):$(id -g), unchanged otherwise: no runtime change since the last bump / CLEARED for deploy.
⚠️The two halves were mutually exclusive across the two documented environments — in the container the validator ran and git skipped; on a bare host git ran and the validator skipped on aiohttp. Neither documented command ran both. The pre-0.9.0 clearance was sound only because it was driven as two separate invocations.
⚠️Invisible in the only case anyone had run: main() consults git only when shipped == deployed, and every real run so far compared 0.7.0 against 0.9.0.
Fixed in _git() with safe.directory, not by documenting --user — the tool should be correct however it is invoked.
Why the tests could not see it
test_version_gate.py invokes the gate against fixtures it creates as its own uid, so no fixture could meet an ownership mismatch. Habit 4 in a fourth shape, inside the file written to prevent it. Two fixtures added: a directory that is not a git repo (must exit 2, INCONCLUSIVE, never CLEARED), and exit codes pinned by value — != 0 is satisfied by collapsing NOT-CLEARED into REFUSED, and 1 vs 2 mean different things to an operator.
⚠️ **The invocation on PKG-09's card and in the tool's own docstring runs only half the check.**
The container runs as uid 0 against a checkout owned by the operator, and git refuses:
`fatal: detected dubious ownership in repository at '/w/goodwe-addon'`. `_git` returns non-zero, `last_version_change()` returns None, and **the silent-no-op check — the reason PKG-09 exists — reports SKIPPED.**
Measured on the documented command: `⚠️ SKIPPED: ... INCONCLUSIVE, not clean` / `NOT CLEARED`. With `--user $(id -u):$(id -g)`, unchanged otherwise: `no runtime change since the last bump` / `CLEARED for deploy`.
⚠️ **The two halves were mutually exclusive across the two documented environments** — in the container the validator ran and git skipped; on a bare host git ran and the validator skipped on aiohttp. **Neither documented command ran both.** The pre-0.9.0 clearance was sound only because it was driven as two separate invocations.
⚠️ **Invisible in the only case anyone had run**: `main()` consults git only when `shipped == deployed`, and every real run so far compared 0.7.0 against 0.9.0.
Fixed in `_git()` with `safe.directory`, not by documenting `--user` — the tool should be correct however it is invoked.
## Why the tests could not see it
`test_version_gate.py` invokes the gate against fixtures it creates as its own uid, so no fixture could meet an ownership mismatch. Habit 4 in a **fourth** shape, inside the file written to prevent it. Two fixtures added: a directory that is not a git repo (must exit 2, INCONCLUSIVE, never CLEARED), and **exit codes pinned by value** — `!= 0` is satisfied by collapsing NOT-CLEARED into REFUSED, and 1 vs 2 mean different things to an operator.
Suite: 26 files, all pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
⚠️ THE INVOCATION ON PKG-09's CARD AND IN THE TOOL'S OWN DOCSTRING RUNS ONLY
HALF THE CHECK. The container runs as uid 0 against a checkout owned by the
operator, and git refuses that:
fatal: detected dubious ownership in repository at '/w/goodwe-addon'
`_git` returned non-zero, `last_version_change()` returned None, and the
silent-no-op check - THE REASON PKG-09 EXISTS - reported SKIPPED. Measured, on
the documented command against release/1.0:
⚠️ SKIPPED: could not ask git what changed since the last bump;
the no-op check is INCONCLUSIVE, not clean
NOT CLEARED
and with `--user $(id -u):$(id -g)`, unchanged otherwise:
no runtime change since the last bump - nothing to deploy
CLEARED for deploy.
⚠️ THE TWO HALVES WERE MUTUALLY EXCLUSIVE ACROSS THE TWO DOCUMENTED
ENVIRONMENTS. In the container the validator ran and git skipped; on a bare host
git ran and the validator skipped on aiohttp. NEITHER DOCUMENTED COMMAND RAN
BOTH. The pre-0.9.0 clearance was sound only because it happened to be driven as
two separate invocations.
⚠️ AND IT WAS INVISIBLE IN THE ONLY CASE ANYONE HAD RUN. `main()` consults the
git result only when `shipped == deployed`; every real run so far compared 0.7.0
against 0.9.0 and printed its verdict without ever needing git.
FIXED IN `_git()` WITH `safe.directory`, NOT BY DOCUMENTING `--user`. The tool
should be correct however it is invoked rather than requiring every future
caller to remember a flag; the read is read-only, on a repository the operator
is about to deploy from.
⚠️ WHY THE TESTS COULD NOT SEE IT, WHICH IS THE FINDING BEHIND THE FINDING.
`test_version_gate.py` invokes the gate with `sys.executable` against fixtures
it creates as its own uid, so no fixture could ever meet an ownership mismatch.
MUTATION.md habit 4 in a fourth shape, inside the file written to prevent it -
after the pickaxe bug, after the one-bump history, after the filter-only
survivor. Two fixtures added:
- a directory that is NOT a git repository, so the lookup genuinely fails:
the gate must exit 2 saying INCONCLUSIVE and must NOT say CLEARED.
- ⚠️ THE EXIT CODES PINNED BY VALUE, NOT BY TRUTHINESS. `returncode != 0` is
satisfied by collapsing NOT-CLEARED into REFUSED, which review found the
earlier draft could not tell apart. 1 says "this deploy is wrong"; 2 says
"nobody checked". Driven: collapsing 2 into 1 now goes red on exactly that
check.
Suite: 26 files, all pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
Review found `-c safe.directory={where}` and `-c safe.directory=*` set on the
same invocation, the specific value redundant once the wildcard is present.
Dropped the WILDCARD rather than the specific path, which is the opposite of
the suggestion and the tighter end of it: `_git()` always runs `-C where`, so
the only repository it ever reads is the one it was pointed at, and naming that
one path grants exactly the trust the tool needs. `*` granted trust to every
repository on the machine for the lifetime of each subprocess - harmless for
read-only `log`/`show` with no tty, as review measured, but broader than the
job.
Verified after the change: the documented container invocation still runs BOTH
halves and reports `no runtime change since the last bump` / `CLEARED for
deploy`, so the fix this branch exists for is intact.
Suite: 26 files, all pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
admin
merged commit 6e7b23388c into release/1.02026-09-07 17:34:18 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
⚠️ The invocation on PKG-09's card and in the tool's own docstring runs only half the check.
The container runs as uid 0 against a checkout owned by the operator, and git refuses:
fatal: detected dubious ownership in repository at '/w/goodwe-addon'._gitreturns non-zero,last_version_change()returns None, and the silent-no-op check — the reason PKG-09 exists — reports SKIPPED.Measured on the documented command:
⚠️ SKIPPED: ... INCONCLUSIVE, not clean/NOT CLEARED. With--user $(id -u):$(id -g), unchanged otherwise:no runtime change since the last bump/CLEARED for deploy.⚠️ The two halves were mutually exclusive across the two documented environments — in the container the validator ran and git skipped; on a bare host git ran and the validator skipped on aiohttp. Neither documented command ran both. The pre-0.9.0 clearance was sound only because it was driven as two separate invocations.
⚠️ Invisible in the only case anyone had run:
main()consults git only whenshipped == deployed, and every real run so far compared 0.7.0 against 0.9.0.Fixed in
_git()withsafe.directory, not by documenting--user— the tool should be correct however it is invoked.Why the tests could not see it
test_version_gate.pyinvokes the gate against fixtures it creates as its own uid, so no fixture could meet an ownership mismatch. Habit 4 in a fourth shape, inside the file written to prevent it. Two fixtures added: a directory that is not a git repo (must exit 2, INCONCLUSIVE, never CLEARED), and exit codes pinned by value —!= 0is satisfied by collapsing NOT-CLEARED into REFUSED, and 1 vs 2 mean different things to an operator.Suite: 26 files, all pass.
🤖 Generated with Claude Code
https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU
Review found `-c safe.directory={where}` and `-c safe.directory=*` set on the same invocation, the specific value redundant once the wildcard is present. Dropped the WILDCARD rather than the specific path, which is the opposite of the suggestion and the tighter end of it: `_git()` always runs `-C where`, so the only repository it ever reads is the one it was pointed at, and naming that one path grants exactly the trust the tool needs. `*` granted trust to every repository on the machine for the lifetime of each subprocess - harmless for read-only `log`/`show` with no tty, as review measured, but broader than the job. Verified after the change: the documented container invocation still runs BOTH halves and reports `no runtime change since the last bump` / `CLEARED for deploy`, so the fix this branch exists for is intact. Suite: 26 files, all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BwRLw7eKYj2byVdwB6kbjU