patch-chat 0.1.0__tar.gz → 0.3.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.3.0}/.agents/setup +4 -1
- patch_chat-0.3.0/.claude/commands/upstream-issue.md +122 -0
- patch_chat-0.3.0/.github/workflows/packaging.yml +103 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.github/workflows/pre-commit.yml +10 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.github/workflows/ubuntu-tests.yml +9 -4
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.github/workflows/windows-tests.yml +5 -3
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.gitignore +5 -0
- patch_chat-0.3.0/AGENTS.md +200 -0
- patch_chat-0.3.0/AUDIT_PROMPT.md +314 -0
- patch_chat-0.3.0/AUDIT_REPORT.md +3620 -0
- patch_chat-0.3.0/CHANGELOG.md +916 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/CONTRIBUTING.md +289 -226
- {patch_chat-0.1.0/patch_chat.egg-info → patch_chat-0.3.0}/PKG-INFO +54 -22
- {patch_chat-0.1.0 → patch_chat-0.3.0}/README.md +50 -8
- {patch_chat-0.1.0 → patch_chat-0.3.0}/docker/Dockerfile +10 -7
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/__init__.py +20 -20
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/_version.py +3 -3
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/analytics.py +66 -27
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/args.py +15 -5
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/args_formatter.py +226 -228
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/__init__.py +53 -32
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/base_coder.py +348 -223
- patch_chat-0.3.0/patch/coders/chat_state.py +92 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_coder.py +25 -11
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_fenced_coder.py +9 -10
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_func_coder.py +1 -2
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/patch_coder.py +10 -3
- patch_chat-0.3.0/patch/coders/search_replace.py +309 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/single_wholefile_func_coder.py +1 -1
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/udiff_coder.py +31 -8
- patch_chat-0.3.0/patch/coders/usage.py +186 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/wholefile_coder.py +1 -2
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/wholefile_func_coder.py +133 -134
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/commands.py +118 -48
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/copypaste.py +71 -70
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/diffs.py +4 -4
- patch_chat-0.3.0/patch/dump.py +33 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/editor.py +16 -5
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/exceptions.py +43 -12
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/history.py +3 -24
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/io.py +199 -41
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/linter.py +25 -8
- patch_chat-0.3.0/patch/llm.py +184 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/main.py +460 -545
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/mdstream.py +244 -243
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/models.py +44 -10
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/onboarding.py +84 -25
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/reasoning_tags.py +80 -82
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/repo.py +44 -44
- patch_chat-0.3.0/patch/repo_trust.py +607 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/repomap.py +38 -14
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/report.py +65 -4
- patch_chat-0.3.0/patch/run_cmd.py +338 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/scrape.py +332 -316
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/sendchat.py +60 -61
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/utils.py +33 -11
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/versioncheck.py +112 -113
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/voice.py +198 -200
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/waiting.py +2 -1
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/watch.py +6 -41
- {patch_chat-0.1.0 → patch_chat-0.3.0/patch_chat.egg-info}/PKG-INFO +54 -22
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/SOURCES.txt +8 -1
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/requires.txt +4 -16
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/scm_file_list.json +8 -1
- patch_chat-0.3.0/patch_chat.egg-info/scm_version.json +8 -0
- patch_chat-0.3.0/pyproject.toml +133 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/common-constraints.txt +504 -535
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-browser.txt +169 -169
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-dev.in +20 -21
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-dev.txt +359 -398
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-playwright.txt +18 -18
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements.in +47 -53
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/tree-sitter.in +2 -3
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements.txt +464 -477
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/pip-compile.sh +46 -46
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_analytics.py +73 -5
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_aws_credentials.py +120 -169
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_coder.py +1725 -1573
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_commands.py +2447 -2226
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_editblock.py +50 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_editor.py +23 -1
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_history.py +81 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_io.py +277 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_linter.py +47 -3
- patch_chat-0.3.0/tests/basic/test_llm.py +107 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_main.py +75 -2
- patch_chat-0.3.0/tests/basic/test_mdstream.py +65 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_models.py +733 -668
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_onboarding.py +77 -1
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_path_containment.py +450 -286
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_repo.py +737 -716
- patch_chat-0.3.0/tests/basic/test_repo_config_trust.py +730 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_repomap.py +71 -1
- patch_chat-0.3.0/tests/basic/test_run_cmd.py +207 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_udiff.py +241 -167
- patch_chat-0.3.0/tests/basic/test_utils.py +43 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/browser/test_browser.py +36 -36
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/conftest.py +94 -59
- {patch_chat-0.1.0 → patch_chat-0.3.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/llm.py +0 -47
- 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/tests/basic/test_utils.py +0 -22
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.agents/resume +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.dockerignore +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.flake8 +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.github/ISSUE_TEMPLATE/issue.yml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/.pre-commit-config.yaml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/LICENSE.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/MANIFEST.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/Dockerfile +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/benchmark.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/clone-exercism.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/cpp-test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/docker.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/docker_build.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/install-docker-ubuntu.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/npm-test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/plot.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/plots.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/refactor_tools.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/rsync.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/rungrid.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/swe-bench-lite.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/swe-bench.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/swe_bench.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/benchmark/test_benchmark.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/__main__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/architect_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/architect_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/ask_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/ask_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/base_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/chat_chunks.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/context_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/context_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/edit_apply.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_fenced_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editblock_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_diff_fenced_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_diff_fenced_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_editblock_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_editblock_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_whole_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/editor_whole_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/patch_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/shell.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/single_wholefile_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/udiff_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/udiff_simple.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/udiff_simple_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/wholefile_func_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/coders/wholefile_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/deprecated.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/format_settings.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/gui.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/openrouter.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/bash-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/c-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/clojure-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/d-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/go-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/java-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/matlab-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/python-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/r-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/README.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/bash-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/c-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/cpp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/dart-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/elisp-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/elixir-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/elm-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/fortran-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/go-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/haskell-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/hcl-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/java-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/javascript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/julia-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/matlab-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/php-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/python-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/ql-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/ruby-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/rust-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/scala-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/typescript-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/queries/tree-sitter-languages/zig-tags.scm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/resources/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/resources/model-metadata.json +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/resources/model-settings.yml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/special.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/urls.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch/watch_prompts.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/dependency_links.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/entry_points.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/patch_chat.egg-info/top_level.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/pytest.ini +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/pydub.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/python-compat.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-browser.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/requirements/requirements-playwright.in +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/blame.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/clean_metadata.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/issues.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/my_models.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/redact-cast.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/tmux_record.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/tsl_pack_langs.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/scripts/yank-old-versions.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/setup.cfg +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/__init__.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_copypaste.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_deprecated.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_edit_apply.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_exceptions.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_find_or_blocks.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_format_settings.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_model_info_manager.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_openrouter.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_patch_coder.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_reasoning.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_report.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_sanity_check_repo.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_scripting.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_sendchat.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_special.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_ssl_verification.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_urls.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_versioncheck.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_voice.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_waiting.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_watch.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/basic/test_wholefile.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/chat-history-search-replace-gold.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/chat-history.md +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/arduino/test.ino +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/bash/test.sh +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/c/test.c +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/chatito/test.chatito +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/clojure/test.clj +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/commonlisp/test.lisp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/cpp/test.cpp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/csharp/test.cs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/d/test.d +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/dart/test.dart +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/elisp/test.el +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/elixir/test.ex +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/elm/test.elm +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/gleam/test.gleam +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/go/test.go +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/haskell/test.hs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/hcl/test.tf +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/java/test.java +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/javascript/test.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/kotlin/test.kt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/lua/test.lua +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/matlab/test.m +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/ocaml/test.ml +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/ocaml_interface/test.mli +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/php/test.php +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/pony/test.pony +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/properties/test.properties +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/python/test.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/ql/test.ql +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/r/test.r +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/racket/test.rkt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/ruby/test.rb +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/rust/test.rs +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/scala/test.scala +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/solidity/test.sol +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/swift/test.swift +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/tsx/test.tsx +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/typescript/test.ts +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/udev/test.rules +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/languages/zig/test.zig +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/sample-code-base/sample.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/sample-code-base/sample.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/sample-code-base-repo-map.txt +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/watch.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/watch.lisp +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/watch.py +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.0}/tests/fixtures/watch_question.js +0 -0
- {patch_chat-0.1.0 → patch_chat-0.3.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,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Copy an upstream aider issue into this fork, fix it, ship it, and comment upstream
|
|
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. Append an attribution footer:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
_Copied from [Aider-AI/aider#<N>](<url>) (opened by @<author> on <YYYY-MM-DD>)._
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
When your reading in step 2 differs from the reporter's — a different root cause, or the
|
|
45
|
+
conclusion that the real defect is elsewhere — add a short paragraph after the footer saying so.
|
|
46
|
+
That paragraph is your analysis, kept separate from their words.
|
|
47
|
+
|
|
48
|
+
Label it from the repo's existing labels (`gh label list --repo PierrunoYT/patch`): always the
|
|
49
|
+
kind (`bug`, `documentation`, `enhancement`, `security`), always a severity (`critical`, `high`,
|
|
50
|
+
`medium`, `low`), and `good first issue` when the fix is genuinely small and self-contained.
|
|
51
|
+
|
|
52
|
+
## 4. Fix it
|
|
53
|
+
|
|
54
|
+
Follow the repository's own conventions in `AGENTS.md`. In short:
|
|
55
|
+
|
|
56
|
+
- Make the change, and add a regression test that fails without it. Tests live in
|
|
57
|
+
`tests/basic/`, mirroring the module layout.
|
|
58
|
+
- `pytest` — the whole suite, not just the new file.
|
|
59
|
+
- `pre-commit run --all-files` — all five hooks. Black may reformat; re-run until clean.
|
|
60
|
+
|
|
61
|
+
## 5. Update every doc the change touches — in the same pass, not as a follow-up
|
|
62
|
+
|
|
63
|
+
The task is not done when the tests pass. It is done when the docs match. Go through this list
|
|
64
|
+
each time and decide about each entry; the answer is often "nothing to change", but it has to be
|
|
65
|
+
a decision rather than an oversight.
|
|
66
|
+
|
|
67
|
+
- **`CHANGELOG.md`** — always, no exceptions. Under `## [Unreleased]`, in the right subsection
|
|
68
|
+
(`Added`, `Changed`, `Fixed`, `Removed`, `Security`). A docs-only change still gets an entry.
|
|
69
|
+
Blank line between top-level bullets; nested sub-lists stay tight. Describe what changed for
|
|
70
|
+
the reader, not which files you edited. A released `## [X.Y.Z]` section is mirrored in the git
|
|
71
|
+
tag and the GitHub release — never reword or restructure one.
|
|
72
|
+
- **`README.md`** — installation, usage, supported Python or model versions, security boundaries,
|
|
73
|
+
or anything a user reads before running the tool.
|
|
74
|
+
- **`CONTRIBUTING.md`** — setup, testing, dependencies, or the release process.
|
|
75
|
+
- **`AGENTS.md`** — repository layout, tooling, conventions, or a trap worth recording so the
|
|
76
|
+
next agent does not rediscover it. A new module, a renamed one, or a new rule about how the
|
|
77
|
+
code is organised belongs here.
|
|
78
|
+
- **Docstrings and comments next to the code you changed** — if the fix invalidates what a
|
|
79
|
+
nearby comment claims, fix the comment too.
|
|
80
|
+
- **User-facing strings in the code** — `patch/args.py` help text and the messages in
|
|
81
|
+
`patch/main.py`, `patch/commands.py` and `patch/io.py` are documentation the user actually
|
|
82
|
+
reads. A changed flag or behaviour usually means one of them is now wrong.
|
|
83
|
+
- **`AUDIT_REPORT.md` / `AUDIT_PROMPT.md`** — only when the fix lands on a finding those files
|
|
84
|
+
track, or rules out a candidate the prompt lists.
|
|
85
|
+
|
|
86
|
+
Then grep for whatever else still describes the old behaviour
|
|
87
|
+
(`grep -rn "<flag or phrase>" README.md CONTRIBUTING.md AGENTS.md patch/`). A stale doc is the
|
|
88
|
+
same defect as stale code.
|
|
89
|
+
|
|
90
|
+
Doc updates ship in the task's own commit (step 6), never in a later one.
|
|
91
|
+
|
|
92
|
+
## 6. Commit and push
|
|
93
|
+
|
|
94
|
+
One commit for the whole task — code, test and docs together. Conventional Commit subject, a body
|
|
95
|
+
explaining the defect and the fix, and a trailer line:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
Closes #<fork issue>. Reported upstream in Aider-AI/aider#<N>.
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Push to `main`. That closes the fork issue. Confirm it did:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
gh issue list --repo PierrunoYT/patch --state closed --limit 3
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 7. Comment upstream
|
|
108
|
+
|
|
109
|
+
Post it without asking — invoking this command is the authorisation. Write the comment to a file
|
|
110
|
+
and post it with `gh issue comment <N> --repo Aider-AI/aider --body-file <file>`. It is a public
|
|
111
|
+
comment on someone else's repository under the user's account, so write it as carefully as if you
|
|
112
|
+
were going to be asked to defend it: say only what step 2 actually established, and nothing the
|
|
113
|
+
tests do not cover.
|
|
114
|
+
|
|
115
|
+
A good comment is short and factual: confirm or correct the diagnosis, show the actual fix, say
|
|
116
|
+
what the tests cover, and disclose that Patch is a fork of aider. Offer a PR when the fix would
|
|
117
|
+
apply upstream unchanged. No promotion.
|
|
118
|
+
|
|
119
|
+
## Report back
|
|
120
|
+
|
|
121
|
+
Finish with the fork issue number, the commit SHA, the test and hook results, and the upstream
|
|
122
|
+
comment link.
|
|
@@ -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,200 @@
|
|
|
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 with attribution, judge whether the defect is really ours — upstream `aider/foo.py` is
|
|
136
|
+
`patch/foo.py` here, and a broken user environment has no fix in this code — write the fix and a
|
|
137
|
+
regression test, update the docs above, commit with `Closes #N`, and only then comment upstream.
|
|
138
|
+
Editing that file is how the procedure changes; do not keep a second copy of it here.
|
|
139
|
+
|
|
140
|
+
## Releases
|
|
141
|
+
|
|
142
|
+
The full steps are in `CONTRIBUTING.md` under "Making a Release". Read them before cutting one;
|
|
143
|
+
the traps below have each cost a rebuild.
|
|
144
|
+
|
|
145
|
+
- **The version comes from the git tag, nothing else.** `patch/__init__.py`'s `safe_version` and
|
|
146
|
+
`pyproject.toml`'s `fallback_version` are floors, not the version. Bumping them without tagging
|
|
147
|
+
makes every run report `X.Y.Z.dev+less`, because the generated `patch/_version.py` left over
|
|
148
|
+
from the previous build is now below the new floor. Tagging and rebuilding clears it.
|
|
149
|
+
- **Tag with `--cleanup=verbatim`.** `git tag -F` otherwise defaults to `--cleanup=strip` and
|
|
150
|
+
deletes every line beginning with `#`, silently removing the `##` title and all the `###`
|
|
151
|
+
headings from a changelog section used as the tag message. Both `v0.1.0` and `v0.2.0` were
|
|
152
|
+
tagged without it, so their tag messages are flattened; the release bodies are fine, because
|
|
153
|
+
both were published with `--notes-file` from the changelog rather than from the tag.
|
|
154
|
+
- **Reuse the notes file for `gh release create --notes-file`.** Write the changelog section to a
|
|
155
|
+
file in step 2 and pass that same path in step 4. Never spell it as a `<placeholder>`: in
|
|
156
|
+
PowerShell, the default shell here, `<` is a reserved operator and the command fails to parse
|
|
157
|
+
before `gh` runs.
|
|
158
|
+
- **Re-tag only while the tag is local.** If a later commit changes the changelog section, delete
|
|
159
|
+
the tag, re-tag on the new HEAD, and rebuild — the artifacts must come from the tagged commit.
|
|
160
|
+
Once the tag is pushed this is closed off; see the rule in Workflow step 3.
|
|
161
|
+
- **Verify the artifact, not the checkout.** Install the built wheel into a venv outside the
|
|
162
|
+
repository and check `patch --version` plus the bundled data files
|
|
163
|
+
(`resources/model-settings.yml`, `queries/**/*.scm`). From the repository root `tests/__init__.py`
|
|
164
|
+
puts the working tree on `sys.path`, so an in-tree import proves nothing about the wheel.
|
|
165
|
+
|
|
166
|
+
## Conventions
|
|
167
|
+
|
|
168
|
+
- Match the surrounding style rather than importing a new one. The codebase is
|
|
169
|
+
plain Python with light comments and no type annotations in most modules.
|
|
170
|
+
- Tests are a mix of `unittest.TestCase` classes (about half the files in
|
|
171
|
+
`tests/basic/`) and plain pytest functions. Follow whichever style the file
|
|
172
|
+
you are editing already uses.
|
|
173
|
+
- Commits follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`), as
|
|
174
|
+
seen in recent history.
|
|
175
|
+
- Separate every top-level `CHANGELOG.md` bullet with a blank line. CommonMark makes a list
|
|
176
|
+
*loose* -- each item wrapped in `<p>`, with paragraph margins -- as soon as any two of its items
|
|
177
|
+
are separated by a blank line, and *tight* otherwise. One stray blank line therefore respaces a
|
|
178
|
+
whole section, so a file mixing the two renders on GitHub with some sections airy and others
|
|
179
|
+
dense. Entries here are multi-sentence, so loose is the target. Nested sub-lists stay tight.
|
|
180
|
+
- Anything passed to `analytics.event(...)` leaves the machine. `Analytics.event` scrubs every
|
|
181
|
+
property -- URL query strings, absolute paths, length -- so a call site cannot leak by
|
|
182
|
+
forgetting, but the scrubber only removes shapes it knows. Send a class name, a fixed reason or
|
|
183
|
+
a count; never `str(err)`, never free text from a remote server, and route a model name through
|
|
184
|
+
`redact_model_name`. The opt-in prompt in `patch/main.py` is a promise about this.
|
|
185
|
+
- A new `raise SwitchCoder(...)` has to say whether the user's message was already carried out
|
|
186
|
+
before the switch. `/ask PROMPT` answers on a temporary coder and then switches back, so it
|
|
187
|
+
passes `message_handled=True`; `/model` switches instead of doing anything, and leaves the
|
|
188
|
+
default. `run_one_message` in `patch/main.py` uses that to decide whether a one-shot
|
|
189
|
+
`--message` run lost the user's request or completed it.
|
|
190
|
+
- A chat message's `content` is not always a string. An assistant reply that is only a function
|
|
191
|
+
call carries `content=None`, and a message carrying an image carries a list of parts. Read the
|
|
192
|
+
words with `patch.utils.message_content_text(msg)`; concatenating `msg["content"]` raises
|
|
193
|
+
`TypeError` on an ordinary conversation.
|
|
194
|
+
- Write to the terminal through `InputOutput._console_print`, never `self.console.print`
|
|
195
|
+
directly. A terminal write can fail on its own — a legacy Windows console rejects some writes
|
|
196
|
+
with `OSError: [Errno 22]`, and a closed or redirected handle raises too — and most callers are
|
|
197
|
+
reporting an error already, so an escaping `OSError` replaces the message with a traceback and
|
|
198
|
+
ends the session. `_console_print` degrades to ASCII, then to a plain `print`, then to silence.
|
|
199
|
+
The exception is a `Console(file=StringIO())` used to format a string, which never touches a
|
|
200
|
+
terminal.
|