Skip to content

Add support for .patch files as a recognized code format - #164

Merged
ChALkeR merged 2 commits into
mainfrom
claude/patch-format-support-8s9bxm
Aug 7, 2026
Merged

Add support for .patch files as a recognized code format#164
ChALkeR merged 2 commits into
mainfrom
claude/patch-format-support-8s9bxm

Conversation

@exo-nikita

Copy link
Copy Markdown
Collaborator

Summary

This PR adds support for .patch files (unified diffs) as a first-class code format in stasis, alongside existing formats like xml, shell, etc. Patch files are build inputs used by tools like pnpm's patchedDependencies, patch-package, and build scripts that apply patches during the build process.

Key Changes

  • New format patch: Added patch to KNOWN_FORMATS and CODE_EXT_FORMATS mapping .patch extension to the patch format
  • Renamed utility function: isBinaryPlist()isBinaryTextInput() to handle both binary plists and non-UTF-8 patches, since both are formats that should be stored as UTF-8 text but can legitimately contain binary bytes
  • Extended binary detection: The isBinaryTextInput() function now checks for both .plist and .patch extensions, treating non-UTF-8 content in these formats as resources rather than code
  • Updated refineNativeCapture(): Modified to use the renamed function and dynamically check the file extension's allowlist status
  • Documentation: Added comprehensive section in file-formats.md explaining patch files, their UTF-8 storage, and behavior when containing non-UTF-8 bytes
  • Error handling: Added specific error message in hooks.js when attempting to execute a patch file via Node loader
  • Test coverage: Added tests for patch file handling in add.test.js and fs.test.js, covering both UTF-8 and non-UTF-8 patch scenarios

Implementation Details

  • Patch files are stored as raw UTF-8 text (like other code formats), not base64, so stasis diff shows text diffs and stasis extract writes them back byte-for-byte
  • A patch whose hunks contain non-UTF-8 bytes (e.g., copying from a latin-1 source file) cannot be represented as UTF-8 and falls through to the resource path, requiring patch in the resources allowlist
  • This follows the same pattern as binary plists: both are formats that should be text but can contain binary bytes in practice
  • Patches are recognized in all name-based classification contexts: stasis add, --fs filesystem captures, and Metro native walks
  • Patches pulled in as bundler assets remain resource format (unchanged behavior)

https://claude.ai/code/session_01KoTa1QbaGEnmYs79TPuARq

claude added 2 commits July 29, 2026 07:04
A `.patch` is a build input in its own right -- pnpm `patchedDependencies`,
patch-package, a podspec or build script that shells out to `git apply` -- but it
had no format: capturing one meant declaring `patch` in `resources` and storing
it as an opaque blob. It now classifies as `patch` and rides the text path, so
the payload is raw UTF-8, `stasis diff` shows a changed patch as a text diff, and
`extract` writes it back byte-for-byte.

- `patch` joins KNOWN_FORMATS as its own family: a UTF-8 text build input, no
  language's source, and not the byte blob `resource` would make it. Recorded
  wherever the name-based classifier runs -- `stasis add`, an `fs.readFileSync`
  capture under `--fs`, and the Metro native capture / `bundle --metro` walk. The
  JS-graph bundler plugins are unchanged: a `.patch` pulled in as a bundler asset
  is still a `resource`, like a `.sh` or a `.plist`.
- A patch whose hunks copy raw bytes out of a non-UTF-8 file can't be the UTF-8
  string the format implies -- exactly the hazard `isBinaryPlist` was added for,
  so generalize it to `isBinaryTextInput` over both extensions. Such a file is
  NOT code: it falls through to the resource path (base64 when `patch` is
  allowlisted, refused otherwise) instead of aborting the capture.
- `patch` is not a Node loader format, so the loader refuses to execute one, with
  its own message rather than the tampered-or-newer-stasis fallback.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KoTa1QbaGEnmYs79TPuARq
Drop the isBinaryPlist -> isBinaryTextInput generalization: a non-UTF-8
`.patch` now fails closed on the ordinary source UTF-8 check like any other
text format, instead of demoting to the resource path. Rare enough (a patch
of a non-UTF-8 file) not to earn the machinery, and it keeps the plist
special case scoped to the one format that legitimately ships binary.

Also fold the standalone doc section into the `formats` bullet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KoTa1QbaGEnmYs79TPuARq
@ChALkeR
ChALkeR merged commit fbad201 into main Aug 7, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants