patch-chat 0.3.0__tar.gz → 0.5.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 (328) hide show
  1. {patch_chat-0.3.0 → patch_chat-0.5.0}/.claude/commands/upstream-issue.md +16 -22
  2. patch_chat-0.5.0/.github/dependabot.yml +30 -0
  3. {patch_chat-0.3.0 → patch_chat-0.5.0}/AGENTS.md +18 -5
  4. {patch_chat-0.3.0 → patch_chat-0.5.0}/AUDIT_REPORT.md +17 -0
  5. {patch_chat-0.3.0 → patch_chat-0.5.0}/CHANGELOG.md +167 -1
  6. {patch_chat-0.3.0 → patch_chat-0.5.0}/CONTRIBUTING.md +16 -0
  7. patch_chat-0.5.0/MANIFEST.in +6 -0
  8. {patch_chat-0.3.0/patch_chat.egg-info → patch_chat-0.5.0}/PKG-INFO +28 -14
  9. {patch_chat-0.3.0 → patch_chat-0.5.0}/README.md +15 -1
  10. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/benchmark.py +8 -0
  11. patch_chat-0.5.0/benchmark/test_benchmark.py +104 -0
  12. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/_version.py +3 -3
  13. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/args.py +27 -0
  14. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/base_coder.py +25 -6
  15. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_coder.py +5 -2
  16. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/udiff_coder.py +15 -12
  17. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/usage.py +182 -186
  18. patch_chat-0.5.0/patch/coders/wholefile_coder.py +260 -0
  19. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/commands.py +12 -9
  20. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/main.py +22 -5
  21. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/repo.py +42 -17
  22. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/repo_trust.py +8 -0
  23. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/report.py +28 -0
  24. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/scrape.py +466 -332
  25. patch_chat-0.5.0/patch/urls.py +44 -0
  26. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/utils.py +23 -1
  27. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/watch.py +6 -1
  28. {patch_chat-0.3.0 → patch_chat-0.5.0/patch_chat.egg-info}/PKG-INFO +28 -14
  29. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/SOURCES.txt +2 -0
  30. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/requires.txt +12 -12
  31. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/scm_file_list.json +2 -0
  32. patch_chat-0.5.0/patch_chat.egg-info/scm_version.json +8 -0
  33. {patch_chat-0.3.0 → patch_chat-0.5.0}/pyproject.toml +133 -133
  34. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/common-constraints.txt +14 -9
  35. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-browser.txt +3 -3
  36. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-dev.txt +2 -2
  37. patch_chat-0.5.0/requirements/requirements.in +63 -0
  38. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements.txt +10 -7
  39. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_coder.py +1856 -1725
  40. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_commands.py +2502 -2447
  41. patch_chat-0.5.0/tests/basic/test_dependency_security.py +35 -0
  42. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_editblock.py +18 -0
  43. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_main.py +36 -1
  44. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_repo.py +830 -737
  45. patch_chat-0.5.0/tests/basic/test_report.py +43 -0
  46. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_sanity_check_repo.py +2 -5
  47. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_udiff.py +260 -241
  48. patch_chat-0.5.0/tests/basic/test_urls.py +40 -0
  49. patch_chat-0.5.0/tests/basic/test_utils.py +88 -0
  50. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_watch.py +21 -0
  51. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_wholefile.py +176 -0
  52. patch_chat-0.5.0/tests/browser/test_browser.py +69 -0
  53. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/scrape/test_scrape.py +163 -54
  54. patch_chat-0.3.0/MANIFEST.in +0 -1
  55. patch_chat-0.3.0/benchmark/test_benchmark.py +0 -47
  56. patch_chat-0.3.0/patch/coders/wholefile_coder.py +0 -143
  57. patch_chat-0.3.0/patch/urls.py +0 -17
  58. patch_chat-0.3.0/patch_chat.egg-info/scm_version.json +0 -8
  59. patch_chat-0.3.0/requirements/requirements.in +0 -47
  60. patch_chat-0.3.0/tests/basic/test_report.py +0 -20
  61. patch_chat-0.3.0/tests/basic/test_urls.py +0 -18
  62. patch_chat-0.3.0/tests/basic/test_utils.py +0 -43
  63. patch_chat-0.3.0/tests/browser/test_browser.py +0 -36
  64. {patch_chat-0.3.0 → patch_chat-0.5.0}/.agents/resume +0 -0
  65. {patch_chat-0.3.0 → patch_chat-0.5.0}/.agents/setup +0 -0
  66. {patch_chat-0.3.0 → patch_chat-0.5.0}/.dockerignore +0 -0
  67. {patch_chat-0.3.0 → patch_chat-0.5.0}/.flake8 +0 -0
  68. {patch_chat-0.3.0 → patch_chat-0.5.0}/.github/ISSUE_TEMPLATE/issue.yml +0 -0
  69. {patch_chat-0.3.0 → patch_chat-0.5.0}/.github/workflows/packaging.yml +0 -0
  70. {patch_chat-0.3.0 → patch_chat-0.5.0}/.github/workflows/pre-commit.yml +0 -0
  71. {patch_chat-0.3.0 → patch_chat-0.5.0}/.github/workflows/ubuntu-tests.yml +0 -0
  72. {patch_chat-0.3.0 → patch_chat-0.5.0}/.github/workflows/windows-tests.yml +0 -0
  73. {patch_chat-0.3.0 → patch_chat-0.5.0}/.gitignore +0 -0
  74. {patch_chat-0.3.0 → patch_chat-0.5.0}/.pre-commit-config.yaml +0 -0
  75. {patch_chat-0.3.0 → patch_chat-0.5.0}/AUDIT_PROMPT.md +0 -0
  76. {patch_chat-0.3.0 → patch_chat-0.5.0}/LICENSE.txt +0 -0
  77. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/Dockerfile +0 -0
  78. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/README.md +0 -0
  79. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/__init__.py +0 -0
  80. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/clone-exercism.sh +0 -0
  81. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/cpp-test.sh +0 -0
  82. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/docker.sh +0 -0
  83. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/docker_build.sh +0 -0
  84. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/install-docker-ubuntu.sh +0 -0
  85. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/npm-test.sh +0 -0
  86. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/plot.sh +0 -0
  87. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/plots.py +0 -0
  88. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/prompts.py +0 -0
  89. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/refactor_tools.py +0 -0
  90. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/rsync.sh +0 -0
  91. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/rungrid.py +0 -0
  92. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/swe-bench-lite.txt +0 -0
  93. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/swe-bench.txt +0 -0
  94. {patch_chat-0.3.0 → patch_chat-0.5.0}/benchmark/swe_bench.py +0 -0
  95. {patch_chat-0.3.0 → patch_chat-0.5.0}/docker/Dockerfile +0 -0
  96. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/__init__.py +0 -0
  97. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/__main__.py +0 -0
  98. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/analytics.py +0 -0
  99. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/args_formatter.py +0 -0
  100. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/__init__.py +0 -0
  101. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/architect_coder.py +0 -0
  102. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/architect_prompts.py +0 -0
  103. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/ask_coder.py +0 -0
  104. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/ask_prompts.py +0 -0
  105. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/base_prompts.py +0 -0
  106. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/chat_chunks.py +0 -0
  107. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/chat_state.py +0 -0
  108. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/context_coder.py +0 -0
  109. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/context_prompts.py +0 -0
  110. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/edit_apply.py +0 -0
  111. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_fenced_coder.py +0 -0
  112. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_fenced_prompts.py +0 -0
  113. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_func_coder.py +0 -0
  114. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_func_prompts.py +0 -0
  115. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editblock_prompts.py +0 -0
  116. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_diff_fenced_coder.py +0 -0
  117. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_diff_fenced_prompts.py +0 -0
  118. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_editblock_coder.py +0 -0
  119. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_editblock_prompts.py +0 -0
  120. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_whole_coder.py +0 -0
  121. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/editor_whole_prompts.py +0 -0
  122. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/patch_coder.py +0 -0
  123. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/patch_prompts.py +0 -0
  124. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/search_replace.py +0 -0
  125. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/shell.py +0 -0
  126. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/single_wholefile_func_coder.py +0 -0
  127. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/single_wholefile_func_prompts.py +0 -0
  128. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/udiff_prompts.py +0 -0
  129. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/udiff_simple.py +0 -0
  130. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/udiff_simple_prompts.py +0 -0
  131. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/wholefile_func_coder.py +0 -0
  132. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/wholefile_func_prompts.py +0 -0
  133. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/coders/wholefile_prompts.py +0 -0
  134. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/copypaste.py +0 -0
  135. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/deprecated.py +0 -0
  136. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/diffs.py +0 -0
  137. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/dump.py +0 -0
  138. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/editor.py +0 -0
  139. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/exceptions.py +0 -0
  140. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/format_settings.py +0 -0
  141. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/gui.py +0 -0
  142. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/history.py +0 -0
  143. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/io.py +0 -0
  144. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/linter.py +0 -0
  145. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/llm.py +0 -0
  146. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/mdstream.py +0 -0
  147. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/models.py +0 -0
  148. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/onboarding.py +0 -0
  149. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/openrouter.py +0 -0
  150. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/prompts.py +0 -0
  151. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/README.md +0 -0
  152. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/arduino-tags.scm +0 -0
  153. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/bash-tags.scm +0 -0
  154. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/c-tags.scm +0 -0
  155. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/chatito-tags.scm +0 -0
  156. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/clojure-tags.scm +0 -0
  157. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/commonlisp-tags.scm +0 -0
  158. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/cpp-tags.scm +0 -0
  159. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/csharp-tags.scm +0 -0
  160. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/d-tags.scm +0 -0
  161. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/dart-tags.scm +0 -0
  162. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/elisp-tags.scm +0 -0
  163. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/elixir-tags.scm +0 -0
  164. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/elm-tags.scm +0 -0
  165. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/gleam-tags.scm +0 -0
  166. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/go-tags.scm +0 -0
  167. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/java-tags.scm +0 -0
  168. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/javascript-tags.scm +0 -0
  169. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/lua-tags.scm +0 -0
  170. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/matlab-tags.scm +0 -0
  171. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/ocaml-tags.scm +0 -0
  172. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +0 -0
  173. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/pony-tags.scm +0 -0
  174. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/properties-tags.scm +0 -0
  175. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/python-tags.scm +0 -0
  176. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/r-tags.scm +0 -0
  177. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/racket-tags.scm +0 -0
  178. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/ruby-tags.scm +0 -0
  179. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/rust-tags.scm +0 -0
  180. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/solidity-tags.scm +0 -0
  181. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/swift-tags.scm +0 -0
  182. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-language-pack/udev-tags.scm +0 -0
  183. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/README.md +0 -0
  184. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/bash-tags.scm +0 -0
  185. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/c-tags.scm +0 -0
  186. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/c_sharp-tags.scm +0 -0
  187. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/cpp-tags.scm +0 -0
  188. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/dart-tags.scm +0 -0
  189. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/elisp-tags.scm +0 -0
  190. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/elixir-tags.scm +0 -0
  191. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/elm-tags.scm +0 -0
  192. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/fortran-tags.scm +0 -0
  193. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/go-tags.scm +0 -0
  194. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/haskell-tags.scm +0 -0
  195. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/hcl-tags.scm +0 -0
  196. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/java-tags.scm +0 -0
  197. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/javascript-tags.scm +0 -0
  198. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/julia-tags.scm +0 -0
  199. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/kotlin-tags.scm +0 -0
  200. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/matlab-tags.scm +0 -0
  201. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/ocaml-tags.scm +0 -0
  202. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/ocaml_interface-tags.scm +0 -0
  203. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/php-tags.scm +0 -0
  204. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/python-tags.scm +0 -0
  205. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/ql-tags.scm +0 -0
  206. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/ruby-tags.scm +0 -0
  207. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/rust-tags.scm +0 -0
  208. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/scala-tags.scm +0 -0
  209. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/typescript-tags.scm +0 -0
  210. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/queries/tree-sitter-languages/zig-tags.scm +0 -0
  211. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/reasoning_tags.py +0 -0
  212. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/repomap.py +0 -0
  213. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/resources/__init__.py +0 -0
  214. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/resources/model-metadata.json +0 -0
  215. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/resources/model-settings.yml +0 -0
  216. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/run_cmd.py +0 -0
  217. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/sendchat.py +0 -0
  218. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/special.py +0 -0
  219. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/versioncheck.py +0 -0
  220. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/voice.py +0 -0
  221. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/waiting.py +0 -0
  222. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch/watch_prompts.py +0 -0
  223. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/dependency_links.txt +0 -0
  224. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/entry_points.txt +0 -0
  225. {patch_chat-0.3.0 → patch_chat-0.5.0}/patch_chat.egg-info/top_level.txt +0 -0
  226. {patch_chat-0.3.0 → patch_chat-0.5.0}/pytest.ini +0 -0
  227. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/pydub.in +0 -0
  228. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/python-compat.in +0 -0
  229. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-browser.in +0 -0
  230. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-dev.in +0 -0
  231. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-playwright.in +0 -0
  232. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/requirements-playwright.txt +0 -0
  233. {patch_chat-0.3.0 → patch_chat-0.5.0}/requirements/tree-sitter.in +0 -0
  234. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/__init__.py +0 -0
  235. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/blame.py +0 -0
  236. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/clean_metadata.py +0 -0
  237. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/issues.py +0 -0
  238. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/my_models.py +0 -0
  239. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/pip-compile.sh +0 -0
  240. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/redact-cast.py +0 -0
  241. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/tmux_record.sh +0 -0
  242. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/tsl_pack_langs.py +0 -0
  243. {patch_chat-0.3.0 → patch_chat-0.5.0}/scripts/yank-old-versions.py +0 -0
  244. {patch_chat-0.3.0 → patch_chat-0.5.0}/setup.cfg +0 -0
  245. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/__init__.py +0 -0
  246. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/__init__.py +0 -0
  247. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_analytics.py +0 -0
  248. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_aws_credentials.py +0 -0
  249. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_copypaste.py +0 -0
  250. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_deprecated.py +0 -0
  251. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_edit_apply.py +0 -0
  252. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_editor.py +0 -0
  253. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_exceptions.py +0 -0
  254. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_find_or_blocks.py +0 -0
  255. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_format_settings.py +0 -0
  256. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_history.py +0 -0
  257. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_io.py +0 -0
  258. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_linter.py +0 -0
  259. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_llm.py +0 -0
  260. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_mdstream.py +0 -0
  261. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_model_info_manager.py +0 -0
  262. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_models.py +0 -0
  263. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_onboarding.py +0 -0
  264. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_openrouter.py +0 -0
  265. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_patch_coder.py +0 -0
  266. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_path_containment.py +0 -0
  267. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_reasoning.py +0 -0
  268. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_repo_config_trust.py +0 -0
  269. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_repomap.py +0 -0
  270. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_run_cmd.py +0 -0
  271. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_scripting.py +0 -0
  272. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_sendchat.py +0 -0
  273. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_special.py +0 -0
  274. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_ssl_verification.py +0 -0
  275. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_versioncheck.py +0 -0
  276. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_voice.py +0 -0
  277. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/basic/test_waiting.py +0 -0
  278. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/conftest.py +0 -0
  279. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/chat-history-search-replace-gold.txt +0 -0
  280. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/chat-history.md +0 -0
  281. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/arduino/test.ino +0 -0
  282. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/bash/test.sh +0 -0
  283. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/c/test.c +0 -0
  284. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/chatito/test.chatito +0 -0
  285. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/clojure/test.clj +0 -0
  286. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/commonlisp/test.lisp +0 -0
  287. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/cpp/test.cpp +0 -0
  288. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/csharp/test.cs +0 -0
  289. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/d/test.d +0 -0
  290. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/dart/test.dart +0 -0
  291. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/elisp/test.el +0 -0
  292. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/elixir/test.ex +0 -0
  293. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/elm/test.elm +0 -0
  294. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/gleam/test.gleam +0 -0
  295. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/go/test.go +0 -0
  296. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/haskell/test.hs +0 -0
  297. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/hcl/test.tf +0 -0
  298. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/java/test.java +0 -0
  299. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/javascript/test.js +0 -0
  300. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/kotlin/test.kt +0 -0
  301. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/lua/test.lua +0 -0
  302. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/matlab/test.m +0 -0
  303. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/ocaml/test.ml +0 -0
  304. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/ocaml_interface/test.mli +0 -0
  305. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/php/test.php +0 -0
  306. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/pony/test.pony +0 -0
  307. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/properties/test.properties +0 -0
  308. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/python/test.py +0 -0
  309. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/ql/test.ql +0 -0
  310. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/r/test.r +0 -0
  311. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/racket/test.rkt +0 -0
  312. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/ruby/test.rb +0 -0
  313. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/rust/test.rs +0 -0
  314. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/scala/test.scala +0 -0
  315. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/solidity/test.sol +0 -0
  316. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/swift/test.swift +0 -0
  317. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/tsx/test.tsx +0 -0
  318. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/typescript/test.ts +0 -0
  319. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/udev/test.rules +0 -0
  320. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/languages/zig/test.zig +0 -0
  321. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/sample-code-base/sample.js +0 -0
  322. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/sample-code-base/sample.py +0 -0
  323. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/sample-code-base-repo-map.txt +0 -0
  324. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/watch.js +0 -0
  325. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/watch.lisp +0 -0
  326. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/watch.py +0 -0
  327. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/fixtures/watch_question.js +0 -0
  328. {patch_chat-0.3.0 → patch_chat-0.5.0}/tests/scrape/test_playwright_disable.py +0 -0
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Copy an upstream aider issue into this fork, fix it, ship it, and comment upstream
2
+ description: Copy an upstream aider issue into this fork, fix it and ship it
3
3
  argument-hint: <upstream issue URL or number>
4
4
  allowed-tools: Bash(gh:*), Bash(git:*), Bash(python:*), Bash(pytest:*), Bash(pre-commit:*), Read, Edit, Write, Grep, Glob
5
5
  ---
@@ -33,17 +33,12 @@ If nothing here is worth changing, stop after step 3 and say why rather than clo
33
33
  ## 3. Copy it into the fork
34
34
 
35
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:
36
+ this fork calls differently, and the body verbatim. Do not add source links, reporter attribution,
37
+ or `@` mentions.
37
38
 
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.
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.
47
42
 
48
43
  Label it from the repo's existing labels (`gh label list --repo PierrunoYT/patch`): always the
49
44
  kind (`bug`, `documentation`, `enhancement`, `security`), always a severity (`critical`, `high`,
@@ -104,19 +99,18 @@ Push to `main`. That closes the fork issue. Confirm it did:
104
99
  gh issue list --repo PierrunoYT/patch --state closed --limit 3
105
100
  ```
106
101
 
107
- ## 7. Comment upstream
102
+ ## 7. Nothing goes upstream
108
103
 
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.
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.
114
108
 
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.
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.
118
113
 
119
114
  ## Report back
120
115
 
121
- Finish with the fork issue number, the commit SHA, the test and hook results, and the upstream
122
- comment link.
116
+ Finish with the fork issue number, the commit SHA, and the test and hook results.
@@ -0,0 +1,30 @@
1
+ version: 2
2
+
3
+ # Nothing was watching the pins, which is how five months of advisories
4
+ # accumulated in requirements.txt unnoticed. See issue #1472.
5
+ #
6
+ # requirements.txt and requirements/*.txt are generated by
7
+ # ./scripts/pip-compile.sh from the matching .in files, so a Dependabot PR that
8
+ # edits a .txt is a signal, not a patch to merge: raise the floor in the .in
9
+ # file, re-run the script, and close the PR. AGENTS.md records the same rule.
10
+ updates:
11
+ - package-ecosystem: pip
12
+ directory: /
13
+ schedule:
14
+ interval: weekly
15
+ open-pull-requests-limit: 10
16
+ labels:
17
+ - security
18
+ groups:
19
+ # One PR per batch rather than ten: these are lockfiles, and they are
20
+ # regenerated as a set anyway.
21
+ python-dependencies:
22
+ patterns:
23
+ - "*"
24
+
25
+ - package-ecosystem: github-actions
26
+ directory: /
27
+ schedule:
28
+ interval: weekly
29
+ labels:
30
+ - security
@@ -85,7 +85,13 @@ Two root-level documents cover the audit history:
85
85
  - `patch/_version.py` — generated by setuptools_scm, gitignored.
86
86
  - `requirements/*.txt` — compiled from the matching `.in` files by
87
87
  `./scripts/pip-compile.sh`. Edit the `.in` file and re-run the script; never
88
- hand-edit the `.txt`.
88
+ hand-edit the `.txt`. `requirements.txt` is also the distribution's install set
89
+ (`pyproject.toml` reads `dependencies` from it), so a pin here is what every
90
+ `pip install patch-chat` resolves to — a stale one ships to users, not just to
91
+ contributors. Security floors go in the `.in` file as `package>=fixed.version`,
92
+ next to a comment saying which advisory forced it. `.github/dependabot.yml`
93
+ watches these weekly; its PRs edit the generated `.txt` and are a signal to act
94
+ on, never a patch to merge.
89
95
 
90
96
  ## CI
91
97
 
@@ -132,10 +138,17 @@ code works — it is done when the docs match and the work is committed.
132
138
  Patch is a fork of [aider](https://github.com/Aider-AI/aider), and reports filed there often
133
139
  apply here. `.claude/commands/upstream-issue.md` is a Claude Code slash command
134
140
  (`/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.
141
+ tracker without source or reporter attribution, judge whether the defect is really ours — upstream
142
+ `aider/foo.py` is `patch/foo.py` here, and a broken user environment has no fix in this code —
143
+ write the fix and a regression test, update the docs above, and commit with `Closes #N`. Editing
144
+ that file is how the procedure changes; do not keep a second copy of it here.
145
+
146
+ The upstream half of that loop is closed. On 2026-08-31 an aider maintainer minimised twelve
147
+ comments from this account as `SPAM` and blocked it from the repository: `gh issue comment` there
148
+ returns `GraphQL: User is blocked (addComment)`, and reactions are refused too. Reading still
149
+ works, so copying issues over and fixing them is unaffected — the command now ends at the commit,
150
+ sends nothing upstream, and omits source and reporter references from copied issues. Do not try to
151
+ post from elsewhere.
139
152
 
140
153
  ## Releases
141
154
 
@@ -3618,3 +3618,20 @@ test the safety of each policy decision, not only the presence of one.
3618
3618
  The 9.0 post-remediation score reflects all nine findings closed with focused tests and the full
3619
3619
  gate green. It remains below 10 because the fourth audit's structural constraints are unchanged:
3620
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 |
@@ -7,6 +7,170 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.5.0] - 2026-09-01
11
+
12
+ ### Added
13
+
14
+ - `--no-detect-file-mentions` stops Patch offering to add files the model names in its reply, for
15
+ sessions where the context should stay exactly what you added yourself. The prompt is otherwise
16
+ unchanged, and `--detect-file-mentions` is still the default.
17
+
18
+ ### Fixed
19
+
20
+ - A reply that both edits files and asks for more files no longer loses the edits. Adding the
21
+ mentioned files returned before the edits were applied, so the edits in that reply were dropped
22
+ while the model was told its files had arrived -- it then carried on believing the edit had
23
+ landed, and its next edit failed to match a file that had never changed. The edits are applied
24
+ and committed first, and the request for more files is reflected back afterwards. An edit error
25
+ and a file request arriving together are now both reported, rather than only the file request.
26
+
27
+ - A whole-file listing of a markdown file no longer stops at the first fenced block inside it.
28
+ Any ```` ``` ```` line ended the listing, so a file containing a code block was truncated there
29
+ and everything after it was written to a second file named after whichever line preceded the
30
+ next fence. A fence carrying a language ("```json") is now read as opening a block within the
31
+ listing, and the listing ends at the fence that closes it. A ```` ```diff ```` block inside a
32
+ listing is likewise content, not a mis-selected edit format. An inner block opened with a bare
33
+ ```` ``` ```` and no language remains ambiguous and still ends the listing.
34
+
35
+ - A debug dump of the chat transcript no longer ends the session when the transcript holds text
36
+ the console cannot encode. Content reaches the transcript from files read with
37
+ `surrogateescape` and from model replies, so a lone surrogate can appear in it; printing one
38
+ raised an uncaught `UnicodeEncodeError` from inside `--verbose` output. Unprintable characters
39
+ are now replaced, and the dump is shown.
40
+
41
+ - `/commit` now respects `--subtree-only`. It committed through `git commit -a`, which stages
42
+ every dirty file in the repository regardless of the subtree the session was scoped to, so
43
+ unrelated work elsewhere in the tree was swept into the commit without appearing anywhere the
44
+ user could see it. The commit is now restricted to dirty files inside the subtree, and does
45
+ nothing at all when the only changes are outside it.
46
+
47
+ ### Security
48
+
49
+ - Web scraping no longer fetches private, loopback or link-local addresses. A URL that resolves
50
+ into one of those ranges is refused before the request is made, which closes the path from a
51
+ repository README naming `http://169.254.169.254/latest/meta-data/iam/security-credentials/` to
52
+ Patch fetching the cloud metadata service it happens to be running next to and putting IAM
53
+ credentials in the chat. The check runs after DNS resolution, so a hostname pointing at a private
54
+ address is refused too, and it runs again on every redirect hop, so a public URL cannot bounce
55
+ the scraper somewhere private. Under Playwright the same rule applies to what the page itself
56
+ loads, not only to the address in the URL bar. `--allow-private-urls` scrapes a local dev server
57
+ deliberately; a repository config cannot set it, since the repository is also what supplies the
58
+ URLs.
59
+
60
+ - The browser UI now listens on `127.0.0.1` instead of every interface. `--browser` handed
61
+ Streamlit no address, and its default is to accept connections from anywhere, so running the UI
62
+ on a shared network put an unauthenticated page that can edit the repository and spend the user's
63
+ API credits in reach of everyone on it. `--gui-address ADDR` binds somewhere else on purpose and
64
+ warns when that address is not loopback; a repository config cannot set it.
65
+
66
+ - litellm is now constrained to 1.84.0 or later, carrying the fixes for an authentication bypass
67
+ via Host header injection (CVE-2026-49468) along with CVE-2026-42208 and CVE-2026-35030. This is
68
+ the library every provider request passes through, so it is the code holding the user's API keys.
69
+ The pin is held below 1.85 deliberately: resolving the floor open-ended lands on 1.99, which adds
70
+ the AWS SDK to every install and downgrades `importlib-metadata`, and that is a change to make
71
+ and validate on its own terms rather than inside a security patch.
72
+
73
+ - soupsieve is now constrained to 2.8.4 or later.
74
+
75
+ - Dependency pins are now watched weekly by Dependabot, for both Python packages and GitHub
76
+ Actions. Nothing had been watching them, which is how a lockfile that is also the published
77
+ install set accumulated advisories unnoticed. `CONTRIBUTING.md` and `AGENTS.md` describe how to
78
+ act on what it reports, since the files it edits are generated.
79
+
80
+ ## [0.4.0] - 2026-09-01
81
+
82
+ ### Changed
83
+
84
+ - The `/upstream-issue` command no longer sends anything to aider or adds source and reporter
85
+ references to copied issues. This account was blocked from commenting on that repository on
86
+ 2026-08-31, after twelve comments in an afternoon were minimised as spam, so the command now
87
+ keeps the workflow entirely inside this fork and ends at the commit. Reading upstream reports,
88
+ copying applicable defects, and fixing them remain unaffected.
89
+
90
+ - `/report` now prefills the questions a report has to answer -- what happened, what was expected
91
+ instead, and how to reproduce it -- above the session details. The command previously sent only
92
+ the announcements, which describe how the session was configured and nothing about the problem,
93
+ so the prefilled form was routinely submitted as an issue that said nothing at all. Text passed
94
+ to the command now answers the first question as well as titling the issue, where before it was
95
+ the title alone. `CONTRIBUTING.md` describes what to fill in.
96
+
97
+ ### Removed
98
+
99
+ - The stale generated dump of upstream aider issues is no longer stored in the repository.
100
+
101
+ ### Fixed
102
+
103
+ - Git repositories now use GitPython's default command-backed object database instead of forcing
104
+ `GitDB`, which could report `BadObject` for objects that Git itself reads successfully and prevent
105
+ Patch from opening a valid repository.
106
+
107
+ - The Polyglot benchmark now gives models the files listed by Exercism under `files.editor` as
108
+ read-only context. Solution files remain editable, while tests and example implementations remain
109
+ hidden, so pass@1 no longer depends on guessing interfaces supplied by the exercise.
110
+
111
+ - Cached input tokens are no longer charged twice in Patch's displayed cost. Cache writes and reads
112
+ use provider metadata when available, only the uncached remainder uses the ordinary input rate,
113
+ and inconsistent provider counts can no longer produce a negative uncached charge.
114
+
115
+ - `/tokens` now measures editable and read-only text files with a real closing code fence instead of
116
+ counting the literal text `{fence}`.
117
+
118
+ - Unified-diff parsing now strips standard Git `a/` and `b/` prefixes from every file in a fenced
119
+ multi-file diff, rather than only from the first file.
120
+
121
+ - Whole-file mode now reports and reflects recognizable unified-diff output instead of silently
122
+ discarding a bare diff or misreading a fenced diff as a new whole-file listing. Recognition
123
+ follows active listing fences, so an earlier completed example block cannot hide a later diff
124
+ and be applied as an edit. A `diff`- or `patch`-tagged fence counts on its own, without the
125
+ `---` and `+++` headers a short hunk often omits: such a block was being read as a listing and
126
+ written to a file named after the sentence above it, so a reply opening "Here is the change:"
127
+ left a file called `Here is the change` in the repository. The line above a fence still names a
128
+ file when it looks like one, which is how a listing of a `.diff` or `.patch` file is written.
129
+ This can happen when an unlisted model ignores the automatically selected edit format; the model
130
+ now gets a precise instruction to retry with the entire updated file.
131
+
132
+ - A fatal model-provider error in `--message` and `--message-file` mode now returns a nonzero exit
133
+ status after retries are exhausted. Headless callers previously received status 0 even though no
134
+ response was produced, making a failed API request indistinguishable from a successful no-op.
135
+
136
+ - A commit-message model that answers with nothing but whitespace no longer stops the fallback.
137
+ The reply was judged before being trimmed, and a string of spaces is not empty as far as an
138
+ `if` is concerned -- so the first model ended the search without producing anything, and the
139
+ next one configured was never asked. The same untrimmed test guarded the "Failed to generate
140
+ commit message!" report, which therefore did not appear either: the commit was made as "(no
141
+ commit message provided)" with nothing said at the time. Each reply is now trimmed as it
142
+ arrives, so the fallback and the failure report both see what the model actually sent.
143
+
144
+ - Search/replace blocks whose fences are indented no longer lose their filename. The search back
145
+ through the preceding lines tested the raw line for a fence while the filename check stripped
146
+ the line first, so the two disagreed about what a fence was and the search stopped one line
147
+ short: a model that indented "```python" produced a valid edit that was rejected for naming no
148
+ file. The docstring's own indented example now parses.
149
+
150
+ - A `.gitignore` containing non-ASCII characters no longer crashes `--watch-files` at startup. The
151
+ file was decoded with the system's locale encoding rather than the UTF-8 Git itself uses, so on
152
+ Windows a single accented path in the ignore file ended the session with an uncaught
153
+ `UnicodeDecodeError` before the first prompt. Bytes that are not valid UTF-8 are now replaced,
154
+ and the remaining patterns still apply.
155
+
156
+ - The "what's new in this version" offer shown on the first run after an upgrade now opens that
157
+ version's release page rather than `CHANGELOG.md` on `main`. The link was always the newest file,
158
+ so it showed entries still sitting under `Unreleased`, and once a later version was cut it buried
159
+ the section it was meant to show under the newer one. `--show-release-notes` follows the same
160
+ link. A development build has no tag behind it and so still opens the changelog.
161
+
162
+ ### Security
163
+
164
+ - urllib3 is now constrained to 2.7.0 or later, preventing low-level proxied cross-origin redirects
165
+ from forwarding sensitive authorization and cookie headers under CVE-2026-44431.
166
+
167
+ - Pillow is now constrained to 12.2.0 or later so a malicious PSD cannot trigger the memory
168
+ corruption and potential arbitrary code execution identified as CVE-2026-42311.
169
+
170
+ - GitPython is now constrained to 3.1.49 or later, closing four High-severity vulnerabilities in
171
+ the previous 3.1.46 lock: configuration injection that could select an attacker-controlled Git
172
+ hooks directory, unsafe clone options, and incomplete hardening of those paths.
173
+
10
174
  ## [0.3.0] - 2026-08-31
11
175
 
12
176
  ### Added
@@ -910,7 +1074,9 @@ than continuing the upstream `0.86.x` numbering.
910
1074
  `.env`, including `OPENAI_API_KEY` and `PATCH_MODEL`, still load normally; and anything passed on
911
1075
  the command line always wins.
912
1076
 
913
- [Unreleased]: https://github.com/PierrunoYT/patch/compare/v0.3.0...main
1077
+ [Unreleased]: https://github.com/PierrunoYT/patch/compare/v0.5.0...main
1078
+ [0.5.0]: https://github.com/PierrunoYT/patch/compare/v0.4.0...v0.5.0
1079
+ [0.4.0]: https://github.com/PierrunoYT/patch/compare/v0.3.0...v0.4.0
914
1080
  [0.3.0]: https://github.com/PierrunoYT/patch/compare/v0.2.0...v0.3.0
915
1081
  [0.2.0]: https://github.com/PierrunoYT/patch/compare/v0.1.0...v0.2.0
916
1082
  [0.1.0]: https://github.com/PierrunoYT/patch/releases/tag/v0.1.0
@@ -11,6 +11,12 @@ Please submit bug reports and feature requests as GitHub issues. This
11
11
  helps us to keep track of them and discuss potential solutions or
12
12
  enhancements.
13
13
 
14
+ From inside a session, `/report` opens a prefilled issue form in your browser:
15
+ the version and model settings of that session, plus headings for what
16
+ happened, what you expected instead, and how to reproduce it. Please answer
17
+ those three — the settings say how Patch was configured, never what went
18
+ wrong. `/report <summary>` titles the issue and answers the first one.
19
+
14
20
  ## LLM Benchmark Results
15
21
 
16
22
  Contributions of
@@ -274,6 +280,16 @@ Any arguments you pass to `pip-compile.sh` flow through to `uv pip compile`. For
274
280
  Note that a plain re-run keeps the existing pins: `uv` treats the current lock as a preference, so
275
281
  moving a dependency needs one of the `--upgrade` flags above.
276
282
 
283
+ **Security updates.** `requirements.txt` is the distribution's install set — `pyproject.toml` reads
284
+ `dependencies` from it — so a vulnerable pin is what everyone who runs `pip install patch-chat`
285
+ receives. Raise the floor in the `.in` file (`package>=fixed.version`) with a comment naming the
286
+ advisory, then re-run the script. Prefer the narrowest range that carries the fix: resolving an
287
+ open-ended floor can jump many minor versions at once and bring new transitive dependencies with
288
+ it, which is a change to review on its own terms rather than inside a security patch.
289
+ `.github/dependabot.yml` watches the pins weekly, and its pull requests edit the generated `.txt`
290
+ files — treat them as notification that a floor needs raising, and close them in favour of a
291
+ regenerated lock.
292
+
277
293
  ### Pre-commit Hooks
278
294
 
279
295
  The project uses [pre-commit](https://pre-commit.com/) hooks to automatically format code, lint, and run other checks before committing changes. After cloning the repository, run the following command to set up the pre-commit hooks:
@@ -0,0 +1,6 @@
1
+ global-exclude .DS_Store
2
+
3
+ # Working data, not part of the distribution. setuptools-scm's git file finder
4
+ # puts every tracked root file into the sdist, so without this the 2.7 MB
5
+ # snapshot of aider's issue tracker would ship inside patch-chat.
6
+ exclude aider-issues.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patch-chat
3
- Version: 0.3.0
3
+ Version: 0.5.0
4
4
  Summary: Patch is AI pair programming in your terminal
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Homepage, https://github.com/PierrunoYT/patch
@@ -19,7 +19,7 @@ Requires-Python: <3.15,>=3.10
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE.txt
21
21
  Requires-Dist: aiohappyeyeballs==2.6.1
22
- Requires-Dist: aiohttp==3.13.3
22
+ Requires-Dist: aiohttp==3.14.3
23
23
  Requires-Dist: aiosignal==1.4.0
24
24
  Requires-Dist: annotated-doc==0.0.4
25
25
  Requires-Dist: annotated-types==0.7.0
@@ -45,7 +45,7 @@ Requires-Dist: filelock==3.25.2
45
45
  Requires-Dist: frozenlist==1.8.0
46
46
  Requires-Dist: fsspec==2026.2.0
47
47
  Requires-Dist: gitdb==4.0.12
48
- Requires-Dist: gitpython==3.1.46
48
+ Requires-Dist: gitpython==3.1.61
49
49
  Requires-Dist: grep-ast==0.9.0
50
50
  Requires-Dist: h11==0.16.0
51
51
  Requires-Dist: hf-xet==1.4.2; platform_machine == "AMD64" or platform_machine == "aarch64" or platform_machine == "amd64" or platform_machine == "arm64" or platform_machine == "x86_64"
@@ -53,14 +53,14 @@ Requires-Dist: httpcore==1.0.9
53
53
  Requires-Dist: httpx==0.28.1
54
54
  Requires-Dist: huggingface-hub==1.7.1
55
55
  Requires-Dist: idna==3.11
56
- Requires-Dist: importlib-metadata==9.0.1
56
+ Requires-Dist: importlib-metadata==8.9.0
57
57
  Requires-Dist: importlib-resources==6.5.2
58
58
  Requires-Dist: jinja2==3.1.6
59
59
  Requires-Dist: jiter==0.13.0
60
60
  Requires-Dist: json5==0.13.0
61
61
  Requires-Dist: jsonschema==4.26.0
62
62
  Requires-Dist: jsonschema-specifications==2025.9.1
63
- Requires-Dist: litellm==1.82.3
63
+ Requires-Dist: litellm==1.84.10
64
64
  Requires-Dist: markdown-it-py==4.0.0
65
65
  Requires-Dist: markupsafe==3.0.3
66
66
  Requires-Dist: mdurl==0.1.2
@@ -74,7 +74,7 @@ Requires-Dist: oslex==0.1.3
74
74
  Requires-Dist: packaging==26.0
75
75
  Requires-Dist: pathspec==1.0.4
76
76
  Requires-Dist: pexpect==4.9.0
77
- Requires-Dist: pillow==12.1.1
77
+ Requires-Dist: pillow==12.3.0
78
78
  Requires-Dist: posthog==7.9.12
79
79
  Requires-Dist: prompt-toolkit==3.0.52
80
80
  Requires-Dist: propcache==0.4.1
@@ -104,7 +104,7 @@ Requires-Dist: smmap==5.0.3
104
104
  Requires-Dist: sniffio==1.3.1
105
105
  Requires-Dist: sounddevice==0.5.5
106
106
  Requires-Dist: soundfile==0.13.1
107
- Requires-Dist: soupsieve==2.8.3
107
+ Requires-Dist: soupsieve==2.9.2
108
108
  Requires-Dist: tiktoken==0.12.0
109
109
  Requires-Dist: tokenizers==0.22.2
110
110
  Requires-Dist: tqdm==4.67.3
@@ -116,7 +116,7 @@ Requires-Dist: tree-sitter-yaml==0.7.2
116
116
  Requires-Dist: typer==0.24.1
117
117
  Requires-Dist: typing-extensions==4.15.0
118
118
  Requires-Dist: typing-inspection==0.4.2
119
- Requires-Dist: urllib3==2.6.3
119
+ Requires-Dist: urllib3==2.7.0
120
120
  Requires-Dist: watchfiles==1.1.1
121
121
  Requires-Dist: wcwidth==0.6.0
122
122
  Requires-Dist: yarl==1.23.0
@@ -170,7 +170,7 @@ Requires-Dist: numpy==2.4.3; python_full_version >= "3.11" and extra == "dev"
170
170
  Requires-Dist: packaging==26.0; extra == "dev"
171
171
  Requires-Dist: pandas==2.3.3; extra == "dev"
172
172
  Requires-Dist: pathspec==1.0.4; extra == "dev"
173
- Requires-Dist: pillow==12.1.1; extra == "dev"
173
+ Requires-Dist: pillow==12.3.0; extra == "dev"
174
174
  Requires-Dist: platformdirs==4.9.4; extra == "dev"
175
175
  Requires-Dist: pluggy==1.6.0; extra == "dev"
176
176
  Requires-Dist: pre-commit==4.5.1; extra == "dev"
@@ -200,7 +200,7 @@ Requires-Dist: tomli==2.4.1; python_full_version <= "3.11" and extra == "dev"
200
200
  Requires-Dist: typer==0.24.1; extra == "dev"
201
201
  Requires-Dist: typing-extensions==4.15.0; extra == "dev"
202
202
  Requires-Dist: tzdata==2025.3; extra == "dev"
203
- Requires-Dist: urllib3==2.6.3; extra == "dev"
203
+ Requires-Dist: urllib3==2.7.0; extra == "dev"
204
204
  Requires-Dist: uv==0.10.11; extra == "dev"
205
205
  Requires-Dist: virtualenv==21.2.0; extra == "dev"
206
206
  Provides-Extra: browser
@@ -213,7 +213,7 @@ Requires-Dist: charset-normalizer==3.4.6; extra == "browser"
213
213
  Requires-Dist: click==8.3.1; extra == "browser"
214
214
  Requires-Dist: colorama==0.4.6; sys_platform == "win32" and extra == "browser"
215
215
  Requires-Dist: gitdb==4.0.12; extra == "browser"
216
- Requires-Dist: gitpython==3.1.46; extra == "browser"
216
+ Requires-Dist: gitpython==3.1.61; extra == "browser"
217
217
  Requires-Dist: idna==3.11; extra == "browser"
218
218
  Requires-Dist: jinja2==3.1.6; extra == "browser"
219
219
  Requires-Dist: jsonschema==4.26.0; extra == "browser"
@@ -224,7 +224,7 @@ Requires-Dist: numpy==1.26.4; python_full_version < "3.11" and extra == "browser
224
224
  Requires-Dist: numpy==2.4.3; python_full_version >= "3.11" and extra == "browser"
225
225
  Requires-Dist: packaging==26.0; extra == "browser"
226
226
  Requires-Dist: pandas==2.3.3; extra == "browser"
227
- Requires-Dist: pillow==12.1.1; extra == "browser"
227
+ Requires-Dist: pillow==12.3.0; extra == "browser"
228
228
  Requires-Dist: protobuf==6.33.5; extra == "browser"
229
229
  Requires-Dist: pyarrow==23.0.1; extra == "browser"
230
230
  Requires-Dist: pydeck==0.9.1; extra == "browser"
@@ -241,7 +241,7 @@ Requires-Dist: toml==0.10.2; extra == "browser"
241
241
  Requires-Dist: tornado==6.5.5; extra == "browser"
242
242
  Requires-Dist: typing-extensions==4.15.0; extra == "browser"
243
243
  Requires-Dist: tzdata==2025.3; extra == "browser"
244
- Requires-Dist: urllib3==2.6.3; extra == "browser"
244
+ Requires-Dist: urllib3==2.7.0; extra == "browser"
245
245
  Requires-Dist: watchdog==6.0.0; sys_platform != "darwin" and extra == "browser"
246
246
  Provides-Extra: playwright
247
247
  Requires-Dist: greenlet==3.3.2; extra == "playwright"
@@ -346,7 +346,8 @@ refused whether it sits inside the repository or outside it.
346
346
 
347
347
  **The repository's own config is not trusted.** A `.patch.conf.yml` or `.env` discovered inside
348
348
  the repository cannot set execution-capable options (`test`, `test-cmd`, `lint-cmd`, `load`,
349
- `notifications-command`, `editor`, `verify-ssl`, `git-commit-verify`) or environment variables
349
+ `notifications-command`, `editor`, `verify-ssl`, `git-commit-verify`, `allow-private-urls`,
350
+ `gui-address`) or environment variables
350
351
  that redirect API endpoints or proxies (`*_API_BASE`, `*_BASE_URL`, `HTTP(S)_PROXY`,
351
352
  `REQUESTS_CA_BUNDLE`, ...). Nor can it name another file for Patch to trust — `env-file`,
352
353
  `model-settings-file` and `model-metadata-file` are refused from repository config for that reason.
@@ -364,6 +365,19 @@ Pass `--trust-repo-config` to opt back in for a repository you trust. You can al
364
365
  `PATCH_TRUST_REPO_CONFIG` in your shell. The setting is ignored when it comes from the repository's
365
366
  own config or `.env`, so a repository cannot grant itself trust.
366
367
 
368
+ **Scraping stays on public addresses.** `/web`, and any URL Patch fetches on your behalf, is
369
+ refused when it resolves to a private, loopback or link-local address. Cloud metadata services
370
+ answer on `169.254.169.254` and hand out IAM credentials to whatever asks, and the URL usually
371
+ comes from the repository — a README is enough to aim it. Names are checked after resolution, so a
372
+ hostname with an A record pointing at a private address is refused too, as is a redirect that
373
+ arrives at one. Pass `--allow-private-urls` to scrape a local dev server deliberately; a repository
374
+ config cannot set it.
375
+
376
+ **The browser UI listens on this machine only.** `--browser` / `--gui` binds `127.0.0.1`. The UI
377
+ has no authentication and can edit your repository and spend your API credits, so it is not
378
+ something to put on a shared network by accident. `--gui-address ADDR` moves it deliberately —
379
+ `--gui-address 0.0.0.0` accepts connections from anywhere and says so at startup.
380
+
367
381
  **Running in a container.** The boundary above distinguishes your files from the repository's by
368
382
  comparing against your home directory, so do not set `HOME` to the directory you mount the project
369
383
  into — the two become indistinguishable and every filter above stops applying. The bundled
@@ -94,7 +94,8 @@ refused whether it sits inside the repository or outside it.
94
94
 
95
95
  **The repository's own config is not trusted.** A `.patch.conf.yml` or `.env` discovered inside
96
96
  the repository cannot set execution-capable options (`test`, `test-cmd`, `lint-cmd`, `load`,
97
- `notifications-command`, `editor`, `verify-ssl`, `git-commit-verify`) or environment variables
97
+ `notifications-command`, `editor`, `verify-ssl`, `git-commit-verify`, `allow-private-urls`,
98
+ `gui-address`) or environment variables
98
99
  that redirect API endpoints or proxies (`*_API_BASE`, `*_BASE_URL`, `HTTP(S)_PROXY`,
99
100
  `REQUESTS_CA_BUNDLE`, ...). Nor can it name another file for Patch to trust — `env-file`,
100
101
  `model-settings-file` and `model-metadata-file` are refused from repository config for that reason.
@@ -112,6 +113,19 @@ Pass `--trust-repo-config` to opt back in for a repository you trust. You can al
112
113
  `PATCH_TRUST_REPO_CONFIG` in your shell. The setting is ignored when it comes from the repository's
113
114
  own config or `.env`, so a repository cannot grant itself trust.
114
115
 
116
+ **Scraping stays on public addresses.** `/web`, and any URL Patch fetches on your behalf, is
117
+ refused when it resolves to a private, loopback or link-local address. Cloud metadata services
118
+ answer on `169.254.169.254` and hand out IAM credentials to whatever asks, and the URL usually
119
+ comes from the repository — a README is enough to aim it. Names are checked after resolution, so a
120
+ hostname with an A record pointing at a private address is refused too, as is a redirect that
121
+ arrives at one. Pass `--allow-private-urls` to scrape a local dev server deliberately; a repository
122
+ config cannot set it.
123
+
124
+ **The browser UI listens on this machine only.** `--browser` / `--gui` binds `127.0.0.1`. The UI
125
+ has no authentication and can edit your repository and spend your API credits, so it is not
126
+ something to put on a shared network by accident. `--gui-address ADDR` moves it deliberately —
127
+ `--gui-address 0.0.0.0` accepts connections from anywhere and says so at startup.
128
+
115
129
  **Running in a container.** The boundary above distinguishes your files from the repository's by
116
130
  comparing against your home directory, so do not set `HOME` to the directory you mount the project
117
131
  into — the two become indistinguishable and every filter above stops applying. The bundled
@@ -727,6 +727,7 @@ def run_test_real(
727
727
  test_files = config.get("files", {}).get("test", [])
728
728
  example_files = config.get("files", {}).get("example", [])
729
729
  solution_files = set(config.get("files", {}).get("solution", []))
730
+ editor_files = set(config.get("files", {}).get("editor", []))
730
731
 
731
732
  # Forcibly ignore certain files not covered by test_files and example_files
732
733
  ignore_files = set(
@@ -747,6 +748,12 @@ def run_test_real(
747
748
  # Remove any ignore files from the solution set that LLM will edit
748
749
  solution_files.difference_update(ignore_files)
749
750
 
751
+ # Editor files provide context, but tests and examples must remain hidden.
752
+ editor_files.difference_update(test_files)
753
+ editor_files.difference_update(example_files)
754
+ editor_files.difference_update(solution_files)
755
+ read_only_fnames = [testdir / file_path for file_path in sorted(editor_files)]
756
+
750
757
  # Copy all solution files
751
758
  for file_path in solution_files:
752
759
  src = testdir / Path(file_path)
@@ -824,6 +831,7 @@ def run_test_real(
824
831
  edit_format,
825
832
  io,
826
833
  fnames=fnames,
834
+ read_only_fnames=read_only_fnames,
827
835
  use_git=False,
828
836
  stream=False,
829
837
  verbose=verbose,