patch-chat 0.2.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- patch_chat-0.4.0/.claude/commands/upstream-issue.md +116 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.gitignore +5 -3
- {patch_chat-0.2.0 → patch_chat-0.4.0}/AGENTS.md +207 -138
- {patch_chat-0.2.0 → patch_chat-0.4.0}/AUDIT_REPORT.md +27 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/CHANGELOG.md +1011 -624
- {patch_chat-0.2.0 → patch_chat-0.4.0}/CONTRIBUTING.md +6 -0
- patch_chat-0.4.0/MANIFEST.in +6 -0
- {patch_chat-0.2.0/patch_chat.egg-info → patch_chat-0.4.0}/PKG-INFO +16 -13
- {patch_chat-0.2.0 → patch_chat-0.4.0}/README.md +7 -4
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/benchmark.py +8 -0
- patch_chat-0.4.0/benchmark/test_benchmark.py +104 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/_version.py +3 -3
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/analytics.py +65 -14
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/args.py +3 -2
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/base_coder.py +21 -8
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_coder.py +5 -2
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/udiff_coder.py +15 -12
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/usage.py +182 -186
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/wholefile_coder.py +69 -6
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/commands.py +71 -35
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/history.py +2 -1
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/io.py +1367 -1318
- patch_chat-0.4.0/patch/llm.py +184 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/main.py +38 -12
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/mdstream.py +4 -1
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/onboarding.py +12 -3
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/repo.py +25 -5
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/repo_trust.py +30 -3
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/report.py +36 -0
- patch_chat-0.4.0/patch/urls.py +44 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/utils.py +21 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/watch.py +6 -1
- {patch_chat-0.2.0 → patch_chat-0.4.0/patch_chat.egg-info}/PKG-INFO +16 -13
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/SOURCES.txt +4 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/requires.txt +8 -8
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/scm_file_list.json +4 -0
- patch_chat-0.4.0/patch_chat.egg-info/scm_version.json +8 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/pyproject.toml +133 -133
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/common-constraints.txt +506 -504
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-browser.txt +169 -169
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-dev.txt +359 -359
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements.in +48 -47
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements.txt +465 -464
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_analytics.py +73 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_coder.py +1777 -1671
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_commands.py +2502 -2297
- patch_chat-0.4.0/tests/basic/test_dependency_security.py +35 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_editblock.py +18 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_history.py +81 -68
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_io.py +41 -0
- patch_chat-0.4.0/tests/basic/test_llm.py +107 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_main.py +85 -1
- patch_chat-0.4.0/tests/basic/test_mdstream.py +65 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_onboarding.py +21 -1
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_repo.py +779 -726
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_repo_config_trust.py +50 -0
- patch_chat-0.4.0/tests/basic/test_report.py +43 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_sanity_check_repo.py +2 -5
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_udiff.py +260 -241
- patch_chat-0.4.0/tests/basic/test_urls.py +40 -0
- patch_chat-0.4.0/tests/basic/test_utils.py +43 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_watch.py +21 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_wholefile.py +97 -0
- patch_chat-0.2.0/MANIFEST.in +0 -1
- patch_chat-0.2.0/benchmark/test_benchmark.py +0 -47
- patch_chat-0.2.0/patch/llm.py +0 -48
- patch_chat-0.2.0/patch/urls.py +0 -17
- patch_chat-0.2.0/patch_chat.egg-info/scm_version.json +0 -8
- patch_chat-0.2.0/tests/basic/test_report.py +0 -20
- patch_chat-0.2.0/tests/basic/test_urls.py +0 -18
- patch_chat-0.2.0/tests/basic/test_utils.py +0 -22
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.agents/resume +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.agents/setup +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.dockerignore +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.flake8 +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.github/ISSUE_TEMPLATE/issue.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.github/workflows/packaging.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.github/workflows/pre-commit.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.github/workflows/ubuntu-tests.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.github/workflows/windows-tests.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/.pre-commit-config.yaml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/AUDIT_PROMPT.md +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/LICENSE.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/Dockerfile +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/README.md +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/clone-exercism.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/cpp-test.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/docker.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/docker_build.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/install-docker-ubuntu.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/npm-test.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/plot.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/plots.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/refactor_tools.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/rsync.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/rungrid.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/swe-bench-lite.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/swe-bench.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/benchmark/swe_bench.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/docker/Dockerfile +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/__main__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/args_formatter.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/architect_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/architect_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/ask_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/ask_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/base_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/chat_chunks.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/chat_state.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/context_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/context_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/edit_apply.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_fenced_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_fenced_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_func_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_func_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editblock_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_diff_fenced_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_diff_fenced_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_editblock_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_editblock_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_whole_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/editor_whole_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/patch_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/patch_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/search_replace.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/shell.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/single_wholefile_func_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/single_wholefile_func_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/udiff_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/udiff_simple.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/udiff_simple_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/wholefile_func_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/wholefile_func_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/coders/wholefile_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/copypaste.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/deprecated.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/diffs.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/dump.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/editor.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/exceptions.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/format_settings.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/gui.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/linter.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/models.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/openrouter.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/README.md +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/bash-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/c-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/clojure-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/d-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/go-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/java-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/matlab-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/python-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/r-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/README.md +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/bash-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/c-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/cpp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/dart-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/elisp-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/elixir-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/elm-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/fortran-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/go-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/haskell-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/hcl-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/java-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/javascript-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/julia-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/matlab-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/php-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/python-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/ql-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/ruby-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/rust-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/scala-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/typescript-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/queries/tree-sitter-languages/zig-tags.scm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/reasoning_tags.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/repomap.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/resources/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/resources/model-metadata.json +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/resources/model-settings.yml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/run_cmd.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/scrape.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/sendchat.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/special.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/versioncheck.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/voice.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/waiting.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch/watch_prompts.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/dependency_links.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/entry_points.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/patch_chat.egg-info/top_level.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/pytest.ini +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/pydub.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/python-compat.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-browser.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-dev.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-playwright.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/requirements-playwright.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/requirements/tree-sitter.in +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/blame.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/clean_metadata.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/issues.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/my_models.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/pip-compile.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/redact-cast.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/tmux_record.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/tsl_pack_langs.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/scripts/yank-old-versions.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/setup.cfg +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/__init__.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_aws_credentials.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_copypaste.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_deprecated.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_edit_apply.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_editor.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_exceptions.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_find_or_blocks.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_format_settings.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_linter.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_model_info_manager.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_models.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_openrouter.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_patch_coder.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_path_containment.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_reasoning.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_repomap.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_run_cmd.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_scripting.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_sendchat.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_special.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_ssl_verification.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_versioncheck.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_voice.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/basic/test_waiting.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/browser/test_browser.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/conftest.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/chat-history-search-replace-gold.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/chat-history.md +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/arduino/test.ino +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/bash/test.sh +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/c/test.c +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/chatito/test.chatito +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/clojure/test.clj +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/commonlisp/test.lisp +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/cpp/test.cpp +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/csharp/test.cs +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/d/test.d +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/dart/test.dart +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/elisp/test.el +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/elixir/test.ex +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/elm/test.elm +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/gleam/test.gleam +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/go/test.go +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/haskell/test.hs +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/hcl/test.tf +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/java/test.java +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/javascript/test.js +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/kotlin/test.kt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/lua/test.lua +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/matlab/test.m +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/ocaml/test.ml +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/ocaml_interface/test.mli +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/php/test.php +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/pony/test.pony +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/properties/test.properties +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/python/test.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/ql/test.ql +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/r/test.r +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/racket/test.rkt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/ruby/test.rb +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/rust/test.rs +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/scala/test.scala +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/solidity/test.sol +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/swift/test.swift +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/tsx/test.tsx +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/typescript/test.ts +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/udev/test.rules +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/languages/zig/test.zig +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/sample-code-base/sample.js +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/sample-code-base/sample.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/sample-code-base-repo-map.txt +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/watch.js +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/watch.lisp +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/watch.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/fixtures/watch_question.js +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/scrape/test_playwright_disable.py +0 -0
- {patch_chat-0.2.0 → patch_chat-0.4.0}/tests/scrape/test_scrape.py +0 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Copy an upstream aider issue into this fork, fix it and ship it
|
|
3
|
+
argument-hint: <upstream issue URL or number>
|
|
4
|
+
allowed-tools: Bash(gh:*), Bash(git:*), Bash(python:*), Bash(pytest:*), Bash(pre-commit:*), Read, Edit, Write, Grep, Glob
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Take the upstream issue at **$ARGUMENTS** (a `Aider-AI/aider` issue URL, or a bare number meaning
|
|
8
|
+
that repo) through the full pipeline below. Work top to bottom, one step at a time, and keep a
|
|
9
|
+
todo list.
|
|
10
|
+
|
|
11
|
+
Use the Read, Edit and Write tools for anything that reads or changes a file. Bash is for `gh`,
|
|
12
|
+
`git`, `pytest` and `pre-commit` — not for `cat`, `sed` or heredocs that rewrite source.
|
|
13
|
+
|
|
14
|
+
## 1. Read the upstream issue
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
gh issue view <N> --repo Aider-AI/aider --json number,title,body,author,createdAt,state,labels
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 2. Decide what the defect actually is
|
|
21
|
+
|
|
22
|
+
This fork renames the module: upstream `aider/foo.py` is `patch/foo.py` here, the distribution is
|
|
23
|
+
`patch-chat`, the CLI is `patch`. Locate the code the issue describes and confirm the behaviour
|
|
24
|
+
still reproduces here — upstream and fork have diverged, and some issues are already fixed.
|
|
25
|
+
|
|
26
|
+
Not every report is a code bug. A broken user environment, a provider outage or a support
|
|
27
|
+
question has no fix in this repo. When that is the case, say so plainly, and look for the defect
|
|
28
|
+
that *is* ours — usually how the tool presents the failure. Fix that instead, and explain the
|
|
29
|
+
split in the issue body you write in step 3. Do not invent a fix for something that is not broken.
|
|
30
|
+
|
|
31
|
+
If nothing here is worth changing, stop after step 3 and say why rather than closing the issue.
|
|
32
|
+
|
|
33
|
+
## 3. Copy it into the fork
|
|
34
|
+
|
|
35
|
+
Create the issue in `PierrunoYT/patch`, preserving the upstream title unless it names something
|
|
36
|
+
this fork calls differently, and the body verbatim. Do not add source links, reporter attribution,
|
|
37
|
+
or `@` mentions.
|
|
38
|
+
|
|
39
|
+
When your reading in step 2 differs from the report — a different root cause, or the conclusion
|
|
40
|
+
that the real defect is elsewhere — add a short paragraph after the original body saying so. That
|
|
41
|
+
paragraph is your analysis, kept separate from the copied words.
|
|
42
|
+
|
|
43
|
+
Label it from the repo's existing labels (`gh label list --repo PierrunoYT/patch`): always the
|
|
44
|
+
kind (`bug`, `documentation`, `enhancement`, `security`), always a severity (`critical`, `high`,
|
|
45
|
+
`medium`, `low`), and `good first issue` when the fix is genuinely small and self-contained.
|
|
46
|
+
|
|
47
|
+
## 4. Fix it
|
|
48
|
+
|
|
49
|
+
Follow the repository's own conventions in `AGENTS.md`. In short:
|
|
50
|
+
|
|
51
|
+
- Make the change, and add a regression test that fails without it. Tests live in
|
|
52
|
+
`tests/basic/`, mirroring the module layout.
|
|
53
|
+
- `pytest` — the whole suite, not just the new file.
|
|
54
|
+
- `pre-commit run --all-files` — all five hooks. Black may reformat; re-run until clean.
|
|
55
|
+
|
|
56
|
+
## 5. Update every doc the change touches — in the same pass, not as a follow-up
|
|
57
|
+
|
|
58
|
+
The task is not done when the tests pass. It is done when the docs match. Go through this list
|
|
59
|
+
each time and decide about each entry; the answer is often "nothing to change", but it has to be
|
|
60
|
+
a decision rather than an oversight.
|
|
61
|
+
|
|
62
|
+
- **`CHANGELOG.md`** — always, no exceptions. Under `## [Unreleased]`, in the right subsection
|
|
63
|
+
(`Added`, `Changed`, `Fixed`, `Removed`, `Security`). A docs-only change still gets an entry.
|
|
64
|
+
Blank line between top-level bullets; nested sub-lists stay tight. Describe what changed for
|
|
65
|
+
the reader, not which files you edited. A released `## [X.Y.Z]` section is mirrored in the git
|
|
66
|
+
tag and the GitHub release — never reword or restructure one.
|
|
67
|
+
- **`README.md`** — installation, usage, supported Python or model versions, security boundaries,
|
|
68
|
+
or anything a user reads before running the tool.
|
|
69
|
+
- **`CONTRIBUTING.md`** — setup, testing, dependencies, or the release process.
|
|
70
|
+
- **`AGENTS.md`** — repository layout, tooling, conventions, or a trap worth recording so the
|
|
71
|
+
next agent does not rediscover it. A new module, a renamed one, or a new rule about how the
|
|
72
|
+
code is organised belongs here.
|
|
73
|
+
- **Docstrings and comments next to the code you changed** — if the fix invalidates what a
|
|
74
|
+
nearby comment claims, fix the comment too.
|
|
75
|
+
- **User-facing strings in the code** — `patch/args.py` help text and the messages in
|
|
76
|
+
`patch/main.py`, `patch/commands.py` and `patch/io.py` are documentation the user actually
|
|
77
|
+
reads. A changed flag or behaviour usually means one of them is now wrong.
|
|
78
|
+
- **`AUDIT_REPORT.md` / `AUDIT_PROMPT.md`** — only when the fix lands on a finding those files
|
|
79
|
+
track, or rules out a candidate the prompt lists.
|
|
80
|
+
|
|
81
|
+
Then grep for whatever else still describes the old behaviour
|
|
82
|
+
(`grep -rn "<flag or phrase>" README.md CONTRIBUTING.md AGENTS.md patch/`). A stale doc is the
|
|
83
|
+
same defect as stale code.
|
|
84
|
+
|
|
85
|
+
Doc updates ship in the task's own commit (step 6), never in a later one.
|
|
86
|
+
|
|
87
|
+
## 6. Commit and push
|
|
88
|
+
|
|
89
|
+
One commit for the whole task — code, test and docs together. Conventional Commit subject, a body
|
|
90
|
+
explaining the defect and the fix, and a trailer line:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Closes #<fork issue>. Reported upstream in Aider-AI/aider#<N>.
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Push to `main`. That closes the fork issue. Confirm it did:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
gh issue list --repo PierrunoYT/patch --state closed --limit 3
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## 7. Nothing goes upstream
|
|
103
|
+
|
|
104
|
+
The pipeline ends at step 6. **This account is blocked from commenting on `Aider-AI/aider`**: on
|
|
105
|
+
2026-08-31 a maintainer minimised twelve comments from it as `SPAM` and blocked it, so
|
|
106
|
+
`gh issue comment` there returns `GraphQL: User is blocked (addComment)` and reactions are refused
|
|
107
|
+
too. Reading still works, which is why steps 1–6 are unaffected.
|
|
108
|
+
|
|
109
|
+
Do not post, do not write a comment for later, and do not look for another route to the same
|
|
110
|
+
effect. A block is that project's decision, not an error to work around. Writing a reply that
|
|
111
|
+
cannot be sent is wasted effort — if the block is ever lifted, or the user wants something to
|
|
112
|
+
relay by hand, they will ask.
|
|
113
|
+
|
|
114
|
+
## Report back
|
|
115
|
+
|
|
116
|
+
Finish with the fork issue number, the commit SHA, and the test and hook results.
|
|
@@ -1,138 +1,207 @@
|
|
|
1
|
-
# AGENTS.md
|
|
2
|
-
|
|
3
|
-
Guidance for AI coding agents working in this repository.
|
|
4
|
-
|
|
5
|
-
## What this project is
|
|
6
|
-
|
|
7
|
-
Patch is an AI pair-programming tool that runs in the terminal. The Python distribution is
|
|
8
|
-
[`patch-chat`](https://pypi.org/project/patch-chat/), the module is `patch/`, and the CLI entry
|
|
9
|
-
point is `patch` (`patch.main:main`). Release history lives in [CHANGELOG.md](CHANGELOG.md).
|
|
10
|
-
|
|
11
|
-
Versions come from git tags via setuptools-scm; the fork's own history starts at `0.1.0` and does
|
|
12
|
-
not continue upstream aider's `0.86.x` numbering.
|
|
13
|
-
|
|
14
|
-
## Setup
|
|
15
|
-
|
|
16
|
-
Python 3.10 through 3.14 (`requires-python = ">=3.10,<3.15"`).
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
pip install -e .
|
|
20
|
-
pip install -r requirements.txt
|
|
21
|
-
pip install -r requirements/requirements-dev.txt
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Testing
|
|
25
|
-
|
|
26
|
-
```
|
|
27
|
-
pytest # full suite
|
|
28
|
-
pytest tests/basic/test_coder.py # one file
|
|
29
|
-
pytest -k test_repomap # one pattern
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
`pytest.ini` sets `testpaths` to `tests/basic`, `tests/browser` and `tests/scrape`, and forces
|
|
33
|
-
`PATCH_ANALYTICS=false`. The bulk of the suite is
|
|
34
|
-
the 30+ files in `tests/basic/`. `benchmark/` is excluded from collection and is
|
|
35
|
-
not part of normal development.
|
|
36
|
-
|
|
37
|
-
## Linting and formatting
|
|
38
|
-
|
|
39
|
-
The project uses pre-commit. Run it before finishing any code change:
|
|
40
|
-
|
|
41
|
-
```
|
|
42
|
-
pre-commit run --all-files
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
Five hooks, all of which CI enforces:
|
|
46
|
-
|
|
47
|
-
- **black**, line length 100, with `--preview`
|
|
48
|
-
- **isort**, black profile
|
|
49
|
-
- **flake8**, max line length 100, ignoring `E203` and `W503`
|
|
50
|
-
- **mypy**, over the configured high-value module boundaries
|
|
51
|
-
- **codespell**
|
|
52
|
-
|
|
53
|
-
The line length is 100, not black's default 88. Match it.
|
|
54
|
-
|
|
55
|
-
## Repository layout
|
|
56
|
-
|
|
57
|
-
- `patch/coders/` — the heart of the project. Each edit format is a
|
|
58
|
-
`*_coder.py` paired with a `*_prompts.py` holding its system prompts.
|
|
59
|
-
`base_coder.py` (~2.6k lines) is the shared chat loop that all of them
|
|
60
|
-
subclass. `coders/usage.py` (token and cost accounting) and
|
|
61
|
-
`coders/chat_state.py` (the transcript and its background summariser)
|
|
62
|
-
hold state extracted from it. New edit formats are registered in `patch/coders/__init__.py`.
|
|
63
|
-
- `patch/main.py` — CLI entry, argument wiring, startup.
|
|
64
|
-
- `patch/models.py` — model definitions, aliases, and metadata. Adding support
|
|
65
|
-
for a new LLM usually means editing this file and nothing else.
|
|
66
|
-
- `patch/commands.py` — the in-chat `/slash` commands.
|
|
67
|
-
- `patch/repo.py`, `patch/repomap.py` — git integration and the tree-sitter
|
|
68
|
-
repository map.
|
|
69
|
-
- `patch/repo_trust.py` — the repository-trust boundary. The repo under edit is
|
|
70
|
-
untrusted input, and every rule about what its config files may set lives
|
|
71
|
-
here, applied in an enforced order. Adding an argument that names a file or a
|
|
72
|
-
command means recording a decision about it in this module, or a test fails.
|
|
73
|
-
- `tests/` — mirrors the module layout under `tests/basic/`.
|
|
74
|
-
|
|
75
|
-
Two root-level documents cover the audit history:
|
|
76
|
-
|
|
77
|
-
- `AUDIT_REPORT.md` — three completed audits (F-1 – F-97) and their remediation.
|
|
78
|
-
- `AUDIT_PROMPT.md` — the reusable brief for running another one. It carries the
|
|
79
|
-
evidence bar, the recurring defect shape worth searching for, and a list of
|
|
80
|
-
candidates already investigated and rejected, so a new round does not
|
|
81
|
-
re-derive them.
|
|
82
|
-
|
|
83
|
-
## Things not to edit
|
|
84
|
-
|
|
85
|
-
- `patch/_version.py` — generated by setuptools_scm, gitignored.
|
|
86
|
-
- `requirements/*.txt` — compiled from the matching `.in` files by
|
|
87
|
-
`./scripts/pip-compile.sh`. Edit the `.in` file and re-run the script; never
|
|
88
|
-
hand-edit the `.txt`.
|
|
89
|
-
|
|
90
|
-
## CI
|
|
91
|
-
|
|
92
|
-
Four workflows, all in `.github/workflows/`:
|
|
93
|
-
|
|
94
|
-
- `ubuntu-tests.yml` — pytest on Python 3.10 through 3.14
|
|
95
|
-
- `windows-tests.yml` — pytest on Python 3.10, 3.13
|
|
96
|
-
- `pre-commit.yml` — the hooks above
|
|
97
|
-
- `packaging.yml` — builds a wheel from a `.git`-less tree, installs it into a clean venv and
|
|
98
|
-
imports it from another directory. `pytest` runs from the repository root and therefore tests
|
|
99
|
-
the working tree, never the built artifact; this is the only job that does. Any new data file
|
|
100
|
-
must be added to `[tool.setuptools.package-data]` or it will fail here.
|
|
101
|
-
|
|
102
|
-
Publishing and deployment workflows are intentionally absent. Do not add them without the
|
|
103
|
-
required Patch-owned registries, infrastructure and secrets.
|
|
104
|
-
|
|
105
|
-
## Workflow
|
|
106
|
-
|
|
107
|
-
Finish each task completely before starting the next one. A task is not done when the
|
|
108
|
-
code works — it is done when the docs match and the work is committed.
|
|
109
|
-
|
|
110
|
-
1. Make the change and get the tests passing (`pytest`).
|
|
111
|
-
2. Run `pre-commit run --all-files`. All five hooks must pass.
|
|
112
|
-
3. Update every doc the change touches, in the same pass — not as a follow-up:
|
|
113
|
-
- `CHANGELOG.md` under `## [Unreleased]`, in the right subsection (`Added`,
|
|
114
|
-
`Changed`, `Fixed`, `Removed`, `Security`). This file records doc-only changes
|
|
115
|
-
too, so a docs commit still gets an entry. Describe what changed for the reader,
|
|
116
|
-
not which files were edited.
|
|
117
|
-
- `README.md` when installation, usage, security boundaries, or supported
|
|
118
|
-
versions change.
|
|
119
|
-
- `CONTRIBUTING.md` when setup, testing, dependencies, or the release process change.
|
|
120
|
-
- This file when the layout, tooling, or conventions change.
|
|
121
|
-
A released `## [X.Y.Z]` section is not a scratchpad: its text is mirrored in the annotated
|
|
122
|
-
git tag and the GitHub release, so do not reword or restructure it. Adding an entry for
|
|
123
|
-
something that genuinely shipped in that release is the one allowed edit — correcting an
|
|
124
|
-
omission is not rewriting history — and it comes with updating that release's body on
|
|
125
|
-
GitHub (`gh release edit`) in the same task. Leave the tag message alone; re-tagging a
|
|
126
|
-
published tag is worse than a tag message that trails the file.
|
|
127
|
-
4. Commit the code and its doc updates together, in one commit per task. Do not
|
|
128
|
-
batch several tasks into one commit, and do not leave a task's docs for later.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Guidance for AI coding agents working in this repository.
|
|
4
|
+
|
|
5
|
+
## What this project is
|
|
6
|
+
|
|
7
|
+
Patch is an AI pair-programming tool that runs in the terminal. The Python distribution is
|
|
8
|
+
[`patch-chat`](https://pypi.org/project/patch-chat/), the module is `patch/`, and the CLI entry
|
|
9
|
+
point is `patch` (`patch.main:main`). Release history lives in [CHANGELOG.md](CHANGELOG.md).
|
|
10
|
+
|
|
11
|
+
Versions come from git tags via setuptools-scm; the fork's own history starts at `0.1.0` and does
|
|
12
|
+
not continue upstream aider's `0.86.x` numbering.
|
|
13
|
+
|
|
14
|
+
## Setup
|
|
15
|
+
|
|
16
|
+
Python 3.10 through 3.14 (`requires-python = ">=3.10,<3.15"`).
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
pip install -e .
|
|
20
|
+
pip install -r requirements.txt
|
|
21
|
+
pip install -r requirements/requirements-dev.txt
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Testing
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
pytest # full suite
|
|
28
|
+
pytest tests/basic/test_coder.py # one file
|
|
29
|
+
pytest -k test_repomap # one pattern
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`pytest.ini` sets `testpaths` to `tests/basic`, `tests/browser` and `tests/scrape`, and forces
|
|
33
|
+
`PATCH_ANALYTICS=false`. The bulk of the suite is
|
|
34
|
+
the 30+ files in `tests/basic/`. `benchmark/` is excluded from collection and is
|
|
35
|
+
not part of normal development.
|
|
36
|
+
|
|
37
|
+
## Linting and formatting
|
|
38
|
+
|
|
39
|
+
The project uses pre-commit. Run it before finishing any code change:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
pre-commit run --all-files
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Five hooks, all of which CI enforces:
|
|
46
|
+
|
|
47
|
+
- **black**, line length 100, with `--preview`
|
|
48
|
+
- **isort**, black profile
|
|
49
|
+
- **flake8**, max line length 100, ignoring `E203` and `W503`
|
|
50
|
+
- **mypy**, over the configured high-value module boundaries
|
|
51
|
+
- **codespell**
|
|
52
|
+
|
|
53
|
+
The line length is 100, not black's default 88. Match it.
|
|
54
|
+
|
|
55
|
+
## Repository layout
|
|
56
|
+
|
|
57
|
+
- `patch/coders/` — the heart of the project. Each edit format is a
|
|
58
|
+
`*_coder.py` paired with a `*_prompts.py` holding its system prompts.
|
|
59
|
+
`base_coder.py` (~2.6k lines) is the shared chat loop that all of them
|
|
60
|
+
subclass. `coders/usage.py` (token and cost accounting) and
|
|
61
|
+
`coders/chat_state.py` (the transcript and its background summariser)
|
|
62
|
+
hold state extracted from it. New edit formats are registered in `patch/coders/__init__.py`.
|
|
63
|
+
- `patch/main.py` — CLI entry, argument wiring, startup.
|
|
64
|
+
- `patch/models.py` — model definitions, aliases, and metadata. Adding support
|
|
65
|
+
for a new LLM usually means editing this file and nothing else.
|
|
66
|
+
- `patch/commands.py` — the in-chat `/slash` commands.
|
|
67
|
+
- `patch/repo.py`, `patch/repomap.py` — git integration and the tree-sitter
|
|
68
|
+
repository map.
|
|
69
|
+
- `patch/repo_trust.py` — the repository-trust boundary. The repo under edit is
|
|
70
|
+
untrusted input, and every rule about what its config files may set lives
|
|
71
|
+
here, applied in an enforced order. Adding an argument that names a file or a
|
|
72
|
+
command means recording a decision about it in this module, or a test fails.
|
|
73
|
+
- `tests/` — mirrors the module layout under `tests/basic/`.
|
|
74
|
+
|
|
75
|
+
Two root-level documents cover the audit history:
|
|
76
|
+
|
|
77
|
+
- `AUDIT_REPORT.md` — three completed audits (F-1 – F-97) and their remediation.
|
|
78
|
+
- `AUDIT_PROMPT.md` — the reusable brief for running another one. It carries the
|
|
79
|
+
evidence bar, the recurring defect shape worth searching for, and a list of
|
|
80
|
+
candidates already investigated and rejected, so a new round does not
|
|
81
|
+
re-derive them.
|
|
82
|
+
|
|
83
|
+
## Things not to edit
|
|
84
|
+
|
|
85
|
+
- `patch/_version.py` — generated by setuptools_scm, gitignored.
|
|
86
|
+
- `requirements/*.txt` — compiled from the matching `.in` files by
|
|
87
|
+
`./scripts/pip-compile.sh`. Edit the `.in` file and re-run the script; never
|
|
88
|
+
hand-edit the `.txt`.
|
|
89
|
+
|
|
90
|
+
## CI
|
|
91
|
+
|
|
92
|
+
Four workflows, all in `.github/workflows/`:
|
|
93
|
+
|
|
94
|
+
- `ubuntu-tests.yml` — pytest on Python 3.10 through 3.14
|
|
95
|
+
- `windows-tests.yml` — pytest on Python 3.10, 3.13
|
|
96
|
+
- `pre-commit.yml` — the hooks above
|
|
97
|
+
- `packaging.yml` — builds a wheel from a `.git`-less tree, installs it into a clean venv and
|
|
98
|
+
imports it from another directory. `pytest` runs from the repository root and therefore tests
|
|
99
|
+
the working tree, never the built artifact; this is the only job that does. Any new data file
|
|
100
|
+
must be added to `[tool.setuptools.package-data]` or it will fail here.
|
|
101
|
+
|
|
102
|
+
Publishing and deployment workflows are intentionally absent. Do not add them without the
|
|
103
|
+
required Patch-owned registries, infrastructure and secrets.
|
|
104
|
+
|
|
105
|
+
## Workflow
|
|
106
|
+
|
|
107
|
+
Finish each task completely before starting the next one. A task is not done when the
|
|
108
|
+
code works — it is done when the docs match and the work is committed.
|
|
109
|
+
|
|
110
|
+
1. Make the change and get the tests passing (`pytest`).
|
|
111
|
+
2. Run `pre-commit run --all-files`. All five hooks must pass.
|
|
112
|
+
3. Update every doc the change touches, in the same pass — not as a follow-up:
|
|
113
|
+
- `CHANGELOG.md` under `## [Unreleased]`, in the right subsection (`Added`,
|
|
114
|
+
`Changed`, `Fixed`, `Removed`, `Security`). This file records doc-only changes
|
|
115
|
+
too, so a docs commit still gets an entry. Describe what changed for the reader,
|
|
116
|
+
not which files were edited.
|
|
117
|
+
- `README.md` when installation, usage, security boundaries, or supported
|
|
118
|
+
versions change.
|
|
119
|
+
- `CONTRIBUTING.md` when setup, testing, dependencies, or the release process change.
|
|
120
|
+
- This file when the layout, tooling, or conventions change.
|
|
121
|
+
A released `## [X.Y.Z]` section is not a scratchpad: its text is mirrored in the annotated
|
|
122
|
+
git tag and the GitHub release, so do not reword or restructure it. Adding an entry for
|
|
123
|
+
something that genuinely shipped in that release is the one allowed edit — correcting an
|
|
124
|
+
omission is not rewriting history — and it comes with updating that release's body on
|
|
125
|
+
GitHub (`gh release edit`) in the same task. Leave the tag message alone; re-tagging a
|
|
126
|
+
published tag is worse than a tag message that trails the file.
|
|
127
|
+
4. Commit the code and its doc updates together, in one commit per task. Do not
|
|
128
|
+
batch several tasks into one commit, and do not leave a task's docs for later.
|
|
129
|
+
|
|
130
|
+
### Upstream issues
|
|
131
|
+
|
|
132
|
+
Patch is a fork of [aider](https://github.com/Aider-AI/aider), and reports filed there often
|
|
133
|
+
apply here. `.claude/commands/upstream-issue.md` is a Claude Code slash command
|
|
134
|
+
(`/upstream-issue <url>`) that carries one from upstream to shipped: copy it into this repo's
|
|
135
|
+
tracker without source or reporter attribution, judge whether the defect is really ours — upstream
|
|
136
|
+
`aider/foo.py` is `patch/foo.py` here, and a broken user environment has no fix in this code —
|
|
137
|
+
write the fix and a regression test, update the docs above, and commit with `Closes #N`. Editing
|
|
138
|
+
that file is how the procedure changes; do not keep a second copy of it here.
|
|
139
|
+
|
|
140
|
+
The upstream half of that loop is closed. On 2026-08-31 an aider maintainer minimised twelve
|
|
141
|
+
comments from this account as `SPAM` and blocked it from the repository: `gh issue comment` there
|
|
142
|
+
returns `GraphQL: User is blocked (addComment)`, and reactions are refused too. Reading still
|
|
143
|
+
works, so copying issues over and fixing them is unaffected — the command now ends at the commit,
|
|
144
|
+
sends nothing upstream, and omits source and reporter references from copied issues. Do not try to
|
|
145
|
+
post from elsewhere.
|
|
146
|
+
|
|
147
|
+
## Releases
|
|
148
|
+
|
|
149
|
+
The full steps are in `CONTRIBUTING.md` under "Making a Release". Read them before cutting one;
|
|
150
|
+
the traps below have each cost a rebuild.
|
|
151
|
+
|
|
152
|
+
- **The version comes from the git tag, nothing else.** `patch/__init__.py`'s `safe_version` and
|
|
153
|
+
`pyproject.toml`'s `fallback_version` are floors, not the version. Bumping them without tagging
|
|
154
|
+
makes every run report `X.Y.Z.dev+less`, because the generated `patch/_version.py` left over
|
|
155
|
+
from the previous build is now below the new floor. Tagging and rebuilding clears it.
|
|
156
|
+
- **Tag with `--cleanup=verbatim`.** `git tag -F` otherwise defaults to `--cleanup=strip` and
|
|
157
|
+
deletes every line beginning with `#`, silently removing the `##` title and all the `###`
|
|
158
|
+
headings from a changelog section used as the tag message. Both `v0.1.0` and `v0.2.0` were
|
|
159
|
+
tagged without it, so their tag messages are flattened; the release bodies are fine, because
|
|
160
|
+
both were published with `--notes-file` from the changelog rather than from the tag.
|
|
161
|
+
- **Reuse the notes file for `gh release create --notes-file`.** Write the changelog section to a
|
|
162
|
+
file in step 2 and pass that same path in step 4. Never spell it as a `<placeholder>`: in
|
|
163
|
+
PowerShell, the default shell here, `<` is a reserved operator and the command fails to parse
|
|
164
|
+
before `gh` runs.
|
|
165
|
+
- **Re-tag only while the tag is local.** If a later commit changes the changelog section, delete
|
|
166
|
+
the tag, re-tag on the new HEAD, and rebuild — the artifacts must come from the tagged commit.
|
|
167
|
+
Once the tag is pushed this is closed off; see the rule in Workflow step 3.
|
|
168
|
+
- **Verify the artifact, not the checkout.** Install the built wheel into a venv outside the
|
|
169
|
+
repository and check `patch --version` plus the bundled data files
|
|
170
|
+
(`resources/model-settings.yml`, `queries/**/*.scm`). From the repository root `tests/__init__.py`
|
|
171
|
+
puts the working tree on `sys.path`, so an in-tree import proves nothing about the wheel.
|
|
172
|
+
|
|
173
|
+
## Conventions
|
|
174
|
+
|
|
175
|
+
- Match the surrounding style rather than importing a new one. The codebase is
|
|
176
|
+
plain Python with light comments and no type annotations in most modules.
|
|
177
|
+
- Tests are a mix of `unittest.TestCase` classes (about half the files in
|
|
178
|
+
`tests/basic/`) and plain pytest functions. Follow whichever style the file
|
|
179
|
+
you are editing already uses.
|
|
180
|
+
- Commits follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`), as
|
|
181
|
+
seen in recent history.
|
|
182
|
+
- Separate every top-level `CHANGELOG.md` bullet with a blank line. CommonMark makes a list
|
|
183
|
+
*loose* -- each item wrapped in `<p>`, with paragraph margins -- as soon as any two of its items
|
|
184
|
+
are separated by a blank line, and *tight* otherwise. One stray blank line therefore respaces a
|
|
185
|
+
whole section, so a file mixing the two renders on GitHub with some sections airy and others
|
|
186
|
+
dense. Entries here are multi-sentence, so loose is the target. Nested sub-lists stay tight.
|
|
187
|
+
- Anything passed to `analytics.event(...)` leaves the machine. `Analytics.event` scrubs every
|
|
188
|
+
property -- URL query strings, absolute paths, length -- so a call site cannot leak by
|
|
189
|
+
forgetting, but the scrubber only removes shapes it knows. Send a class name, a fixed reason or
|
|
190
|
+
a count; never `str(err)`, never free text from a remote server, and route a model name through
|
|
191
|
+
`redact_model_name`. The opt-in prompt in `patch/main.py` is a promise about this.
|
|
192
|
+
- A new `raise SwitchCoder(...)` has to say whether the user's message was already carried out
|
|
193
|
+
before the switch. `/ask PROMPT` answers on a temporary coder and then switches back, so it
|
|
194
|
+
passes `message_handled=True`; `/model` switches instead of doing anything, and leaves the
|
|
195
|
+
default. `run_one_message` in `patch/main.py` uses that to decide whether a one-shot
|
|
196
|
+
`--message` run lost the user's request or completed it.
|
|
197
|
+
- A chat message's `content` is not always a string. An assistant reply that is only a function
|
|
198
|
+
call carries `content=None`, and a message carrying an image carries a list of parts. Read the
|
|
199
|
+
words with `patch.utils.message_content_text(msg)`; concatenating `msg["content"]` raises
|
|
200
|
+
`TypeError` on an ordinary conversation.
|
|
201
|
+
- Write to the terminal through `InputOutput._console_print`, never `self.console.print`
|
|
202
|
+
directly. A terminal write can fail on its own — a legacy Windows console rejects some writes
|
|
203
|
+
with `OSError: [Errno 22]`, and a closed or redirected handle raises too — and most callers are
|
|
204
|
+
reporting an error already, so an escaping `OSError` replaces the message with a traceback and
|
|
205
|
+
ends the session. `_console_print` degrades to ASCII, then to a plain `print`, then to silence.
|
|
206
|
+
The exception is a `Console(file=StringIO())` used to format a string, which never touches a
|
|
207
|
+
terminal.
|
|
@@ -274,6 +274,16 @@ Reject in `allowed_to_edit` and in `patch_coder`'s `move_path` (see F-8).
|
|
|
274
274
|
`.env` supplying a key is a common legitimate workflow and is not the exfiltration primitive; the
|
|
275
275
|
endpoint redirect is, and that is blocked.
|
|
276
276
|
|
|
277
|
+
**Revised** while porting `Aider-AI/aider#5622`. The narrowing above was half right: supplying a
|
|
278
|
+
key is a legitimate workflow, but *replacing* the user's own key is a second exfiltration
|
|
279
|
+
primitive, not a lesser version of the first. A repository shipping `OPENAI_API_KEY=sk-attacker`
|
|
280
|
+
sends the victim's prompts to the real provider on the attacker's account, where the attacker can
|
|
281
|
+
read them — no fake endpoint required, and nothing on the denylist touches it. An untrusted
|
|
282
|
+
repository `.env` now applies only to variables the inherited environment does not already define,
|
|
283
|
+
and reports the ones it left alone. The legitimate workflow is unaffected, because a project key
|
|
284
|
+
still applies when the user has not set one; `override=False` for the user's own files was *not*
|
|
285
|
+
adopted, since naming `--env-file` on the command line is an instruction rather than a surprise.
|
|
286
|
+
|
|
277
287
|
Opt back in with `--trust-repo-config` / `PATCH_TRUST_REPO_CONFIG`, accepted only from the command
|
|
278
288
|
line or the ambient shell environment — both read before the repository `.env` is loaded — and
|
|
279
289
|
`trust-repo-config` is itself on the blocked list, so a repository cannot self-grant from either
|
|
@@ -3608,3 +3618,20 @@ test the safety of each policy decision, not only the presence of one.
|
|
|
3608
3618
|
The 9.0 post-remediation score reflects all nine findings closed with focused tests and the full
|
|
3609
3619
|
gate green. It remains below 10 because the fourth audit's structural constraints are unchanged:
|
|
3610
3620
|
the type gate is intentionally partial and the largest modules still carry broad responsibilities.
|
|
3621
|
+
|
|
3622
|
+
---
|
|
3623
|
+
|
|
3624
|
+
## Post-audit upstream issue remediation
|
|
3625
|
+
|
|
3626
|
+
These upstream reports were selected from the 2026-08-31 `aider-issues.json` snapshot after the
|
|
3627
|
+
fourth audit. They are not new audit findings and do not extend the F-1 – F-106 sequence. The
|
|
3628
|
+
snapshot has since been pruned of every report resolved in this fork, so the rows below are no
|
|
3629
|
+
longer found in it; its `removed_resolved` block lists the upstream numbers that were dropped.
|
|
3630
|
+
|
|
3631
|
+
| Upstream report | Severity | Fork issue | Fix | Verification |
|
|
3632
|
+
| --- | --- | --- | --- | --- |
|
|
3633
|
+
| GitPython CVE-2026-42215, CVE-2026-42284, CVE-2026-44243 and CVE-2026-44244 | High | [#137](https://github.com/PierrunoYT/patch/issues/137) | **Resolved in `bf16ec6db`** by requiring GitPython 3.1.49+ | Dependency regression test, full `pytest`, and all pre-commit hooks |
|
|
3634
|
+
| Pillow CVE-2026-42311 | High | [#138](https://github.com/PierrunoYT/patch/issues/138) | **Resolved in `a7ef1ca21`** by requiring Pillow 12.2.0+ | Dependency regression test, full `pytest`, and all pre-commit hooks |
|
|
3635
|
+
| urllib3 CVE-2026-44431 | High | [#139](https://github.com/PierrunoYT/patch/issues/139) | **Resolved in `23358a200`** by requiring urllib3 2.7.0+ | Dependency regression test, full `pytest`, and all pre-commit hooks |
|
|
3636
|
+
| Fatal provider errors return success in one-shot mode | High | [#140](https://github.com/PierrunoYT/patch/issues/140) | **Resolved in `0af8c6508`** by propagating per-message provider failure to the CLI status | API-error retry-exhaustion test, one-shot status test, full `pytest`, and all pre-commit hooks |
|
|
3637
|
+
| Whole-file mode mishandles unified-diff output | Medium | [#141](https://github.com/PierrunoYT/patch/issues/141) | **Resolved in `083edb34f`** by detecting the format mismatch before edit parsing, with fence-span tracking added in `81cba83b0` and headerless diff fences covered in `a682516ef` | Bare, fenced and headerless diff regressions, a listing of a `.patch` file, full `pytest`, and all pre-commit hooks |
|