patch-chat 0.1.0__tar.gz → 0.2.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.1.0 → patch_chat-0.2.0}/.agents/setup +4 -1
- patch_chat-0.2.0/.github/workflows/packaging.yml +103 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.github/workflows/pre-commit.yml +10 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.github/workflows/ubuntu-tests.yml +9 -4
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.github/workflows/windows-tests.yml +5 -3
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.gitignore +3 -0
- patch_chat-0.2.0/AGENTS.md +138 -0
- patch_chat-0.2.0/AUDIT_PROMPT.md +314 -0
- patch_chat-0.2.0/AUDIT_REPORT.md +3610 -0
- patch_chat-0.2.0/CHANGELOG.md +624 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/CONTRIBUTING.md +289 -226
- {patch_chat-0.1.0/patch_chat.egg-info → patch_chat-0.2.0}/PKG-INFO +51 -22
- {patch_chat-0.1.0 → patch_chat-0.2.0}/README.md +47 -8
- {patch_chat-0.1.0 → patch_chat-0.2.0}/docker/Dockerfile +10 -7
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/__init__.py +20 -20
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/_version.py +3 -3
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/analytics.py +1 -13
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/args.py +12 -3
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/args_formatter.py +226 -228
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/__init__.py +53 -32
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/base_coder.py +331 -215
- patch_chat-0.2.0/patch/coders/chat_state.py +92 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_coder.py +25 -11
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_fenced_coder.py +9 -10
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_func_coder.py +1 -2
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/patch_coder.py +10 -3
- patch_chat-0.2.0/patch/coders/search_replace.py +309 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/single_wholefile_func_coder.py +1 -1
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/udiff_coder.py +31 -8
- patch_chat-0.2.0/patch/coders/usage.py +186 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/wholefile_coder.py +1 -2
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/wholefile_func_coder.py +133 -134
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/commands.py +58 -22
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/copypaste.py +71 -70
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/diffs.py +4 -4
- patch_chat-0.2.0/patch/dump.py +33 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/editor.py +16 -5
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/exceptions.py +43 -12
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/history.py +1 -23
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/io.py +1318 -1209
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/linter.py +25 -8
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/llm.py +7 -6
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/main.py +433 -537
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/mdstream.py +241 -243
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/models.py +44 -10
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/onboarding.py +72 -22
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/reasoning_tags.py +80 -82
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/repo.py +28 -43
- patch_chat-0.2.0/patch/repo_trust.py +580 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/repomap.py +38 -14
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/report.py +57 -4
- patch_chat-0.2.0/patch/run_cmd.py +338 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/scrape.py +332 -316
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/sendchat.py +60 -61
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/utils.py +12 -11
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/versioncheck.py +112 -113
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/voice.py +198 -200
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/waiting.py +2 -1
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/watch.py +6 -41
- {patch_chat-0.1.0 → patch_chat-0.2.0/patch_chat.egg-info}/PKG-INFO +51 -22
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/SOURCES.txt +5 -1
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/requires.txt +4 -16
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/scm_file_list.json +5 -1
- patch_chat-0.2.0/patch_chat.egg-info/scm_version.json +8 -0
- patch_chat-0.2.0/pyproject.toml +133 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/common-constraints.txt +504 -535
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-browser.txt +169 -169
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-dev.in +20 -21
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-dev.txt +359 -398
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-playwright.txt +18 -18
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements.in +47 -53
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/tree-sitter.in +2 -3
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements.txt +464 -477
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/pip-compile.sh +46 -46
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_analytics.py +0 -5
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_aws_credentials.py +120 -169
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_coder.py +1671 -1573
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_commands.py +2297 -2226
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_editblock.py +50 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_editor.py +23 -1
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_history.py +68 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_io.py +236 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_linter.py +47 -3
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_main.py +26 -2
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_models.py +733 -668
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_onboarding.py +56 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_path_containment.py +450 -286
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_repo.py +726 -716
- patch_chat-0.2.0/tests/basic/test_repo_config_trust.py +680 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_repomap.py +71 -1
- patch_chat-0.2.0/tests/basic/test_run_cmd.py +207 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_udiff.py +241 -167
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/browser/test_browser.py +36 -36
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/conftest.py +94 -59
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/scrape/test_scrape.py +56 -0
- patch_chat-0.1.0/AGENTS.md +0 -92
- patch_chat-0.1.0/AUDIT_REPORT.md +0 -1133
- patch_chat-0.1.0/CHANGELOG.md +0 -178
- patch_chat-0.1.0/patch/coders/search_replace.py +0 -757
- patch_chat-0.1.0/patch/dump.py +0 -29
- patch_chat-0.1.0/patch/run_cmd.py +0 -146
- patch_chat-0.1.0/patch_chat.egg-info/scm_version.json +0 -8
- patch_chat-0.1.0/pyproject.toml +0 -74
- patch_chat-0.1.0/scripts/versionbump.py +0 -175
- patch_chat-0.1.0/tests/basic/test_repo_config_trust.py +0 -216
- patch_chat-0.1.0/tests/basic/test_run_cmd.py +0 -45
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.agents/resume +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.dockerignore +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.flake8 +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.github/ISSUE_TEMPLATE/issue.yml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/.pre-commit-config.yaml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/LICENSE.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/MANIFEST.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/Dockerfile +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/benchmark.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/clone-exercism.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/cpp-test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/docker.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/docker_build.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/install-docker-ubuntu.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/npm-test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/plot.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/plots.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/refactor_tools.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/rsync.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/rungrid.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/swe-bench-lite.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/swe-bench.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/swe_bench.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/benchmark/test_benchmark.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/__main__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/architect_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/architect_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/ask_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/ask_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/base_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/chat_chunks.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/context_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/context_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/edit_apply.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_fenced_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editblock_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_diff_fenced_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_diff_fenced_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_editblock_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_editblock_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_whole_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/editor_whole_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/patch_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/shell.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/single_wholefile_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/udiff_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/udiff_simple.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/udiff_simple_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/wholefile_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/coders/wholefile_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/deprecated.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/format_settings.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/gui.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/openrouter.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/bash-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/c-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/clojure-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/d-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/go-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/java-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/matlab-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/python-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/r-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/bash-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/c-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/cpp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/dart-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/elisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/elixir-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/elm-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/fortran-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/go-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/haskell-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/hcl-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/java-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/javascript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/julia-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/matlab-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/php-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/python-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/ql-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/ruby-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/rust-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/scala-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/typescript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/queries/tree-sitter-languages/zig-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/resources/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/resources/model-metadata.json +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/resources/model-settings.yml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/special.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/urls.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch/watch_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/dependency_links.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/entry_points.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/patch_chat.egg-info/top_level.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/pytest.ini +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/pydub.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/python-compat.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-browser.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/requirements/requirements-playwright.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/blame.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/clean_metadata.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/issues.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/my_models.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/redact-cast.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/tmux_record.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/tsl_pack_langs.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/scripts/yank-old-versions.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/setup.cfg +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_copypaste.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_deprecated.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_edit_apply.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_exceptions.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_find_or_blocks.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_format_settings.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_model_info_manager.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_openrouter.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_patch_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_reasoning.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_report.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_sanity_check_repo.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_scripting.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_sendchat.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_special.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_ssl_verification.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_urls.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_utils.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_versioncheck.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_voice.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_waiting.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_watch.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/basic/test_wholefile.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/chat-history-search-replace-gold.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/chat-history.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/arduino/test.ino +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/bash/test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/c/test.c +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/chatito/test.chatito +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/clojure/test.clj +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/commonlisp/test.lisp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/cpp/test.cpp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/csharp/test.cs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/d/test.d +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/dart/test.dart +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/elisp/test.el +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/elixir/test.ex +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/elm/test.elm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/gleam/test.gleam +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/go/test.go +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/haskell/test.hs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/hcl/test.tf +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/java/test.java +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/javascript/test.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/kotlin/test.kt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/lua/test.lua +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/matlab/test.m +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/ocaml/test.ml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/ocaml_interface/test.mli +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/php/test.php +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/pony/test.pony +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/properties/test.properties +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/python/test.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/ql/test.ql +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/r/test.r +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/racket/test.rkt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/ruby/test.rb +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/rust/test.rs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/scala/test.scala +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/solidity/test.sol +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/swift/test.swift +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/tsx/test.tsx +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/typescript/test.ts +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/udev/test.rules +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/languages/zig/test.zig +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/sample-code-base/sample.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/sample-code-base/sample.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/sample-code-base-repo-map.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/watch.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/watch.lisp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/watch.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/fixtures/watch_question.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.2.0}/tests/scrape/test_playwright_disable.py +0 -0
|
@@ -20,8 +20,11 @@ if ((${#missing_packages[@]})); then
|
|
|
20
20
|
fi
|
|
21
21
|
|
|
22
22
|
step "Installing Python project and development dependencies"
|
|
23
|
+
# No --extra-index-url: it resolves each name across both indexes and takes the
|
|
24
|
+
# highest version, rather than replacing the index as --index-url does. Nothing
|
|
25
|
+
# in the pinned locks needs the torch index; docker/Dockerfile uses --index-url
|
|
26
|
+
# where it genuinely does.
|
|
23
27
|
python3 -m pip install --editable . \
|
|
24
|
-
--extra-index-url https://download.pytorch.org/whl/cpu \
|
|
25
28
|
--requirement requirements/requirements-dev.txt \
|
|
26
29
|
--requirement requirements/requirements-browser.txt \
|
|
27
30
|
--requirement requirements/requirements-playwright.txt
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
name: Packaging
|
|
2
|
+
|
|
3
|
+
# The test suite runs from the repository root, where `tests/__init__.py` puts the
|
|
4
|
+
# working tree on sys.path -- so `import patch` resolves to ./patch and the suite
|
|
5
|
+
# never sees the artifact users install. This job closes that gap: it builds a
|
|
6
|
+
# wheel with no .git present (the same context docker/Dockerfile gets, since
|
|
7
|
+
# .dockerignore excludes .git), installs it into a clean environment, and imports
|
|
8
|
+
# it from another directory.
|
|
9
|
+
#
|
|
10
|
+
# Without .git, setuptools-scm's file finder is unavailable and only the files
|
|
11
|
+
# enumerated in [tool.setuptools.package-data] survive. That is how
|
|
12
|
+
# patch/resources/model-settings.yml went missing once already; models.py opens it
|
|
13
|
+
# at import time, so the wheel raised FileNotFoundError on every invocation while
|
|
14
|
+
# passing the whole test suite.
|
|
15
|
+
|
|
16
|
+
on:
|
|
17
|
+
push:
|
|
18
|
+
branches:
|
|
19
|
+
- main
|
|
20
|
+
pull_request:
|
|
21
|
+
branches:
|
|
22
|
+
- main
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
installed-wheel:
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
|
|
28
|
+
steps:
|
|
29
|
+
- name: Check out repository
|
|
30
|
+
uses: actions/checkout@v4
|
|
31
|
+
with:
|
|
32
|
+
fetch-depth: 0
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.10"
|
|
38
|
+
|
|
39
|
+
- name: Build a wheel from a source tree with no .git
|
|
40
|
+
run: |
|
|
41
|
+
python -m pip install --upgrade pip build
|
|
42
|
+
mkdir -p /tmp/nogit
|
|
43
|
+
# Deliberately not `git archive`: this must mirror `COPY . /tmp/patch`,
|
|
44
|
+
# i.e. the working tree minus the directories .dockerignore excludes.
|
|
45
|
+
tar --exclude=.git --exclude='*.egg-info' --exclude=dist --exclude=build \
|
|
46
|
+
-cf - . | tar -C /tmp/nogit -xf -
|
|
47
|
+
test ! -e /tmp/nogit/.git
|
|
48
|
+
cd /tmp/nogit && python -m build --wheel --outdir /tmp/dist .
|
|
49
|
+
|
|
50
|
+
- name: Install the wheel into a clean environment
|
|
51
|
+
run: |
|
|
52
|
+
python -m venv /tmp/venv
|
|
53
|
+
/tmp/venv/bin/python -m pip install --upgrade pip
|
|
54
|
+
/tmp/venv/bin/python -m pip install /tmp/dist/*.whl
|
|
55
|
+
|
|
56
|
+
- name: Import it from another directory
|
|
57
|
+
run: |
|
|
58
|
+
mkdir -p /tmp/elsewhere
|
|
59
|
+
cd /tmp/elsewhere
|
|
60
|
+
# Must not resolve to a source checkout.
|
|
61
|
+
/tmp/venv/bin/python -c "
|
|
62
|
+
import patch, patch.main, patch.models
|
|
63
|
+
assert 'site-packages' in patch.__file__, patch.__file__
|
|
64
|
+
assert patch.models.MODEL_SETTINGS, 'model-settings.yml did not load'
|
|
65
|
+
print('imported', patch.__file__)
|
|
66
|
+
print('model settings:', len(patch.models.MODEL_SETTINGS))
|
|
67
|
+
"
|
|
68
|
+
|
|
69
|
+
- name: Check the console script is wired up
|
|
70
|
+
run: |
|
|
71
|
+
cd /tmp/elsewhere
|
|
72
|
+
/tmp/venv/bin/patch --version
|
|
73
|
+
|
|
74
|
+
- name: Verify wheel metadata and declared package data
|
|
75
|
+
run: |
|
|
76
|
+
python - <<'EOF'
|
|
77
|
+
from email.parser import BytesParser
|
|
78
|
+
import glob
|
|
79
|
+
from pathlib import Path
|
|
80
|
+
import zipfile
|
|
81
|
+
|
|
82
|
+
with zipfile.ZipFile(glob.glob("/tmp/dist/*.whl")[0]) as wheel:
|
|
83
|
+
names = wheel.namelist()
|
|
84
|
+
metadata_name = next(n for n in names if n.endswith(".dist-info/METADATA"))
|
|
85
|
+
metadata = BytesParser().parsebytes(wheel.read(metadata_name))
|
|
86
|
+
|
|
87
|
+
assert metadata["License-Expression"] == "Apache-2.0"
|
|
88
|
+
assert metadata["Requires-Python"] == "<3.15,>=3.10"
|
|
89
|
+
assert any(n.endswith(".dist-info/licenses/LICENSE.txt") for n in names)
|
|
90
|
+
|
|
91
|
+
required = [
|
|
92
|
+
"patch/resources/model-settings.yml",
|
|
93
|
+
"patch/resources/model-metadata.json",
|
|
94
|
+
]
|
|
95
|
+
missing = [r for r in required if r not in names]
|
|
96
|
+
assert not missing, f"missing from the wheel: {missing}"
|
|
97
|
+
assert any(n.endswith(".scm") for n in names), "no tree-sitter queries in the wheel"
|
|
98
|
+
assert any(n.startswith("patch/coders/") for n in names), "patch.coders missing"
|
|
99
|
+
|
|
100
|
+
readme = Path("README.md").read_text()
|
|
101
|
+
assert "supports Python 3.10 through 3.14" in readme
|
|
102
|
+
print(f"wheel contains {len(names)} entries; metadata and required files verified")
|
|
103
|
+
EOF
|
|
@@ -14,6 +14,16 @@ jobs:
|
|
|
14
14
|
- run: sudo apt-get update && sudo apt-get install cppcheck uncrustify
|
|
15
15
|
if: false
|
|
16
16
|
- uses: actions/checkout@v4
|
|
17
|
+
# Pin the interpreter. Without this every hook environment -- including
|
|
18
|
+
# mypy, which pyproject.toml configures for python_version = "3.10" -- is
|
|
19
|
+
# built against whatever ubuntu-latest currently ships, so the type gate
|
|
20
|
+
# drifts silently when the runner image changes. It also populates
|
|
21
|
+
# env.pythonLocation, which the cache keys below interpolate: unset, they
|
|
22
|
+
# collapse to `pre-commit-4||<hash>` and restore hook virtualenvs built
|
|
23
|
+
# against a different Python.
|
|
24
|
+
- uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: "3.10"
|
|
17
27
|
- run: python -m pip install pre-commit
|
|
18
28
|
- uses: actions/cache/restore@v4
|
|
19
29
|
with:
|
|
@@ -32,7 +32,6 @@ jobs:
|
|
|
32
32
|
cache: pip
|
|
33
33
|
cache-dependency-path: |
|
|
34
34
|
requirements.txt
|
|
35
|
-
requirements/requirements-dev.txt
|
|
36
35
|
|
|
37
36
|
- name: Install system dependencies
|
|
38
37
|
run: |
|
|
@@ -42,11 +41,17 @@ jobs:
|
|
|
42
41
|
- name: Install dependencies
|
|
43
42
|
run: |
|
|
44
43
|
python -m pip install --upgrade pip
|
|
45
|
-
pip install pytest pytest-env
|
|
46
|
-
|
|
44
|
+
pip install pytest pytest-env pytest-cov
|
|
45
|
+
# pytest.ini collects tests/browser and tests/scrape, so the optional
|
|
46
|
+
# extras those exercise have to be present -- and installing them is the
|
|
47
|
+
# only thing that checks the extras are declared correctly at all.
|
|
48
|
+
pip install .[browser,playwright]
|
|
47
49
|
|
|
48
50
|
- name: Run tests
|
|
49
51
|
env:
|
|
50
52
|
PATCH_ANALYTICS: false
|
|
53
|
+
# Coverage is reported, not gated: a threshold now would either be set so
|
|
54
|
+
# low it asserts nothing or would fail the build on unrelated changes.
|
|
55
|
+
# Making the number visible is the point.
|
|
51
56
|
run: |
|
|
52
|
-
pytest
|
|
57
|
+
pytest --cov=patch --cov-report=term-missing
|
|
@@ -32,13 +32,15 @@ jobs:
|
|
|
32
32
|
cache: pip
|
|
33
33
|
cache-dependency-path: |
|
|
34
34
|
requirements.txt
|
|
35
|
-
requirements/requirements-dev.txt
|
|
36
35
|
|
|
37
36
|
- name: Install dependencies
|
|
38
37
|
run: |
|
|
39
38
|
python -m pip install --upgrade pip
|
|
40
|
-
pip install pytest pytest-env
|
|
41
|
-
|
|
39
|
+
pip install pytest pytest-env pytest-cov
|
|
40
|
+
# pytest.ini collects tests/browser and tests/scrape, so the optional
|
|
41
|
+
# extras those exercise have to be present -- and installing them is the
|
|
42
|
+
# only thing that checks the extras are declared correctly at all.
|
|
43
|
+
pip install .[browser,playwright]
|
|
42
44
|
|
|
43
45
|
- name: Run tests
|
|
44
46
|
env:
|
|
@@ -0,0 +1,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
|
+
## Conventions
|
|
131
|
+
|
|
132
|
+
- Match the surrounding style rather than importing a new one. The codebase is
|
|
133
|
+
plain Python with light comments and no type annotations in most modules.
|
|
134
|
+
- Tests are a mix of `unittest.TestCase` classes (about half the files in
|
|
135
|
+
`tests/basic/`) and plain pytest functions. Follow whichever style the file
|
|
136
|
+
you are editing already uses.
|
|
137
|
+
- Commits follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`), as
|
|
138
|
+
seen in recent history.
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
# Full Codebase Audit — Prompt
|
|
2
|
+
|
|
3
|
+
The reusable brief for a full-repository audit of Patch. Three have been run
|
|
4
|
+
([`AUDIT_REPORT.md`](AUDIT_REPORT.md)); this file exists so the fourth starts from what the first
|
|
5
|
+
three learned rather than from a blank page.
|
|
6
|
+
|
|
7
|
+
Read [Before you start](#before-you-start) and [Already disproved](#already-disproved) first. They
|
|
8
|
+
are the difference between a useful round and one that re-derives what is already known.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## The brief
|
|
13
|
+
|
|
14
|
+
You are a senior Python engineer performing a comprehensive audit of this entire codebase.
|
|
15
|
+
|
|
16
|
+
Identify real problems: correctness bugs, architectural weaknesses, maintainability issues, security
|
|
17
|
+
risks, performance problems, and opportunities to delete complexity.
|
|
18
|
+
|
|
19
|
+
**Do not modify the repository during the audit.** Inspect, understand, and report. Remediation is a
|
|
20
|
+
separate pass with its own commits.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Before you start
|
|
25
|
+
|
|
26
|
+
Five rules, each of which came from a specific failure in an earlier round.
|
|
27
|
+
|
|
28
|
+
### 1. Trace callers before reporting anything
|
|
29
|
+
|
|
30
|
+
Round three nearly reported `git_cherry_pick_osr_onto_o` as a thread-safety hazard — it calls
|
|
31
|
+
`os.chdir` process-wide during edit application, with watcher threads live. It is unreachable:
|
|
32
|
+
`udiff_coder.py` builds its own strategy list and never uses the table that references it. The
|
|
33
|
+
finding would have been wrong, and confidently so.
|
|
34
|
+
|
|
35
|
+
Before writing a finding: find the callers, confirm the path is reachable, and check whether a guard
|
|
36
|
+
already exists somewhere you have not looked.
|
|
37
|
+
|
|
38
|
+
### 2. Verify by execution, not by reading
|
|
39
|
+
|
|
40
|
+
Anything you would call Critical or High should be reproduced by running the tree's own code in a
|
|
41
|
+
scratch directory **outside** the repository. Quote the output in the finding.
|
|
42
|
+
|
|
43
|
+
The three top findings of round three each had a probe:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
args.env_file = ./evil.env
|
|
47
|
+
OPENAI_API_BASE = https://attacker.example
|
|
48
|
+
args.test_cmd = touch /tmp/pwned
|
|
49
|
+
after sanitize_repo_config:
|
|
50
|
+
args.test_cmd = touch /tmp/pwned <-- not stripped
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Mark such findings **verified**. Findings you are confident about but did not execute are
|
|
54
|
+
**confirmed by reading** — say which.
|
|
55
|
+
|
|
56
|
+
### 3. Look for the recurring shape
|
|
57
|
+
|
|
58
|
+
Every Critical finding across three audits has been the same thing: **a guard that exists, is right,
|
|
59
|
+
and is missing from one call site.**
|
|
60
|
+
|
|
61
|
+
| Round | Policy | Was missing at |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| 2 | Repository config is untrusted | `.patch.model.settings.yml` |
|
|
64
|
+
| 2 | Redirect vars are denied | the yaml layer's `set-env` |
|
|
65
|
+
| 2 | `--dry-run` performs no side effects | `dirty_commit` |
|
|
66
|
+
| 2 | Writes stay inside the root | read-only paths |
|
|
67
|
+
| 3 | Repository config is untrusted | `env-file` |
|
|
68
|
+
| 3 | Home is distinguishable from the repo | the project's own Docker image |
|
|
69
|
+
| 3 | Writes stay inside the root | `/add` under `--no-auto-commits` |
|
|
70
|
+
| 3 | A failure is not a result | `apply_updates`' `OSError` branch, `summarize_worker` |
|
|
71
|
+
|
|
72
|
+
So: for each policy the code claims to enforce, enumerate *every* place it should apply and check
|
|
73
|
+
each one. That is a more productive search than reading files in order.
|
|
74
|
+
|
|
75
|
+
Several of these now have enforcement — `patch/repo_trust.py` is a chokepoint with a test that
|
|
76
|
+
enumerates the argument parser, and `Coder.write_edited_file` is the single write gate. **Test those
|
|
77
|
+
mechanisms rather than trusting them.** Each was written in response to a finding and has not yet
|
|
78
|
+
survived an audit it did not author.
|
|
79
|
+
|
|
80
|
+
### 4. Distrust green gates
|
|
81
|
+
|
|
82
|
+
Four round-two findings were behaviours the suite actively reported as working. One test passed only
|
|
83
|
+
because it first set the global that hid the bug.
|
|
84
|
+
|
|
85
|
+
Ask what each gate does *not* cover:
|
|
86
|
+
|
|
87
|
+
- `pytest` runs from the repository root, so `import patch` resolves to the working tree. Only
|
|
88
|
+
`packaging.yml` exercises the built artifact.
|
|
89
|
+
- mypy covers 29 of 81 modules. `commands.py` and every coder are outside it.
|
|
90
|
+
- Gate results are per-platform. The fourth round recorded a green run while the
|
|
91
|
+
Windows job was red: `pexpect.spawn` does not exist there, and nothing in a
|
|
92
|
+
Linux-only run says so. Check the CI matrix, not just your own machine.
|
|
93
|
+
- `check_untyped_defs` is on, with three named exceptions (`base_coder.py`, `models.py`, `io.py`).
|
|
94
|
+
- Coverage is reported, not gated.
|
|
95
|
+
|
|
96
|
+
### 5. Record what you disprove
|
|
97
|
+
|
|
98
|
+
Add to [Already disproved](#already-disproved) below. A candidate you investigated and rejected is
|
|
99
|
+
worth as much to the next round as one you confirmed, and costs nothing to write down.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Scope
|
|
104
|
+
|
|
105
|
+
Everything: source, tests, `pyproject.toml`, the four lock files, `docker/Dockerfile`, the four
|
|
106
|
+
GitHub workflows, `.pre-commit-config.yaml`, `scripts/`, `benchmark/`, and the docs.
|
|
107
|
+
|
|
108
|
+
Trace the main execution path rather than reading files in isolation:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
main() → build_config() → RepoTrust layers → setup_model()
|
|
112
|
+
→ Coder.create() → Coder.run() → send_message()
|
|
113
|
+
→ get_edits() → allowed_to_edit() → apply_edits() → write_edited_file()
|
|
114
|
+
→ lint → test → auto_commit
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`AGENTS.md` has the module layout. Determine what the application does, its module boundaries, how
|
|
118
|
+
configuration and secrets are handled, and how it is built, tested, typed, packaged and deployed.
|
|
119
|
+
|
|
120
|
+
### What to look for
|
|
121
|
+
|
|
122
|
+
**Correctness** — logic errors, broken edge cases, swallowed exceptions, mutable default arguments,
|
|
123
|
+
shared mutable state, resource leaks, incorrect context-manager use, races, thread-safety, deadlocks,
|
|
124
|
+
timeout and retry behaviour, datetime/timezone handling, encoding, path handling, platform
|
|
125
|
+
assumptions, `None` handling, generator exhaustion, identity-vs-equality, object lifetime and caching.
|
|
126
|
+
|
|
127
|
+
**Python quality** — functions and classes doing too much, unnecessary abstraction, circular or
|
|
128
|
+
dynamic imports, excessive `Any`, misleading annotations, dataclass and property misuse, fragile
|
|
129
|
+
monkey-patching, incorrect dunders, deep nesting, duplication, dead code, compatibility shims that
|
|
130
|
+
have outlived their Python version.
|
|
131
|
+
|
|
132
|
+
**Architecture** — separation of concerns, coupling, hidden dependencies, leaky abstractions, god
|
|
133
|
+
objects, business logic mixed with transport, configuration mixed with runtime, dependency
|
|
134
|
+
direction, duplicated domain concepts, missing abstractions where duplication is real. Do not
|
|
135
|
+
recommend enterprise-style abstractions without a concrete benefit.
|
|
136
|
+
|
|
137
|
+
**Reliability** — exception boundaries and types, retries, timeouts, cleanup, partial failures,
|
|
138
|
+
transaction boundaries, idempotency, graceful shutdown, startup failures, recovery. Flag anywhere an
|
|
139
|
+
error is logged and execution continues in an invalid state, and anywhere a failure is
|
|
140
|
+
indistinguishable from a result.
|
|
141
|
+
|
|
142
|
+
**Security** — hardcoded secrets, committed credentials, unsafe environment handling, command and
|
|
143
|
+
SQL injection, path traversal, unsafe temp files and archive extraction, SSRF, auth mistakes,
|
|
144
|
+
missing permission checks, cryptographic misuse, unsafe deserialization, `pickle` and `yaml.load`
|
|
145
|
+
with untrusted input, `eval`/`exec`, insecure subprocess use, missing TLS verification, secrets in
|
|
146
|
+
logs, dependency risk. **Distinguish exploitable from theoretical.**
|
|
147
|
+
|
|
148
|
+
**Dependencies and packaging** — unused, duplicate, or heavyweight dependencies, poor pinning,
|
|
149
|
+
version conflicts, misplaced dev dependencies, deprecated APIs, Python-version compatibility,
|
|
150
|
+
packaging mistakes, imports that only work from the repository root. Note where a dependency could
|
|
151
|
+
be replaced by the standard library *if that would materially simplify things*.
|
|
152
|
+
|
|
153
|
+
**Performance** — accidental quadratic behaviour, repeated expensive work, repeated I/O, loading
|
|
154
|
+
whole datasets needlessly, poor data structures, blocking calls in concurrency-sensitive paths,
|
|
155
|
+
unbounded queues, caches and accumulation, excessive logging in hot paths. Measure before claiming;
|
|
156
|
+
do not report micro-optimisations.
|
|
157
|
+
|
|
158
|
+
**Typing** — incorrect or inconsistent annotations, excessive `Any`, wrong optionality, unsafe
|
|
159
|
+
casts, `# type: ignore` hiding defects, poor protocol boundaries, models that permit invalid states.
|
|
160
|
+
Assess whether the gate is *useful*, not merely present.
|
|
161
|
+
|
|
162
|
+
**Tests** — what is actually covered, which behaviour has none, whether failure paths are exercised,
|
|
163
|
+
determinism, order dependence, mocks hiding integration problems, tests asserting implementation
|
|
164
|
+
details rather than behaviour, fixture leakage, isolation of external services. Identify the
|
|
165
|
+
**highest-value missing tests** — ranked by the blast radius of what would break undetected, not by
|
|
166
|
+
coverage percentage.
|
|
167
|
+
|
|
168
|
+
**Observability** — log levels, structure, failure context, secrets in logs, repeated errors,
|
|
169
|
+
failures that cannot be diagnosed from what is emitted.
|
|
170
|
+
|
|
171
|
+
**Configuration** — precedence, defaults, validation, dev-vs-production behaviour, missing or
|
|
172
|
+
malformed handling. Configuration errors should fail early with a useful message.
|
|
173
|
+
|
|
174
|
+
**CI/CD** — tests that do not actually run, missing Python versions, caching, reproducibility,
|
|
175
|
+
deployment despite failed checks, secrets exposure, missing gates, CI-vs-production drift.
|
|
176
|
+
|
|
177
|
+
---
|
|
178
|
+
|
|
179
|
+
## Output
|
|
180
|
+
|
|
181
|
+
### The report
|
|
182
|
+
|
|
183
|
+
Append a new section to `AUDIT_REPORT.md`, matching the existing structure:
|
|
184
|
+
|
|
185
|
+
- `# Nth Audit — commit <sha>`, with the tree state (LOC, test count, gate results)
|
|
186
|
+
- Remediation status tables — severity summary, then per-finding
|
|
187
|
+
- Audit scope and method
|
|
188
|
+
- Executive summary: the biggest risks, the systemic theme if there is one, what to fix first
|
|
189
|
+
- Findings, grouped `CRITICAL` / `HIGH` / `MEDIUM` / `LOW`
|
|
190
|
+
- Prioritised remediation plan: fix immediately / soon / refactor when convenient / optional
|
|
191
|
+
- Highest-value missing tests
|
|
192
|
+
- Positive findings
|
|
193
|
+
- **Disproved during this audit**
|
|
194
|
+
- Ratings
|
|
195
|
+
|
|
196
|
+
Update the table at the top of the file and add a row for the round.
|
|
197
|
+
|
|
198
|
+
### Finding format
|
|
199
|
+
|
|
200
|
+
Continue the `F-N` sequence (three audits have used F-1 – F-97). Each finding:
|
|
201
|
+
|
|
202
|
+
```markdown
|
|
203
|
+
#### F-98 · One-line statement of the defect
|
|
204
|
+
|
|
205
|
+
**Severity:** Critical | High | Medium | Low · **Category:** Security · **Confidence:** verified
|
|
206
|
+
**Location:** `patch/main.py:302-340`, `:787-796`
|
|
207
|
+
|
|
208
|
+
**Problem.** What is wrong.
|
|
209
|
+
|
|
210
|
+
**Evidence.** The code, and the probe output if you ran one.
|
|
211
|
+
|
|
212
|
+
**Impact.** What can happen because of it.
|
|
213
|
+
|
|
214
|
+
**Recommendation.** The smallest sensible fix.
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**Do not report an issue unless you can explain why it matters.** Line numbers go stale — cite the
|
|
218
|
+
commit you audited.
|
|
219
|
+
|
|
220
|
+
### Issues
|
|
221
|
+
|
|
222
|
+
Open one GitHub issue per finding, matching the existing convention (see #80–#111):
|
|
223
|
+
|
|
224
|
+
- Title: `Severity: short description`
|
|
225
|
+
- Body: `**Severity:** X · **Audit ref:** F-N` then `## Problem` / `## Evidence` (or
|
|
226
|
+
`## Reproduction`) / `## Impact` / `## Fix`, plus `## Test` where the missing test is the actual
|
|
227
|
+
root cause
|
|
228
|
+
- Labels: `bug` (or `enhancement`), `security` where applicable, and the severity label
|
|
229
|
+
|
|
230
|
+
### Ratings
|
|
231
|
+
|
|
232
|
+
Rate 1–10, with one sentence of reasoning each: Correctness, Security, Architecture,
|
|
233
|
+
Maintainability, Test quality, Type safety, Performance, Production readiness. Then an overall score.
|
|
234
|
+
|
|
235
|
+
Compare against the previous round's column. **If a dimension did not move, say so and why** — an
|
|
236
|
+
unchanged rating with an honest reason is more useful than a rounded-up one.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Rules
|
|
241
|
+
|
|
242
|
+
- Do not modify the repository during the audit.
|
|
243
|
+
- Do not assume something is broken because it looks unusual.
|
|
244
|
+
- Trace callers and confirm reachability before reporting.
|
|
245
|
+
- Search for existing safeguards before claiming one is missing.
|
|
246
|
+
- Distinguish confirmed bugs from potential risks.
|
|
247
|
+
- Consolidate findings with a common root cause; do not produce dozens of duplicates.
|
|
248
|
+
- Avoid generic style complaints and cosmetic preferences.
|
|
249
|
+
- Prefer deleting complexity over adding abstraction.
|
|
250
|
+
- Do not recommend large rewrites without strong justification.
|
|
251
|
+
- Be skeptical of your own findings and try to disprove them before including them.
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Baseline at `5d6ad03b6`
|
|
256
|
+
|
|
257
|
+
What a clean run looks like today. If any of these has regressed, that is itself a finding.
|
|
258
|
+
|
|
259
|
+
| | |
|
|
260
|
+
| --- | --- |
|
|
261
|
+
| Source | 81 modules, 21,292 lines |
|
|
262
|
+
| Tests | 50 files, 15,209 lines — **674 passed**, 2 skipped on POSIX / 3 on Windows |
|
|
263
|
+
| `flake8` | clean over `patch tests scripts benchmark` |
|
|
264
|
+
| `mypy` | clean over 29 of 81 modules, `check_untyped_defs` on with 3 exceptions |
|
|
265
|
+
| `black` / `isort` / `codespell` | clean |
|
|
266
|
+
| Coverage | 67% overall |
|
|
267
|
+
| Findings | F-1 – F-106 across four rounds, all resolved |
|
|
268
|
+
|
|
269
|
+
Coverage is weakest where it matters most: `report.py` 40%, `linter.py` 43%, `utils.py` 46%,
|
|
270
|
+
`commands.py` 60%. `utils.py` contains `path_is_within`, the containment primitive the entire write
|
|
271
|
+
gate rests on.
|
|
272
|
+
|
|
273
|
+
Run the gates yourself before starting — do not trust this table.
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
pytest -q
|
|
277
|
+
pre-commit run --all-files
|
|
278
|
+
pytest -q --cov=patch --cov-report=term
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Already disproved
|
|
284
|
+
|
|
285
|
+
Investigated in an earlier round and rejected. Re-check if the code has changed, but do not re-derive
|
|
286
|
+
these from scratch.
|
|
287
|
+
|
|
288
|
+
| Candidate | Why it is not a finding |
|
|
289
|
+
| --- | --- |
|
|
290
|
+
| The 120s command timeout | **Was open, now fixed.** It applied to `/run`, `/test` and `--test-cmd` with no way to raise it, and this repository's own suite takes ~150s -- so `patch --test-cmd pytest` here was killed at 120s, and `--auto-test` reported the timeout to the model as a test failure to fix. `--command-timeout SECONDS` now raises it and `0` removes it. Kept here as the shape to look for: a safety limit with no escape hatch. |
|
|
291
|
+
| `Coder.commit_before_message` as shared class state | Declared `list[str] = []` at class level, but rebound in `__init__`, so the class attribute is never mutated. |
|
|
292
|
+
| `git_cherry_pick_*` chdir-ing the process during edit application | `GitTemporaryDirectory` does `os.chdir`, which would be a real race against the watcher threads — but the strategy tables referencing it were unreachable, and are now deleted. |
|
|
293
|
+
| `diff-match-patch` as an unused dependency | Reached only from dead functions at three sites, but live `diff_lines` uses it. |
|
|
294
|
+
| `RepoMap.token_count` dividing by zero | `lines[::step]` always includes `lines[0]`, so the sample is never empty. |
|
|
295
|
+
| `cmd_add`'s "Directory X is not in git" branch as unreachable | Reachable for a plain existing directory whose glob matches nothing. |
|
|
296
|
+
| `scrape_with_httpx` missing a timeout | `httpx.Client` applies its own 5s default. |
|
|
297
|
+
| The `F824` in `onboarding.py` as a live CI failure | The pinned flake8 did not flag it; only a newer one did. Since fixed. |
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Where the previous rounds landed
|
|
302
|
+
|
|
303
|
+
Context for judging whether a theme is recurring or resolved.
|
|
304
|
+
|
|
305
|
+
| Round | Commit | Findings | Overall |
|
|
306
|
+
| --- | --- | --- | --- |
|
|
307
|
+
| First | `425cb623c` | F-1 – F-41 | 8.3 after remediation |
|
|
308
|
+
| Second | `d6146ea7c` | F-42 – F-76 | 5.0 at audit |
|
|
309
|
+
| Third | `95ed59940` | F-77 – F-97 | 6.5 at audit, 8.8 after remediation |
|
|
310
|
+
|
|
311
|
+
The second round scored *lower* than the first's post-remediation figure. That was not a regression:
|
|
312
|
+
it reflected the first round's scope being narrower than its "all resolved" status suggested. Expect
|
|
313
|
+
the same of this file — a fourth round scoring below 8.8 most likely means the third round's scope
|
|
314
|
+
was narrower than it looked, which is the useful thing to find out.
|