patch-chat 0.2.0__tar.gz → 0.4.0__tar.gz

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