From 5175469759c343c5201f0970878f640aaeca8755 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 02:55:43 +0000 Subject: [PATCH 01/24] Adopt the Sonar/Checkstyle/FindBugs ruff rule-family bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Turn on C90/N/PLR/PLW/PLC/ERA/T20/ARG/RET/SIM/PIE/FBT/A/B/S/BLE/TRY/RUF in [tool.ruff.lint] select per plan/coding-standards.md §3, with mccabe max-complexity=10 and pylint max-args=5/max-branches=12/ max-returns=6/max-statements=50. tests/ and acceptance/ get a documented per-file-ignore for S101 (bare assert by design), FBT (fixture values as positional args) and PLR2004 (literal test data, not magic values). The baseline this select turns up is fixed category by category in the commits that follow. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Claude --- pyproject.toml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5b91f4e..11674d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -140,6 +140,31 @@ target-version = "py311" extend-exclude = ["*.md", ".chock/bin/", "tests/fixtures/runtime_goldens/"] [tool.ruff.lint] -select = ["E", "F", "W", "I"] +# The Sonar/Checkstyle/FindBugs bar, in Python (plan/coding-standards.md §3, W50): +# C90 complexity, N naming, PLR/PLW/PLC pylint refactor/warning/convention, ERA +# commented-out code, T20 print-as-System.out, ARG unused args, RET/SIM/PIE +# FindBugs-class correctness, FBT boolean traps, A builtin shadowing, B bugbear, +# S bandit security, BLE blind except, TRY exception hygiene, RUF ruff-native. +select = [ + "E", "F", "W", "I", + "C90", "N", "PLR", "PLW", "PLC", "ERA", "T20", "ARG", "RET", "SIM", "PIE", + "FBT", "A", "B", "S", "BLE", "TRY", "RUF", +] # Layout is governed by `ruff format`; long diagnostic strings are allowed. ignore = ["E501"] + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.ruff.lint.pylint] +max-args = 5 +max-branches = 12 +max-returns = 6 +max-statements = 50 + +[tool.ruff.lint.per-file-ignores] +# tests/ and acceptance/ assert with bare `assert` by design (S101), commonly pass +# literal fixture values as positional args to helpers (FBT), and repeat short +# literal strings as test data, not magic values (PLR2004). +"tests/**" = ["S101", "FBT", "PLR2004"] +"acceptance/**" = ["S101", "FBT", "PLR2004"] From ccf35d19565288fbbe1c8287c53325dc3e5136ad Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 02:55:53 +0000 Subject: [PATCH 02/24] Fix mechanical lint findings: stale noqa, dunder-all order, misc RUF100 (noqa comments no longer needed once the new rule set proved them unnecessary -- ruff confirmed F401/BLE001 don't fire on the underlying lines), RUF022 (__all__ sort order), PLC0207 (str.split needs maxsplit), PLR0402 (manual from-import for importlib.resources), SIM300 (yoda-condition reorder). All via targeted `ruff check --select --fix`, reviewed individually, never a blanket --fix. Full suite green (1036 passed, 6 skipped). Co-Authored-By: Claude Sonnet 5 Signed-off-by: Claude --- src/chock/hooks/autocompile.py | 4 ++-- src/chock/hooks/install.py | 2 +- src/chock/packs/__init__.py | 2 +- src/chock/plugin/marketplace.py | 2 +- src/chock/plugin/store.py | 2 +- src/chock/registry/__init__.py | 6 +++--- src/chock/scaffold/recompile.py | 8 ++++---- src/chock/validation/__init__.py | 30 +++++++++++++++--------------- src/chock/vendored.py | 2 +- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/chock/hooks/autocompile.py b/src/chock/hooks/autocompile.py index f40e30e..dad6fb0 100644 --- a/src/chock/hooks/autocompile.py +++ b/src/chock/hooks/autocompile.py @@ -60,7 +60,7 @@ def auto_compile(repo_root: Path) -> None: config = load_config(repo_root) agents = agents_from_config(repo_root) pack_dirs = discover_policy_dirs(repo_root) - except Exception as exc: # noqa: BLE001 + except Exception as exc: print(f"[WARN] auto-compile could not enumerate policies: {exc}", file=sys.stderr) return @@ -68,7 +68,7 @@ def auto_compile(repo_root: Path) -> None: for pack_dir in pack_dirs: try: compile_one_dropin(pack_dir, config, compiled_root, agents=agents, repo_root=repo_root) - except Exception as exc: # noqa: BLE001 + except Exception as exc: print( f"[WARN] skipped policy '{pack_dir.name}': {exc}. Other policies still compiled.", file=sys.stderr, diff --git a/src/chock/hooks/install.py b/src/chock/hooks/install.py index ea26d0a..ad828a4 100644 --- a/src/chock/hooks/install.py +++ b/src/chock/hooks/install.py @@ -8,7 +8,7 @@ import sys from pathlib import Path -from chock.hooks.installers import ( # noqa: F401 +from chock.hooks.installers import ( DISPATCHER_TEMPLATE, GENERATED_MARKER, INTERPRETER_PLACEHOLDER, diff --git a/src/chock/packs/__init__.py b/src/chock/packs/__init__.py index f1313db..90ea886 100644 --- a/src/chock/packs/__init__.py +++ b/src/chock/packs/__init__.py @@ -24,4 +24,4 @@ def to_path(traversable: Traversable) -> Path: return Path(str(traversable)) -__all__ = ["packs_root", "to_path", "Traversable"] +__all__ = ["Traversable", "packs_root", "to_path"] diff --git a/src/chock/plugin/marketplace.py b/src/chock/plugin/marketplace.py index 15af7de..3c0dc56 100644 --- a/src/chock/plugin/marketplace.py +++ b/src/chock/plugin/marketplace.py @@ -114,7 +114,7 @@ def lock_differences(dist_root: Path) -> list[str]: def _summary(description: str) -> str: """First sentence of the description, with the bracketed posture note stripped.""" - text = description.split("[")[0].strip() + text = description.split("[", maxsplit=1)[0].strip() first = text.split(". ")[0].strip().rstrip(".") return (first[:96].rstrip() + "...") if len(first) > 99 else first diff --git a/src/chock/plugin/store.py b/src/chock/plugin/store.py index 33341dd..2ca8113 100644 --- a/src/chock/plugin/store.py +++ b/src/chock/plugin/store.py @@ -20,7 +20,7 @@ #: this one constant, borrowed from the two agents where agentseam does record it, instead #: of repeating the literal. SCRIPTS_TEMPLATE = packaging.supports("claude_code", packaging.EXECUTABLE) -assert SCRIPTS_TEMPLATE == packaging.supports("copilot", packaging.EXECUTABLE) +assert packaging.supports("copilot", packaging.EXECUTABLE) == SCRIPTS_TEMPLATE def owned_subtrees(store: str) -> tuple[str, ...]: diff --git a/src/chock/registry/__init__.py b/src/chock/registry/__init__.py index 1d37f50..1a4bef9 100644 --- a/src/chock/registry/__init__.py +++ b/src/chock/registry/__init__.py @@ -1,8 +1,8 @@ """Facade: single import surface for this activity package.""" -import yaml # noqa: F401 (re-exported for callers/tests) +import yaml -from chock.registry.cli import ( # noqa: F401 +from chock.registry.cli import ( cmd_get, cmd_init, cmd_list, @@ -10,7 +10,7 @@ cmd_scan, main, ) -from chock.registry.core import ( # noqa: F401 +from chock.registry.core import ( REGISTRY_DIR, REGISTRY_FILE, REGISTRY_FORMAT_VERSION, diff --git a/src/chock/scaffold/recompile.py b/src/chock/scaffold/recompile.py index 96a354f..2b52859 100644 --- a/src/chock/scaffold/recompile.py +++ b/src/chock/scaffold/recompile.py @@ -92,19 +92,19 @@ def _refresh_bookkeeping(repo_root: Path) -> None: try: entries, _skips = scan(repo_root) save_registry(entries, repo_root) - except Exception as exc: # noqa: BLE001 + except Exception as exc: print(f"[WARN] registry scan failed: {exc}. Run `chock registry scan`.", file=sys.stderr) try: cmd_refresh(["--repo", str(repo_root)]) - except Exception as exc: # noqa: BLE001 + except Exception as exc: print(f"[WARN] index refresh failed: {exc}. Run `chock sync`.", file=sys.stderr) try: from chock.lock import build_lock, write_lock write_lock(build_lock(repo_root), repo_root) - except Exception as exc: # noqa: BLE001 + except Exception as exc: raise BookkeepingError( f"chock.lock was not updated ({exc}). The compiled artifacts are in place, but the " "lockfile still attests the previous ones -- `chock check --only verify` will fail " @@ -118,7 +118,7 @@ def refresh_after_install(repo_root: Path) -> None: from chock.config import agents_from_config recompile(repo_root, agents_from_config(repo_root), skip_hooks=True) - except Exception as exc: # noqa: BLE001 - never fail an install over bookkeeping + except Exception as exc: print(f"[WARN] coverage not refreshed: {exc}. Run `chock sync --repo .`", file=sys.stderr) diff --git a/src/chock/validation/__init__.py b/src/chock/validation/__init__.py index e759d61..4238c18 100644 --- a/src/chock/validation/__init__.py +++ b/src/chock/validation/__init__.py @@ -1,8 +1,8 @@ """Facade: single import surface for the validation package.""" -import yaml # noqa: F401 (re-exported for callers/tests) +import yaml -from chock.validation.checks_content import ( # noqa: F401 +from chock.validation.checks_content import ( check_description_parity, check_no_agent_specific_leakage, check_progressive_disclosure, @@ -10,7 +10,7 @@ check_yagni, extract_skill_md_description, ) -from chock.validation.checks_determinism import ( # noqa: F401 +from chock.validation.checks_determinism import ( _compute_script_hashes, _hash_file, check_determinization_heuristic, @@ -18,27 +18,27 @@ check_scripts_shipped, check_verb_first_naming, ) -from chock.validation.checks_drift import ( # noqa: F401 +from chock.validation.checks_drift import ( check_registry_freshness, ) -from chock.validation.checks_evals import ( # noqa: F401 +from chock.validation.checks_evals import ( _schema_validate_suite, check_eval_first, ) -from chock.validation.checks_manifest_advice import ( # noqa: F401 +from chock.validation.checks_manifest_advice import ( check_manifest_advice, ) -from chock.validation.checks_manifest_schema import ( # noqa: F401 +from chock.validation.checks_manifest_schema import ( check_manifest_schema, ) -from chock.validation.checks_orchestration import ( # noqa: F401 +from chock.validation.checks_orchestration import ( check_composition_contract, check_dependencies_resolvable, check_lifecycle_guards, check_subagent_contract, check_trust_tier, ) -from chock.validation.checks_repo import ( # noqa: F401 +from chock.validation.checks_repo import ( _ADAPTER_FILES, _adapter_file_exists, check_adapter_integrity, @@ -46,7 +46,7 @@ check_ambient_token_budget, check_release_consistency, ) -from chock.validation.checks_security import ( # noqa: F401 +from chock.validation.checks_security import ( _is_script_file, _scan_text_surfaces, _split_eval_suite, @@ -54,15 +54,15 @@ check_effects_and_approval, check_security_baseline, ) -from chock.validation.engine import ( # noqa: F401 +from chock.validation.engine import ( main, validate_artifact, ) -from chock.validation.frontier import ( # noqa: F401 +from chock.validation.frontier import ( check_frontier_mode, load_frontier_standard, ) -from chock.validation.loading import ( # noqa: F401 +from chock.validation.loading import ( BUDGETS, SCHEMA_DIR, count_lines, @@ -73,7 +73,7 @@ schema_validator, validate_yaml_against_schema, ) -from chock.validation.patterns import ( # noqa: F401 +from chock.validation.patterns import ( _DETERMINISTIC_HEURISTIC_PATTERNS, _INT3_GRANDFATHERED_IDS, _VERB_PREFIXES, @@ -82,7 +82,7 @@ DEPTH_MARKERS, INJECTION_PATTERNS, ) -from chock.validation.report import ( # noqa: F401 +from chock.validation.report import ( Finding, Report, emit, diff --git a/src/chock/vendored.py b/src/chock/vendored.py index f6724ab..0da01bf 100644 --- a/src/chock/vendored.py +++ b/src/chock/vendored.py @@ -14,7 +14,7 @@ def _expected_bytes(kind: str, source) -> bytes | None: if kind == "static": - import importlib.resources as resources + from importlib import resources package, source_name = source try: From 545ff584f0d2f074cba3c6809dc86b713e7d01a7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 03:00:31 +0000 Subject: [PATCH 03/24] Fix SIM105/B905: contextlib.suppress, explicit zip(strict=) Replace try/except-pass patterns with contextlib.suppress(...), and narrow to OSError where the guarded call (chmod, rmdir) only ever raises that (was a broad `except Exception` in two installers.py spots). zip() over paired same-length tuples in toggles.py now declares strict=True. Full suite green. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Claude --- src/chock/compile/emitters/git_hook.py | 5 ++--- src/chock/gate/build.py | 5 ++--- src/chock/gateway/proxy.py | 9 +++------ src/chock/hooks/installers.py | 9 +++------ src/chock/hooks/runtime_vendor.py | 5 ++--- src/chock/scaffold/adapters.py | 5 ++--- src/chock/toggles.py | 4 ++-- 7 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/chock/compile/emitters/git_hook.py b/src/chock/compile/emitters/git_hook.py index 678dbcd..c6e4ccc 100644 --- a/src/chock/compile/emitters/git_hook.py +++ b/src/chock/compile/emitters/git_hook.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib from pathlib import Path from typing import Any @@ -28,10 +29,8 @@ def _emit_shims(output_dir: Path, policy_id: str, events: list[str]) -> list[Pat shim = output_dir / script_name rendered = SHIM_TEMPLATE.replace("__POLICY_ID__", policy_id).replace("__EVENT__", event_arg) write_generated(shim, rendered) - try: + with contextlib.suppress(OSError): shim.chmod(0o755) - except OSError: - pass emitted.append(shim) return emitted diff --git a/src/chock/gate/build.py b/src/chock/gate/build.py index 0db5611..79b9b03 100644 --- a/src/chock/gate/build.py +++ b/src/chock/gate/build.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib import shutil from pathlib import Path from typing import Any @@ -62,8 +63,6 @@ def vendor_runner(artifact_root: Path) -> Path: dest = Path(artifact_root) / "bin" / "gate.py" dest.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(source, dest) - try: + with contextlib.suppress(OSError): dest.chmod(0o755) - except OSError: - pass return dest diff --git a/src/chock/gateway/proxy.py b/src/chock/gateway/proxy.py index 14d993c..3ef7f38 100644 --- a/src/chock/gateway/proxy.py +++ b/src/chock/gateway/proxy.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib import json import subprocess import sys @@ -26,10 +27,8 @@ def _blocked_response(request_id: Any, message: str) -> str: def _force_utf8(stream: Any) -> None: """Best-effort: pin a text stream to UTF-8 with replacement.""" - try: + with contextlib.suppress(AttributeError, ValueError, OSError): stream.reconfigure(encoding="utf-8", errors="replace") - except (AttributeError, ValueError, OSError): - pass class Gateway: @@ -66,10 +65,8 @@ def _pipe_downstream(self) -> None: for line in self.process.stdout: self._write_out(line, sys.stdout) self._downstream_ended.set() - try: + with contextlib.suppress(OSError, ValueError): sys.stdin.close() - except (OSError, ValueError): - pass def _block_message(self, item: Any) -> str | None: """Block message for a single request object, or None to allow it.""" diff --git a/src/chock/hooks/installers.py b/src/chock/hooks/installers.py index 36a5ce5..470a171 100644 --- a/src/chock/hooks/installers.py +++ b/src/chock/hooks/installers.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib import shutil import subprocess import sys @@ -132,10 +133,8 @@ def install_validate_hook(hooks_dir: Path, repo_root: Path) -> None: impl = impl_dir / "99-chock-validate" _render_hook(source_dir / "pre-commit", impl) - try: + with contextlib.suppress(OSError): impl.chmod(0o755) - except Exception: - pass print(f"Implementation registered at {impl}") @@ -177,8 +176,6 @@ def install_policy_hooks(repo_root: Path, hooks_dir: Path) -> None: rel = _repo_relative(impl_source, repo_root) content = _POLICY_WRAPPER_TEMPLATE.replace("__MARKER__", GENERATED_MARKER).replace("__SOURCE_REL__", rel) write_generated(wrapper, content) - try: + with contextlib.suppress(OSError): wrapper.chmod(0o755) - except Exception: - pass print(f"Registered {len(implementations)} {event} policy implementation(s)") diff --git a/src/chock/hooks/runtime_vendor.py b/src/chock/hooks/runtime_vendor.py index 5c3d304..e6b9845 100644 --- a/src/chock/hooks/runtime_vendor.py +++ b/src/chock/hooks/runtime_vendor.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib from pathlib import Path from chock.gate import runtime_bundle @@ -16,8 +17,6 @@ def vendor_runtime(repo_root: Path, agent: str) -> Path: dest = Path(repo_root) / runtime_rel(agent) dest.parent.mkdir(parents=True, exist_ok=True) dest.write_text(runtime_bundle.render(agent), encoding="utf-8") - try: + with contextlib.suppress(OSError): dest.chmod(0o755) - except OSError: - pass return dest diff --git a/src/chock/scaffold/adapters.py b/src/chock/scaffold/adapters.py index fc6aea3..32b8cca 100644 --- a/src/chock/scaffold/adapters.py +++ b/src/chock/scaffold/adapters.py @@ -2,6 +2,7 @@ from __future__ import annotations +import contextlib from pathlib import Path from agentseam import instructions as agentseam_instructions @@ -56,10 +57,8 @@ def remove_instructions(repo_root: Path, deselected: list[str]) -> dict[str, str if path.exists() and not path.read_text(encoding="utf-8").strip(): path.unlink() parent = path.parent - try: + with contextlib.suppress(OSError): parent.rmdir() - except OSError: - pass if "aider" in deselected: conf = Path(repo_root) / _AIDER_CONF_REL if conf.exists() and conf.read_text(encoding="utf-8") == packaged_template(_AIDER_CONF_REL): diff --git a/src/chock/toggles.py b/src/chock/toggles.py index ea540a7..a862040 100644 --- a/src/chock/toggles.py +++ b/src/chock/toggles.py @@ -158,9 +158,9 @@ def policies_main(argv: list[str] | None) -> int: headers = ("id", "state", "coverage", "mandatory") widths = [max(len(h), *(len(r[i]) for r in rows)) for i, h in enumerate(headers)] - print(" ".join(h.ljust(w) for h, w in zip(headers, widths)).rstrip()) + print(" ".join(h.ljust(w) for h, w in zip(headers, widths, strict=True)).rstrip()) for row in rows: - print(" ".join(cell.ljust(w) for cell, w in zip(row, widths)).rstrip()) + print(" ".join(cell.ljust(w) for cell, w in zip(row, widths, strict=True)).rstrip()) return 0 From f30fb1e1c913334eea66112de08c6d5c4a5380a5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 03:07:53 +0000 Subject: [PATCH 04/24] Correct the previous commit: restore noqa comments RUF100 wrongly flagged The prior commit ran `ruff check --select RUF100,... --fix`, and a CLI --select overrides the project's configured select entirely for that invocation -- so RUF100 evaluated "unused" against a rule set of just those five codes, not the full configured bar, and treated every noqa:F401/noqa:BLE001 as unused because F401/BLE001 weren't even being checked in that run. Restores the six genuinely-needed noqa comments (facade re-export F401s in registry/__init__.py and validation/__init__.py, and BLE001 on three deliberate best-effort except-Exception blocks in autocompile.py and scaffold/recompile.py) and keeps the two RUF100 removals that verify as genuinely unused under the full project config (hooks/install.py's F401, covered by an __all__; scaffold/recompile.py's BLE001 on a block that re-raises, which BLE001 doesn't flag as blind). Verified against `ruff check src/` with no CLI --select override. Full suite green. Co-Authored-By: Claude Sonnet 5 Signed-off-by: Claude --- src/chock/hooks/autocompile.py | 4 ++-- src/chock/registry/__init__.py | 6 +++--- src/chock/scaffold/recompile.py | 6 +++--- src/chock/validation/__init__.py | 30 +++++++++++++++--------------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/chock/hooks/autocompile.py b/src/chock/hooks/autocompile.py index dad6fb0..f40e30e 100644 --- a/src/chock/hooks/autocompile.py +++ b/src/chock/hooks/autocompile.py @@ -60,7 +60,7 @@ def auto_compile(repo_root: Path) -> None: config = load_config(repo_root) agents = agents_from_config(repo_root) pack_dirs = discover_policy_dirs(repo_root) - except Exception as exc: + except Exception as exc: # noqa: BLE001 print(f"[WARN] auto-compile could not enumerate policies: {exc}", file=sys.stderr) return @@ -68,7 +68,7 @@ def auto_compile(repo_root: Path) -> None: for pack_dir in pack_dirs: try: compile_one_dropin(pack_dir, config, compiled_root, agents=agents, repo_root=repo_root) - except Exception as exc: + except Exception as exc: # noqa: BLE001 print( f"[WARN] skipped policy '{pack_dir.name}': {exc}. Other policies still compiled.", file=sys.stderr, diff --git a/src/chock/registry/__init__.py b/src/chock/registry/__init__.py index 1a4bef9..1d37f50 100644 --- a/src/chock/registry/__init__.py +++ b/src/chock/registry/__init__.py @@ -1,8 +1,8 @@ """Facade: single import surface for this activity package.""" -import yaml +import yaml # noqa: F401 (re-exported for callers/tests) -from chock.registry.cli import ( +from chock.registry.cli import ( # noqa: F401 cmd_get, cmd_init, cmd_list, @@ -10,7 +10,7 @@ cmd_scan, main, ) -from chock.registry.core import ( +from chock.registry.core import ( # noqa: F401 REGISTRY_DIR, REGISTRY_FILE, REGISTRY_FORMAT_VERSION, diff --git a/src/chock/scaffold/recompile.py b/src/chock/scaffold/recompile.py index 2b52859..c436a13 100644 --- a/src/chock/scaffold/recompile.py +++ b/src/chock/scaffold/recompile.py @@ -92,12 +92,12 @@ def _refresh_bookkeeping(repo_root: Path) -> None: try: entries, _skips = scan(repo_root) save_registry(entries, repo_root) - except Exception as exc: + except Exception as exc: # noqa: BLE001 print(f"[WARN] registry scan failed: {exc}. Run `chock registry scan`.", file=sys.stderr) try: cmd_refresh(["--repo", str(repo_root)]) - except Exception as exc: + except Exception as exc: # noqa: BLE001 print(f"[WARN] index refresh failed: {exc}. Run `chock sync`.", file=sys.stderr) try: @@ -118,7 +118,7 @@ def refresh_after_install(repo_root: Path) -> None: from chock.config import agents_from_config recompile(repo_root, agents_from_config(repo_root), skip_hooks=True) - except Exception as exc: + except Exception as exc: # noqa: BLE001 - never fail an install over bookkeeping print(f"[WARN] coverage not refreshed: {exc}. Run `chock sync --repo .`", file=sys.stderr) diff --git a/src/chock/validation/__init__.py b/src/chock/validation/__init__.py index 4238c18..e759d61 100644 --- a/src/chock/validation/__init__.py +++ b/src/chock/validation/__init__.py @@ -1,8 +1,8 @@ """Facade: single import surface for the validation package.""" -import yaml +import yaml # noqa: F401 (re-exported for callers/tests) -from chock.validation.checks_content import ( +from chock.validation.checks_content import ( # noqa: F401 check_description_parity, check_no_agent_specific_leakage, check_progressive_disclosure, @@ -10,7 +10,7 @@ check_yagni, extract_skill_md_description, ) -from chock.validation.checks_determinism import ( +from chock.validation.checks_determinism import ( # noqa: F401 _compute_script_hashes, _hash_file, check_determinization_heuristic, @@ -18,27 +18,27 @@ check_scripts_shipped, check_verb_first_naming, ) -from chock.validation.checks_drift import ( +from chock.validation.checks_drift import ( # noqa: F401 check_registry_freshness, ) -from chock.validation.checks_evals import ( +from chock.validation.checks_evals import ( # noqa: F401 _schema_validate_suite, check_eval_first, ) -from chock.validation.checks_manifest_advice import ( +from chock.validation.checks_manifest_advice import ( # noqa: F401 check_manifest_advice, ) -from chock.validation.checks_manifest_schema import ( +from chock.validation.checks_manifest_schema import ( # noqa: F401 check_manifest_schema, ) -from chock.validation.checks_orchestration import ( +from chock.validation.checks_orchestration import ( # noqa: F401 check_composition_contract, check_dependencies_resolvable, check_lifecycle_guards, check_subagent_contract, check_trust_tier, ) -from chock.validation.checks_repo import ( +from chock.validation.checks_repo import ( # noqa: F401 _ADAPTER_FILES, _adapter_file_exists, check_adapter_integrity, @@ -46,7 +46,7 @@ check_ambient_token_budget, check_release_consistency, ) -from chock.validation.checks_security import ( +from chock.validation.checks_security import ( # noqa: F401 _is_script_file, _scan_text_surfaces, _split_eval_suite, @@ -54,15 +54,15 @@ check_effects_and_approval, check_security_baseline, ) -from chock.validation.engine import ( +from chock.validation.engine import ( # noqa: F401 main, validate_artifact, ) -from chock.validation.frontier import ( +from chock.validation.frontier import ( # noqa: F401 check_frontier_mode, load_frontier_standard, ) -from chock.validation.loading import ( +from chock.validation.loading import ( # noqa: F401 BUDGETS, SCHEMA_DIR, count_lines, @@ -73,7 +73,7 @@ schema_validator, validate_yaml_against_schema, ) -from chock.validation.patterns import ( +from chock.validation.patterns import ( # noqa: F401 _DETERMINISTIC_HEURISTIC_PATTERNS, _INT3_GRANDFATHERED_IDS, _VERB_PREFIXES, @@ -82,7 +82,7 @@ DEPTH_MARKERS, INJECTION_PATTERNS, ) -from chock.validation.report import ( +from chock.validation.report import ( # noqa: F401 Finding, Report, emit, From 8a120ccaf9adb90c6ed38cc44b555f02df0c8767 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 03:18:32 +0000 Subject: [PATCH 05/24] Fix misc small-count findings batch Signed-off-by: Claude Co-Authored-By: Claude Sonnet 5 --- .chock/bin/gate.py | 5 +++-- src/chock/authoring/compliance.py | 10 ++------- src/chock/compile/compiler.py | 4 ++-- src/chock/compile/emitters/in_agent.py | 2 +- src/chock/compile/surfaces.py | 4 ++-- src/chock/eval/suites.py | 2 +- src/chock/gate/runner.py | 5 +++-- src/chock/gate/runtime_bundle.py | 2 +- src/chock/gateway/gates.py | 5 +---- src/chock/hooks/sessionstart_install.py | 2 +- src/chock/index/render.py | 2 +- src/chock/lock.py | 2 +- src/chock/manifest.py | 15 +++++-------- src/chock/policy_id.py | 8 +++---- src/chock/registry/core.py | 4 ++-- src/chock/scaffold/skills_bridge.py | 8 ++++--- src/chock/validation/checks_evals.py | 22 +++++++++++-------- .../validation/checks_manifest_schema.py | 4 ++-- src/chock/validation/checks_policy_toggles.py | 21 ++++++++++-------- src/chock/validation/frontier_ingest.py | 2 +- tests/test_manifest_id_safety.py | 6 ++--- tests/test_properties.py | 8 +++---- 22 files changed, 70 insertions(+), 73 deletions(-) diff --git a/.chock/bin/gate.py b/.chock/bin/gate.py index 32073d4..77a4d4b 100755 --- a/.chock/bin/gate.py +++ b/.chock/bin/gate.py @@ -53,9 +53,10 @@ def _git(self, *args: str) -> str: errors="replace", check=True, ) - return proc.stdout or "" except (subprocess.CalledProcessError, FileNotFoundError, UnicodeError): return "" + else: + return proc.stdout or "" def rev_exists(self, ref: str) -> bool: """True when `ref` resolves to a commit. Used to fail CI closed on a missing base.""" @@ -140,7 +141,7 @@ def _deps_requirements(text: str) -> set[str]: names: set[str] = set() for line in text.splitlines(): s = line.strip() - if not s or s.startswith("#") or s.startswith("-"): + if not s or s.startswith(("#", "-")): continue m = _REQ_RE.match(line) if m: diff --git a/src/chock/authoring/compliance.py b/src/chock/authoring/compliance.py index b74efb9..7e75985 100644 --- a/src/chock/authoring/compliance.py +++ b/src/chock/authoring/compliance.py @@ -94,10 +94,7 @@ def _build_report( builtin = _load_builtin_controls(framework) claims = _collect_claims(repo_root, framework) - if framework in BUILTIN_FRAMEWORKS: - control_ids = list(builtin.keys()) - else: - control_ids = sorted(claims.keys()) + control_ids = list(builtin.keys()) if framework in BUILTIN_FRAMEWORKS else sorted(claims.keys()) report: dict[str, Any] = {framework: {}} for control_id in control_ids: @@ -131,10 +128,7 @@ def _format_table( detail = ", ".join(policy_strs) else: detail = "-" - if title: - first = f"{control_id:<12} {state:<10} {title}" - else: - first = f"{control_id:<12} {state:<10} {detail}" + first = f"{control_id:<12} {state:<10} {title}" if title else f"{control_id:<12} {state:<10} {detail}" lines.append(first) if title and policies: lines.append(f"{'':<12} {'':<10} {detail}") diff --git a/src/chock/compile/compiler.py b/src/chock/compile/compiler.py index 35cac0b..d989a0c 100644 --- a/src/chock/compile/compiler.py +++ b/src/chock/compile/compiler.py @@ -25,7 +25,7 @@ from chock.config import agents_from_config from chock.hooks.in_agent_install import WIRED_VENDORS, installed_policy_ids from chock.manifest import ManifestSourceError, load_manifest -from chock.policy_id import InvalidPolicyId, validate_policy_id +from chock.policy_id import InvalidPolicyIdError, validate_policy_id from chock.scaffold.install_ci import ci_workflow_installed from chock.vendors import CHOCK_AGENT @@ -99,7 +99,7 @@ def compile_policy( try: validate_policy_id(policy_id, policy_dir.name) - except InvalidPolicyId as exc: + except InvalidPolicyIdError as exc: print(f"[ERROR] {policy_dir / 'manifest.yaml'}: manifest_id: {exc}", file=sys.stderr) return CompileResult(policy_id=policy_dir.name) diff --git a/src/chock/compile/emitters/in_agent.py b/src/chock/compile/emitters/in_agent.py index 37fd80c..2346875 100644 --- a/src/chock/compile/emitters/in_agent.py +++ b/src/chock/compile/emitters/in_agent.py @@ -42,7 +42,7 @@ def _guard_script(policy_dir: Path, policy_id: str) -> str | None: #: Wire token Claude Code substitutes for the repo root; agentseam 0.2.0's vendor-config #: schema carries no repo-root-token field yet, so the fact still lives here. -PROJECT_DIR_TOKEN = "${CLAUDE_PROJECT_DIR}" +PROJECT_DIR_TOKEN = "${CLAUDE_PROJECT_DIR}" # noqa: S105 -- a shell variable reference, not a credential # Witnessed overrides: chock's agent-hooks file speaks `preToolUse` with bash/powershell/ # timeoutSec entry keys (live deny, data/witnesses.json: vscode_copilot x agent-hooks); diff --git a/src/chock/compile/surfaces.py b/src/chock/compile/surfaces.py index 1844536..3e2ee90 100644 --- a/src/chock/compile/surfaces.py +++ b/src/chock/compile/surfaces.py @@ -96,8 +96,8 @@ def parse_agent_selection(groups: list[str], valid: dict[str, object] | None = N valid = SURFACE_AGENTS if valid is None else valid agents: list[str] = [] for group in groups: - for name in group.split(","): - name = name.strip() + for raw_name in group.split(","): + name = raw_name.strip() if name and name not in agents: agents.append(name) unknown = [a for a in agents if a not in valid] diff --git a/src/chock/eval/suites.py b/src/chock/eval/suites.py index 0bc5e7f..11d7ecc 100644 --- a/src/chock/eval/suites.py +++ b/src/chock/eval/suites.py @@ -84,7 +84,7 @@ def discover_policies(repo_root: Path, policy_id: str | None = None) -> list[Pol for _artifact_type, directory in discover_artifacts(Path(repo_root)): try: loaded = load_manifest(directory) - except Exception: + except Exception: # noqa: BLE001, S112 -- best-effort discovery: skip any dir whose manifest fails to load continue if loaded is None: continue diff --git a/src/chock/gate/runner.py b/src/chock/gate/runner.py index 32073d4..77a4d4b 100644 --- a/src/chock/gate/runner.py +++ b/src/chock/gate/runner.py @@ -53,9 +53,10 @@ def _git(self, *args: str) -> str: errors="replace", check=True, ) - return proc.stdout or "" except (subprocess.CalledProcessError, FileNotFoundError, UnicodeError): return "" + else: + return proc.stdout or "" def rev_exists(self, ref: str) -> bool: """True when `ref` resolves to a commit. Used to fail CI closed on a missing base.""" @@ -140,7 +141,7 @@ def _deps_requirements(text: str) -> set[str]: names: set[str] = set() for line in text.splitlines(): s = line.strip() - if not s or s.startswith("#") or s.startswith("-"): + if not s or s.startswith(("#", "-")): continue m = _REQ_RE.match(line) if m: diff --git a/src/chock/gate/runtime_bundle.py b/src/chock/gate/runtime_bundle.py index cf59f47..6ab8e74 100644 --- a/src/chock/gate/runtime_bundle.py +++ b/src/chock/gate/runtime_bundle.py @@ -55,7 +55,7 @@ def _extract(module) -> str: _DISPATCH = _DATA_DIR.joinpath("dispatch.py.tmpl").read_text(encoding="utf-8") -_DISPATCH_BRANCH_TOKEN = "# __SESSION_START_BRANCH__\n" +_DISPATCH_BRANCH_TOKEN = "# __SESSION_START_BRANCH__\n" # noqa: S105 -- a template marker, not a credential _SESSION_START_BRANCH = _DATA_DIR.joinpath("session_start_branch.py.tmpl").read_text(encoding="utf-8") diff --git a/src/chock/gateway/gates.py b/src/chock/gateway/gates.py index e531230..8ee9a73 100644 --- a/src/chock/gateway/gates.py +++ b/src/chock/gateway/gates.py @@ -69,10 +69,7 @@ def _hosts_in(text: str) -> Iterator[str]: def _emit(authority: str) -> Iterator[str]: authority = authority.rsplit("@", 1)[-1] - if authority.startswith("["): - host = authority[1:].split("]", 1)[0] - else: - host = authority.split(":", 1)[0] + host = authority[1:].split("]", 1)[0] if authority.startswith("[") else authority.split(":", 1)[0] host = host.lower().rstrip(".") key = host or "\x00no-host" if key not in seen: diff --git a/src/chock/hooks/sessionstart_install.py b/src/chock/hooks/sessionstart_install.py index 71aa73d..d6eb095 100644 --- a/src/chock/hooks/sessionstart_install.py +++ b/src/chock/hooks/sessionstart_install.py @@ -76,7 +76,7 @@ def install_sessionstart_hook(repo_root: Path) -> bool: vendor_adapter(repo_root) - desired = kept + [install_form] + desired = [*kept, install_form] if isinstance(existing, list) and desired == existing: return False hooks[ARM_EVENT] = desired diff --git a/src/chock/index/render.py b/src/chock/index/render.py index 45b41fe..c23fee9 100644 --- a/src/chock/index/render.py +++ b/src/chock/index/render.py @@ -71,7 +71,7 @@ def _render_extended(entries: list[IndexEntry]) -> str: ] for entry in entries: if entry.artifact == "rule": - lines.extend(_rule_lines(entry) + [""]) + lines.extend([*_rule_lines(entry), ""]) elif entry.artifact == "hook": lines.append(_gate_line(entry) + "\n") else: diff --git a/src/chock/lock.py b/src/chock/lock.py index fecad70..dabc46c 100644 --- a/src/chock/lock.py +++ b/src/chock/lock.py @@ -128,7 +128,7 @@ def main(argv: list[str] | None = None) -> int: argv = list(argv or []) valid_commands = {"init", "verify"} if not argv or argv[0] not in valid_commands: - argv = ["verify"] + argv + argv = ["verify", *argv] root_parser = argparse.ArgumentParser(add_help=False) root_parser.add_argument("--root", "--repo", default=".", dest="root", help="Repo root") diff --git a/src/chock/manifest.py b/src/chock/manifest.py index 25b341c..53761f2 100644 --- a/src/chock/manifest.py +++ b/src/chock/manifest.py @@ -79,13 +79,11 @@ def _project_skill_frontmatter( if not isinstance(front_name, str): front_name = str(front_name) - if front_name != artifact_dir.name: - if warnings is not None: - warnings.append(f"frontmatter name '{front_name}' does not match directory name '{artifact_dir.name}'") + if front_name != artifact_dir.name and warnings is not None: + warnings.append(f"frontmatter name '{front_name}' does not match directory name '{artifact_dir.name}'") - if len(front_name) > 128: - if warnings is not None: - warnings.append(f"name exceeds 128 characters ({len(front_name)})") + if len(front_name) > 128 and warnings is not None: + warnings.append(f"name exceeds 128 characters ({len(front_name)})") data["id"] = ac.get("id") or artifact_dir.name data["name"] = ac.get("name") or front_name @@ -181,10 +179,7 @@ def _parse_skill_frontmatter(text: str) -> dict[str, Any]: if end == -1: return {} - try: - return yaml.safe_load("\n".join(lines[:end])) or {} - except yaml.YAMLError: - raise + return yaml.safe_load("\n".join(lines[:end])) or {} def normalize_manifest(data: dict[str, Any]) -> dict[str, Any]: diff --git a/src/chock/policy_id.py b/src/chock/policy_id.py index 6038f02..78d9341 100644 --- a/src/chock/policy_id.py +++ b/src/chock/policy_id.py @@ -7,16 +7,16 @@ POLICY_ID_RE = re.compile(r"^[a-z][a-z0-9-]{2,63}$") -class InvalidPolicyId(ValueError): +class InvalidPolicyIdError(ValueError): """A policy id is unsafe to use as a path or command token, or disagrees with its folder.""" def validate_policy_id(policy_id: str, folder_name: str) -> None: - """Raise InvalidPolicyId unless `policy_id` is schema-valid and equals its folder name.""" + """Raise InvalidPolicyIdError unless `policy_id` is schema-valid and equals its folder name.""" if not isinstance(policy_id, str) or not POLICY_ID_RE.fullmatch(policy_id): - raise InvalidPolicyId( + raise InvalidPolicyIdError( f"policy id {policy_id!r} is not a valid identifier (must match {POLICY_ID_RE.pattern}); " "refusing to use it as a filesystem path or command token" ) if policy_id != folder_name: - raise InvalidPolicyId(f"policy id {policy_id!r} does not match its folder name {folder_name!r}") + raise InvalidPolicyIdError(f"policy id {policy_id!r} does not match its folder name {folder_name!r}") diff --git a/src/chock/registry/core.py b/src/chock/registry/core.py index 8c1ec7b..0ad14fe 100644 --- a/src/chock/registry/core.py +++ b/src/chock/registry/core.py @@ -214,14 +214,14 @@ def load_registry(root: Path | None = None) -> dict[str, list[RegistryEntry]]: def resolve( - id: str, + artifact_id: str, version: str | None = None, artifact_type: str | None = None, root: Path | None = None, ) -> RegistryEntry | None: """Resolve an ID to the best matching registry entry.""" entries = load_registry(root) - versions = entries.get(id, []) + versions = entries.get(artifact_id, []) if not versions: return None diff --git a/src/chock/scaffold/skills_bridge.py b/src/chock/scaffold/skills_bridge.py index 57f218c..8d6d506 100644 --- a/src/chock/scaffold/skills_bridge.py +++ b/src/chock/scaffold/skills_bridge.py @@ -55,17 +55,19 @@ def _bridge_one(link: Path, target: Path) -> str: rel = Path(os.path.relpath(str(target), str(link.parent))) try: os.symlink(rel, link, target_is_directory=True) - return "symlink" except OSError: pass + else: + return "symlink" try: shutil.copytree(str(target), str(link)) - _mark_bridge(link) - return "copy" except OSError as exc: print(f"[WARN] skills-bridge: could not bridge {target.name}: {exc}", file=sys.stderr) return "error" + else: + _mark_bridge(link) + return "copy" def _skill_dirs(skills_root: Path) -> list[Path]: diff --git a/src/chock/validation/checks_evals.py b/src/chock/validation/checks_evals.py index 21fe3a6..25dd0fb 100644 --- a/src/chock/validation/checks_evals.py +++ b/src/chock/validation/checks_evals.py @@ -101,13 +101,17 @@ def check_eval_first(artifact_dir: Path, manifest: dict[str, Any], artifact_type ) ) - if artifact_type == "skill" and manifest.get("security", {}).get("processes_external_content"): - if categories.count("adversarial") < 1 and categories.count("security") < 1: - report.add( - Finding( - str(suite_file), - "eval_first", - "error", - "security.processes_external_content is true but eval suite has no adversarial or security case (SEC-6).", - ) + if ( + artifact_type == "skill" + and manifest.get("security", {}).get("processes_external_content") + and categories.count("adversarial") < 1 + and categories.count("security") < 1 + ): + report.add( + Finding( + str(suite_file), + "eval_first", + "error", + "security.processes_external_content is true but eval suite has no adversarial or security case (SEC-6).", ) + ) diff --git a/src/chock/validation/checks_manifest_schema.py b/src/chock/validation/checks_manifest_schema.py index 9ad21e3..a02e810 100644 --- a/src/chock/validation/checks_manifest_schema.py +++ b/src/chock/validation/checks_manifest_schema.py @@ -6,7 +6,7 @@ from typing import Any from chock.manifest import CANONICAL_MANIFEST, resolve_manifest_path -from chock.policy_id import InvalidPolicyId, validate_policy_id +from chock.policy_id import InvalidPolicyIdError, validate_policy_id from chock.validation.checks_gate_shape import _validate_gate from chock.validation.report import Finding, Report @@ -28,7 +28,7 @@ def _check_manifest_id_folder(artifact_dir: Path, manifest: dict[str, Any], repo effective_id = manifest.get("id") or artifact_dir.name try: validate_policy_id(effective_id, artifact_dir.name) - except InvalidPolicyId as exc: + except InvalidPolicyIdError as exc: report.add(Finding(str(_manifest_ref(artifact_dir)), "manifest_id_folder", "error", str(exc))) diff --git a/src/chock/validation/checks_policy_toggles.py b/src/chock/validation/checks_policy_toggles.py index 5a453f5..46928ca 100644 --- a/src/chock/validation/checks_policy_toggles.py +++ b/src/chock/validation/checks_policy_toggles.py @@ -84,13 +84,16 @@ def check_policy_toggles(repo_root: Path, report: Report) -> None: ) ) continue - if manifest.get("enforcement") == "block" and policy_id in SECURITY_BLOCK_GUARDS: - if override.get("enforcement") == "advise" or override.get("surfaces") == ["ambient-rule"]: - report.add( - Finding( - str(repo_root / ".chock" / "config.yaml"), - "policy_toggles", - "warning", - f"Block security guard {policy_id} is downgraded to advisory", - ) + if ( + manifest.get("enforcement") == "block" + and policy_id in SECURITY_BLOCK_GUARDS + and (override.get("enforcement") == "advise" or override.get("surfaces") == ["ambient-rule"]) + ): + report.add( + Finding( + str(repo_root / ".chock" / "config.yaml"), + "policy_toggles", + "warning", + f"Block security guard {policy_id} is downgraded to advisory", ) + ) diff --git a/src/chock/validation/frontier_ingest.py b/src/chock/validation/frontier_ingest.py index 12bae88..f364960 100644 --- a/src/chock/validation/frontier_ingest.py +++ b/src/chock/validation/frontier_ingest.py @@ -74,7 +74,7 @@ def fetch_url(url: str) -> str: try: import urllib.request - with urllib.request.urlopen(url, timeout=30) as response: # nosec B310 -- https enforced above + with urllib.request.urlopen(url, timeout=30) as response: # noqa: S310 -- https:// enforced above return response.read().decode("utf-8") except Exception as exc: print(f"WARN: could not fetch {url}: {exc}", file=sys.stderr) diff --git a/tests/test_manifest_id_safety.py b/tests/test_manifest_id_safety.py index a04b683..e900adc 100644 --- a/tests/test_manifest_id_safety.py +++ b/tests/test_manifest_id_safety.py @@ -8,7 +8,7 @@ import pytest from chock.compile.compiler import compile_policy -from chock.policy_id import InvalidPolicyId, validate_policy_id +from chock.policy_id import InvalidPolicyIdError, validate_policy_id from chock.scaffold.add import _reject_unsafe_id, locate FRAMEWORK_ROOT = Path(__file__).resolve().parents[1] @@ -40,12 +40,12 @@ def test_validate_policy_id_accepts_the_canonical_shape(): ], ) def test_validate_policy_id_rejects_unsafe_ids(bad_id): - with pytest.raises(InvalidPolicyId): + with pytest.raises(InvalidPolicyIdError): validate_policy_id(bad_id, bad_id) def test_validate_policy_id_requires_folder_match(): - with pytest.raises(InvalidPolicyId): + with pytest.raises(InvalidPolicyIdError): validate_policy_id("branch-guard", "protect-main-branch") diff --git a/tests/test_properties.py b/tests/test_properties.py index 15664f4..ee563bd 100644 --- a/tests/test_properties.py +++ b/tests/test_properties.py @@ -9,7 +9,7 @@ from hypothesis import strategies as st from chock.compile.surfaces import parse_agent_selection -from chock.policy_id import POLICY_ID_RE, InvalidPolicyId, validate_policy_id +from chock.policy_id import POLICY_ID_RE, InvalidPolicyIdError, validate_policy_id SAFE_CHARS = set(string.ascii_lowercase + string.digits + "-") @@ -31,7 +31,7 @@ def test_validator_agrees_with_the_published_pattern(candidate: str) -> None: if POLICY_ID_RE.fullmatch(candidate): validate_policy_id(candidate, candidate) else: - with pytest.raises(InvalidPolicyId): + with pytest.raises(InvalidPolicyIdError): validate_policy_id(candidate, candidate) @@ -39,7 +39,7 @@ def test_validator_agrees_with_the_published_pattern(candidate: str) -> None: def test_one_hot_byte_anywhere_is_rejected(policy_id: str, hot: str) -> None: for pos in (0, len(policy_id) // 2, len(policy_id)): poisoned = policy_id[:pos] + hot + policy_id[pos:] - with pytest.raises(InvalidPolicyId): + with pytest.raises(InvalidPolicyIdError): validate_policy_id(poisoned, poisoned) @@ -48,7 +48,7 @@ def test_id_must_equal_folder(policy_id: str, folder: str) -> None: if policy_id == folder: validate_policy_id(policy_id, folder) else: - with pytest.raises(InvalidPolicyId): + with pytest.raises(InvalidPolicyIdError): validate_policy_id(policy_id, folder) From 971266a279809c452ca3f43b86409e1151e0d22c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 2 Sep 2026 03:24:31 +0000 Subject: [PATCH 06/24] PLR2004: name the magic values as module constants Replaced bare int/word-count comparisons (row/path segment counts, gate exit codes, name/paragraph/line-length/staleness thresholds) with named module-level constants documenting what the number means, across authoring/matrix.py, eval/execute.py, the vendored gate runner, manifest.py, plugin/marketplace.py, validation/checks_content.py and validation/frontier.py. Resynced the vendored runtime copy. Full suite green. Signed-off-by: Claude Co-Authored-By: Claude Sonnet 5 --- .chock/bin/gate.py | 13 +++++++++++-- src/chock/authoring/matrix.py | 6 +++++- src/chock/eval/execute.py | 5 ++++- src/chock/gate/runner.py | 13 +++++++++++-- src/chock/manifest.py | 5 ++++- src/chock/plugin/marketplace.py | 7 ++++++- src/chock/validation/checks_content.py | 17 +++++++++++++---- src/chock/validation/frontier.py | 5 ++++- 8 files changed, 58 insertions(+), 13 deletions(-) diff --git a/.chock/bin/gate.py b/.chock/bin/gate.py index 77a4d4b..bed4392 100755 --- a/.chock/bin/gate.py +++ b/.chock/bin/gate.py @@ -92,7 +92,7 @@ def push_refs(self) -> list[str]: refs: list[str] = [] for line in self._push_stdin.splitlines(): parts = line.split() - if len(parts) >= 3: + if len(parts) >= _PUSH_LINE_MIN_PARTS: refs.append(parts[2]) return refs @@ -242,6 +242,15 @@ def _kind_dependency_allowlist(ctx: GateContext, params: dict, event: str) -> Ga _LOG_MAX_BYTES = 1_048_576 _LOG_MATCH_CAP = 20 +#: A pre-push stdin line is ` `; +#: at least 3 whitespace-separated parts to reach the remote ref at index 2. +_PUSH_LINE_MIN_PARTS = 3 + +#: `/.chock/compiled//git-hook/