diff --git a/.chock/bin/_chock_runtime.py b/.chock/bin/_chock_runtime.py index 0fb9b3de..336e74a1 100644 --- a/.chock/bin/_chock_runtime.py +++ b/.chock/bin/_chock_runtime.py @@ -2106,15 +2106,27 @@ def _repo_stop_path(text): text = _repo_stop_unquote(rest[rest.find('/'):] if '/' in rest else '') return text if 0 < len(text) <= _REPO_STOP_PATH_MAX and '\x00' not in text else None -def _repo_stop_words(command): - """Each word of a shell command, and the value of each `--flag=value` word: best effort, never raises.""" - lexer = _chock_shlex.shlex(command, posix=True, punctuation_chars=True) +def _repo_stop_split(command, posix): + lexer = _chock_shlex.shlex(command, posix=posix, punctuation_chars=True) lexer.whitespace_split = True try: - words = list(lexer) + return list(lexer) except ValueError: - words = command.split() - return words + [word.split('=', 1)[1] for word in words if '=' in word] + return command.split() + +def _repo_stop_windows(word): + """A word read as a Windows path (`C:\\repo\\x` kept, quotes dropped), spelled with `/`; None when it has no drive.""" + path = _chock_PureWindowsPath(word.strip('"\'')) + return path.as_posix() if path.drive else None + +def _repo_stop_words(command): + """Each word of a shell command, the value of each `--flag=value` word, and each Windows-path reading of a word + (a POSIX split eats the backslashes of `C:\\repo\\x`): best effort, never raises.""" + words = _repo_stop_split(command, posix=True) + raw = _repo_stop_split(command, posix=False) + words += [word.strip('"\'') for word in raw if '\\' in word] + words += [word.split('=', 1)[1] for word in words if '=' in word] + return words + [path for path in map(_repo_stop_windows, raw) if path] def _repo_stop_named(raw): """Every string anywhere in a payload that may name a path (`file://` URIs decoded): each client nests and diff --git a/.chock/bin/claude_code.py b/.chock/bin/claude_code.py index c3ed5fe2..ee95433b 100755 --- a/.chock/bin/claude_code.py +++ b/.chock/bin/claude_code.py @@ -809,7 +809,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/codex_cli.py b/.chock/bin/codex_cli.py index bac13ade..9f24d0d4 100755 --- a/.chock/bin/codex_cli.py +++ b/.chock/bin/codex_cli.py @@ -777,7 +777,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/cursor.py b/.chock/bin/cursor.py index 703ff7ef..ef075ec6 100755 --- a/.chock/bin/cursor.py +++ b/.chock/bin/cursor.py @@ -670,7 +670,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/devin.py b/.chock/bin/devin.py index d14adb32..627c4116 100755 --- a/.chock/bin/devin.py +++ b/.chock/bin/devin.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/gemini_cli.py b/.chock/bin/gemini_cli.py index 2068cdf8..2990ff7e 100755 --- a/.chock/bin/gemini_cli.py +++ b/.chock/bin/gemini_cli.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/grok.py b/.chock/bin/grok.py index ccee4c79..16b86489 100755 --- a/.chock/bin/grok.py +++ b/.chock/bin/grok.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/tabnine.py b/.chock/bin/tabnine.py index 441d5f08..d513535a 100755 --- a/.chock/bin/tabnine.py +++ b/.chock/bin/tabnine.py @@ -732,7 +732,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/vscode_copilot.py b/.chock/bin/vscode_copilot.py index d354df15..ab04974d 100755 --- a/.chock/bin/vscode_copilot.py +++ b/.chock/bin/vscode_copilot.py @@ -560,7 +560,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.chock/bin/windsurf.py b/.chock/bin/windsurf.py index 848b2587..ee68c3b5 100755 --- a/.chock/bin/windsurf.py +++ b/.chock/bin/windsurf.py @@ -629,7 +629,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/.github/workflows/windows-paths.yml b/.github/workflows/windows-paths.yml index f22905c4..dc439d3e 100644 --- a/.github/workflows/windows-paths.yml +++ b/.github/workflows/windows-paths.yml @@ -1,8 +1,8 @@ name: Windows paths # Windows path spellings in the agent write gate (drive-letter case, `/c:/` roots, either -# slash). Linux cannot exercise them, and CI's full matrix does not run on PRs, so this one -# targeted file runs on Windows every time. +# slash), the repo stop, pack hashing, install and scaffold. Linux cannot exercise them, and CI's +# full matrix does not run on PRs, so these targeted files run on Windows every time. on: push: @@ -39,5 +39,13 @@ jobs: python -m pip install --require-hashes --upgrade -r requirements/pip.txt python -m pip install --require-hashes -r requirements/dev.txt && pip install -e . --no-deps - - name: Windows write-gate path tests - run: pytest -q tests/test_cursor_windows_write_gate.py + - name: Windows path tests + run: >- + pytest -q + tests/test_cursor_windows_write_gate.py + tests/test_repo_stop_gap1d.py + tests/test_pack_hash_platform.py + tests/test_install_command.py + tests/test_install_local.py + tests/test_scaffold_new.py + tests/test_scaffold_kinds.py diff --git a/src/chock/gate/repo_stop.py b/src/chock/gate/repo_stop.py index 23b20275..cd1a1c90 100644 --- a/src/chock/gate/repo_stop.py +++ b/src/chock/gate/repo_stop.py @@ -17,7 +17,7 @@ import shlex import sys import time -from pathlib import Path +from pathlib import Path, PureWindowsPath from .decision_log import DLOG_ROUTE_SYNC, runtime_route from .runner.halt import ( @@ -64,15 +64,29 @@ def _repo_stop_path(text): return text if 0 < len(text) <= _REPO_STOP_PATH_MAX and "\x00" not in text else None -def _repo_stop_words(command): - """Each word of a shell command, and the value of each `--flag=value` word: best effort, never raises.""" - lexer = shlex.shlex(command, posix=True, punctuation_chars=True) +def _repo_stop_split(command, posix): + lexer = shlex.shlex(command, posix=posix, punctuation_chars=True) lexer.whitespace_split = True try: - words = list(lexer) + return list(lexer) except ValueError: - words = command.split() - return words + [word.split("=", 1)[1] for word in words if "=" in word] + return command.split() + + +def _repo_stop_windows(word): + """A word read as a Windows path (`C:\\repo\\x` kept, quotes dropped), spelled with `/`; None when it has no drive.""" + path = PureWindowsPath(word.strip("\"'")) + return path.as_posix() if path.drive else None + + +def _repo_stop_words(command): + """Each word of a shell command, the value of each `--flag=value` word, and each Windows-path reading of a word + (a POSIX split eats the backslashes of `C:\\repo\\x`): best effort, never raises.""" + words = _repo_stop_split(command, posix=True) + raw = _repo_stop_split(command, posix=False) + words += [word.strip("\"'") for word in raw if "\\" in word] + words += [word.split("=", 1)[1] for word in words if "=" in word] + return words + [path for path in map(_repo_stop_windows, raw) if path] def _repo_stop_named(raw): diff --git a/src/chock/validation/selection_source.py b/src/chock/validation/selection_source.py index fc7f967f..7e01621d 100644 --- a/src/chock/validation/selection_source.py +++ b/src/chock/validation/selection_source.py @@ -28,7 +28,7 @@ def _mode_at(repo_root: Path, ref: str, path: Path) -> str | None: """The git mode of `path` at `ref`; None when the revision has nothing there.""" result = _git(repo_root, "ls-tree", ref, "--", path.as_posix()) if result.returncode != 0: - msg = f"cannot list {path} at {ref}: {result.stderr.strip()}" + msg = f"cannot list {path.as_posix()} at {ref}: {result.stderr.strip()}" raise SelectionInvalidError(msg) return result.stdout.split(maxsplit=1)[0] if result.stdout.strip() else None @@ -41,7 +41,9 @@ def _at_ref(repo_root: Path, kind: Kind, ref: str) -> str | None: return None if mode != _TREE if part == rel.parent else mode not in _REGULAR: what = "a file" if mode in _REGULAR else _MODES.get(mode, f"object mode {mode}") - msg = f"{part} is {what} at {ref}, not {want}; the base selection cannot be trusted as a baseline" + msg = ( + f"{part.as_posix()} is {what} at {ref}, not {want}; the base selection cannot be trusted as a baseline" + ) raise SelectionInvalidError(msg) result = _git(repo_root, "show", f"{ref}:{kind.filename}") if result.returncode != 0: @@ -59,10 +61,12 @@ def _in_worktree(repo_root: Path, kind: Kind) -> str | None: except FileNotFoundError: return None if stat.S_ISLNK(mode) or (part == rel and not stat.S_ISREG(mode)): - msg = f"{part} is a symlink or not a regular file; a selection must be a committed regular file" + msg = f"{part.as_posix()} is a symlink or not a regular file; a selection must be a committed regular file" raise SelectionInvalidError(msg) if part != rel and not stat.S_ISDIR(mode): - msg = f"{part} is a file, not a directory; the runtime finds no selection under it and falls back" + msg = ( + f"{part.as_posix()} is a file, not a directory; the runtime finds no selection under it and falls back" + ) raise SelectionInvalidError(msg) return (repo_root / rel).read_text(encoding="utf-8") diff --git a/tests/fixtures/runtime_goldens/_chock_runtime.py b/tests/fixtures/runtime_goldens/_chock_runtime.py index 0fb9b3de..336e74a1 100644 --- a/tests/fixtures/runtime_goldens/_chock_runtime.py +++ b/tests/fixtures/runtime_goldens/_chock_runtime.py @@ -2106,15 +2106,27 @@ def _repo_stop_path(text): text = _repo_stop_unquote(rest[rest.find('/'):] if '/' in rest else '') return text if 0 < len(text) <= _REPO_STOP_PATH_MAX and '\x00' not in text else None -def _repo_stop_words(command): - """Each word of a shell command, and the value of each `--flag=value` word: best effort, never raises.""" - lexer = _chock_shlex.shlex(command, posix=True, punctuation_chars=True) +def _repo_stop_split(command, posix): + lexer = _chock_shlex.shlex(command, posix=posix, punctuation_chars=True) lexer.whitespace_split = True try: - words = list(lexer) + return list(lexer) except ValueError: - words = command.split() - return words + [word.split('=', 1)[1] for word in words if '=' in word] + return command.split() + +def _repo_stop_windows(word): + """A word read as a Windows path (`C:\\repo\\x` kept, quotes dropped), spelled with `/`; None when it has no drive.""" + path = _chock_PureWindowsPath(word.strip('"\'')) + return path.as_posix() if path.drive else None + +def _repo_stop_words(command): + """Each word of a shell command, the value of each `--flag=value` word, and each Windows-path reading of a word + (a POSIX split eats the backslashes of `C:\\repo\\x`): best effort, never raises.""" + words = _repo_stop_split(command, posix=True) + raw = _repo_stop_split(command, posix=False) + words += [word.strip('"\'') for word in raw if '\\' in word] + words += [word.split('=', 1)[1] for word in words if '=' in word] + return words + [path for path in map(_repo_stop_windows, raw) if path] def _repo_stop_named(raw): """Every string anywhere in a payload that may name a path (`file://` URIs decoded): each client nests and diff --git a/tests/fixtures/runtime_goldens/antigravity.py b/tests/fixtures/runtime_goldens/antigravity.py index 194ac66c..8ec79325 100644 --- a/tests/fixtures/runtime_goldens/antigravity.py +++ b/tests/fixtures/runtime_goldens/antigravity.py @@ -698,7 +698,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/claude_code.py b/tests/fixtures/runtime_goldens/claude_code.py index c3ed5fe2..ee95433b 100644 --- a/tests/fixtures/runtime_goldens/claude_code.py +++ b/tests/fixtures/runtime_goldens/claude_code.py @@ -809,7 +809,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/codex_cli.py b/tests/fixtures/runtime_goldens/codex_cli.py index bac13ade..9f24d0d4 100644 --- a/tests/fixtures/runtime_goldens/codex_cli.py +++ b/tests/fixtures/runtime_goldens/codex_cli.py @@ -777,7 +777,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/cursor.py b/tests/fixtures/runtime_goldens/cursor.py index 703ff7ef..ef075ec6 100644 --- a/tests/fixtures/runtime_goldens/cursor.py +++ b/tests/fixtures/runtime_goldens/cursor.py @@ -670,7 +670,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/devin.py b/tests/fixtures/runtime_goldens/devin.py index d14adb32..627c4116 100644 --- a/tests/fixtures/runtime_goldens/devin.py +++ b/tests/fixtures/runtime_goldens/devin.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/factory_droid.py b/tests/fixtures/runtime_goldens/factory_droid.py index be2109eb..3af4298f 100644 --- a/tests/fixtures/runtime_goldens/factory_droid.py +++ b/tests/fixtures/runtime_goldens/factory_droid.py @@ -763,7 +763,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/gemini_cli.py b/tests/fixtures/runtime_goldens/gemini_cli.py index 2068cdf8..2990ff7e 100644 --- a/tests/fixtures/runtime_goldens/gemini_cli.py +++ b/tests/fixtures/runtime_goldens/gemini_cli.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/goose.py b/tests/fixtures/runtime_goldens/goose.py index dcd731f6..c1b03e5a 100644 --- a/tests/fixtures/runtime_goldens/goose.py +++ b/tests/fixtures/runtime_goldens/goose.py @@ -732,7 +732,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/grok.py b/tests/fixtures/runtime_goldens/grok.py index ccee4c79..16b86489 100644 --- a/tests/fixtures/runtime_goldens/grok.py +++ b/tests/fixtures/runtime_goldens/grok.py @@ -776,7 +776,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/mistral_vibe.py b/tests/fixtures/runtime_goldens/mistral_vibe.py index 8469252f..8a6bcaa7 100644 --- a/tests/fixtures/runtime_goldens/mistral_vibe.py +++ b/tests/fixtures/runtime_goldens/mistral_vibe.py @@ -759,7 +759,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/openhands.py b/tests/fixtures/runtime_goldens/openhands.py index 64d7a75a..4343f5b2 100644 --- a/tests/fixtures/runtime_goldens/openhands.py +++ b/tests/fixtures/runtime_goldens/openhands.py @@ -732,7 +732,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/tabnine.py b/tests/fixtures/runtime_goldens/tabnine.py index 441d5f08..d513535a 100644 --- a/tests/fixtures/runtime_goldens/tabnine.py +++ b/tests/fixtures/runtime_goldens/tabnine.py @@ -732,7 +732,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/vscode_copilot.py b/tests/fixtures/runtime_goldens/vscode_copilot.py index d354df15..ab04974d 100644 --- a/tests/fixtures/runtime_goldens/vscode_copilot.py +++ b/tests/fixtures/runtime_goldens/vscode_copilot.py @@ -560,7 +560,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/fixtures/runtime_goldens/windsurf.py b/tests/fixtures/runtime_goldens/windsurf.py index 848b2587..ee68c3b5 100644 --- a/tests/fixtures/runtime_goldens/windsurf.py +++ b/tests/fixtures/runtime_goldens/windsurf.py @@ -629,7 +629,7 @@ def degrade(decision, event): # Not self-contained: chock's guard logic lives in the sibling _chock_runtime.py, loaded from this # file's own folder and pinned to the sha256 of that file's bytes (CRLF read as LF), hashed before they are executed. # Missing, unreadable, another version, or failing to import: every call refuses (_CHOCK_RUNTIME_FAULT), never allows. -_CHOCK_RUNTIME_PIN = '09ed5e7bf20341a34839444d62cf4b17a37eeb24e1120b65724eabec6f83fba9' +_CHOCK_RUNTIME_PIN = '1338b7f2c52bc6aa85599d6913bab34e13784a39897247e3d84c092684bbb443' def _chock_load_runtime(): diff --git a/tests/test_repo_stop_gap1d.py b/tests/test_repo_stop_gap1d.py index 9b391179..ad7040fc 100644 --- a/tests/test_repo_stop_gap1d.py +++ b/tests/test_repo_stop_gap1d.py @@ -222,3 +222,17 @@ def test_a_persons_commit_passes_in_a_repo_with_no_policy_while_stopped( refused = _commit(root, AGENT) assert refused.returncode != 0 assert "stopped: no policy" in refused.stderr + + +@pytest.mark.parametrize( + "command", + [ + r"rm C:\repo\.chock\stop.json", + r"rm -f 'C:\repo\.chock\stop.json'", + r'rm "C:\repo\.chock\stop.json"', + r"rm C:\repo/.chock/stop.json", + ], +) +def test_a_windows_path_word_names_its_repo_on_every_platform(command: str) -> None: + paths = repo_stop.repo_stop_paths(SimpleNamespace(command=command, path=None, raw=None)) + assert "C:/repo/.chock/stop.json" in paths or "C:\\repo\\.chock\\stop.json" in paths diff --git a/tests/test_scaffold_kinds.py b/tests/test_scaffold_kinds.py index b080b39b..ba4289da 100644 --- a/tests/test_scaffold_kinds.py +++ b/tests/test_scaffold_kinds.py @@ -2,6 +2,7 @@ from __future__ import annotations +import os import re import shutil import warnings @@ -62,6 +63,7 @@ def test_each_scaffold_passes_chock_check_only_evals_and_compiles_without_warnin assert "PEND" not in out +@pytest.mark.skipif(os.name == "nt", reason="NTFS has no executable bit; the scaffold's chmod is a POSIX property") @pytest.mark.parametrize("kind", ["guard", "script"]) def test_executable_templates_are_executable(tmp_path: Path, kind: str) -> None: assert new.cmd_new(["policy", "demo", "--kind", kind, "--root", str(tmp_path)]) == 0