npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

patchsift

v0.1.1

Published

Reduce a Git diff to an observed 1-minimal failure-reproducing patch.

Readme

PatchSift

Thu gọn diff Git đã commit thành một bản vá nhỏ vẫn tái hiện đúng một lỗi cụ thể.

English | Tiếng Việt

Trạng thái: PatchSift 0.1.1 đã được phát hành trên npm. Dòng phiên bản 0.1.x hiện tại gồm CLI, entrypoint thư viện không có side effect, JSON report có phiên bản, demo xác định, setup hook, cleanup worktree cũ và release gate.

PatchSift khác git bisect như thế nào?

git bisect trả lời commit nào bắt đầu gây lỗi? PatchSift trả lời những thay đổi nào bên trong diff giữa hai snapshot là cần thiết để tái hiện lỗi?

git bisect                         PatchSift
──────────                         ─────────
Tìm trong lịch sử commit           Tìm trong các unit của một endpoint diff
Trả về một commit                  Trả về bản vá tối giản có thể chia sẻ
Cần các commit good/bad            Cần base PASS và target MATCH
Không tách nội dung commit         Tách file text đã sửa thành các hunk

PatchSift báo cáo observed 1-minimality, không khẳng định đã tìm ra bản vá nhỏ nhất toàn cục. observed-1-minimal nghĩa là công cụ đã thử bỏ riêng từng unit cuối cùng và không phép bỏ nào còn tái hiện lỗi. Nếu có phép thử không thể kết luận, kết quả được ghi là best-found-unresolved.

Yêu cầu

  • Node.js 22 trở lên.
  • Git 2.25 trở lên.
  • macOS hoặc Linux.
  • Git worktree sạch và không phải bare repository.
  • Lệnh oracle có tính xác định.

PatchSift không có runtime npm dependency.

Cài đặt và build

Cài CLI từ public npm registry:

npm install --global [email protected]
patchsift --version

Để build cùng phiên bản đó từ mã nguồn:

npm ci --ignore-scripts
npm run build
node dist/cli.js --help

Quy trình build chỉ xóa thư mục dist/ thật bên trong repository trước khi chạy TypeScript. Có thể kiểm tra đúng npm artifact mà không cần publish:

npm run pack:check
npm run test:consumers
npm run test:packed

Bắt đầu nhanh

Lệnh dưới đây giả định revision base chạy thành công và revision target in ra Expected total: 1201 rồi thoát với mã khác 0:

patchsift minimize \
  --base good-revision \
  --target bad-revision \
  --match-literal "Expected total: 1201" \
  -- npm test -- pricing.test.ts

API thư viện

Root của package là thư viện ESM không có side effect và đi kèm declaration. Các đường dẫn module nội bộ không được export; chỉ import từ patchsift. API lập trình cung cấp cùng minimization engine và thao tác cleanup có guard như CLI, với run context và progress event rõ ràng.

import {
  PATCHSIFT_VERSION,
  minimize,
} from "patchsift";
import type { MinimizeOptions } from "patchsift";

const options: MinimizeOptions = {
  repository: process.cwd(),
  base: "demo-good",
  target: "demo-bad",
  oracle: { command: process.execPath, args: ["test-pricing.mjs"] },
  matcher: {
    kind: "literal",
    text: "Expected total: 1201",
    stream: "stderr",
  },
  timeoutMs: 30_000,
  artifacts: {
    patchPath: "./patchsift-min.patch",
    reportPath: "./patchsift-report.json",
  },
};

const result = await minimize(options, {
  environment: { PATCHSIFT_DEMO: "1" },
  onProgress(event) {
    if (event.type === "warning") console.warn(event.message);
  },
});
console.log(PATCHSIFT_VERSION, result.minimality, result.retainedUnitIds);

Các runtime export chính xác là minimize, cleanup, PatchSiftError, PATCHSIFT_VERSIONREPORT_SCHEMA_VERSION. Literal matcher dùng text; regular-expression matcher dùng pattern cùng flags tùy chọn. MinimizeOptions bắt buộc có repository và mô tả base, target, matcher, oracle, giới hạn cùng artifact path tùy chọn. Mỗi run ưu tiên bộ nhớ: bỏ artifacts để không ghi file và nhận verified patch cùng report trong kết quả trả về. Nếu được cung cấp, artifacts phải yêu cầu patch path, report path hoặc cả hai. RunContext cung cấp environment overlay, abort signal và progress callback tùy chọn. Callback trả về Promise được await tuần tự; context không thay đổi working directory của repository. Kết quả còn chứa minimality, exit code, retained unit ID và các artifact path đã yêu cầu ghi. Dùng cleanup({ repository, olderThanMs, dryRun }) để kiểm tra hoặc xóa các owned worktree cũ bằng API.

Target mặc định là HEAD. PatchSift ghi artifact vào:

<repository>/.patchsift/runs/<run-id>/
├── minimal.patch
└── report.json

Tiến trình dành cho người đọc được ghi vào stderr. Dùng --json - để stdout chỉ chứa JSON dành cho máy.

CLI

patchsift minimize
  --base <revision>
  [--target <revision>]
  (--match-literal <text> |
   --match-regex <pattern> [--regex-flags <imsu>])
  [--match-stream either|stdout|stderr]
  [--timeout <Nms|Ns|Nm|Nh>]
  [--max-output <NB|NKiB|NMiB>]
  [--setup <posix-shell-command>]
  [--output <patch-path>]
  [--json <report-path|->]
  [--force]
  [--quiet]
  [--no-color]
  -- <program> [arguments...]

patchsift cleanup [--older-than <duration>] [--dry-run] [--quiet]
patchsift --help
patchsift --version

Hành vi quan trọng:

  • --match-literal tìm chuỗi chính xác và phân biệt hoa thường.
  • --match-regex dùng JavaScript regular expression. Flags mặc định là u; chỉ chấp nhận i, m, s, u. Regex chạy trong worker có deadline để backtracking xấu không thể làm treo CLI.
  • stdout và stderr được kiểm tra riêng. either không nối hai stream.
  • --timeout mặc định 5m và tối đa 24h.
  • --max-output mặc định 8 MiB tổng cộng và tối đa 64 MiB.
  • cleanup --older-than chấp nhận ms, s, m, h, d; mặc định là 24h và tối đa 365d.
  • Oracle sau -- được spawn trực tiếp bằng argv, không qua shell.
  • --setup chủ động dùng /bin/sh -c; nó chạy sau khi áp dụng từng candidate và trước oracle tương ứng.
  • --force chỉ thay một artifact regular chưa được Git track. Nó không bỏ qua kiểm tra repository, symlink hoặc quyền sở hữu worktree.

Ví dụ dùng regex và cài dependency:

patchsift minimize \
  --base main \
  --target HEAD \
  --match-regex "Expected total: 12[0-9]{2}" \
  --regex-flags u \
  --setup "npm ci --ignore-scripts" \
  -- npm test -- pricing.test.ts

Các kết quả của oracle

PatchSift không xem mọi exit khác 0 là bằng chứng lỗi mục tiêu vẫn tồn tại.

| Quan sát process | Kết quả | | --- | --- | | Exit 0 | PASS, kể cả khi output chứa matcher | | Exit khác 0 và có đúng signature | MATCH | | Exit khác 0 nhưng không có signature | UNRESOLVED/different-failure | | Hết thời gian | UNRESOLVED/timeout | | Bị signal | UNRESOLVED/signal | | Vượt giới hạn output | UNRESOLVED/output-limit | | Regex worker quá deadline | UNRESOLVED/matcher-timeout | | Candidate không qua git apply --check | UNRESOLVED/invalid-patch | | Setup thất bại | UNRESOLVED/setup-failed |

Chỉ MATCH cho phép minimizer loại thay đổi. Base preflight bắt buộc là PASS và toàn bộ endpoint diff bắt buộc là MATCH.

Cách hoạt động

  1. Phân giải base và target đúng một lần thành commit object ID bất biến.
  2. Từ chối source worktree bẩn và metadata diff chưa được hỗ trợ.
  3. Tạo endpoint-tree diff canonical UTF-8.
  4. Xem mỗi hunk của file sửa là một unit; file thêm/xóa là unit atomic.
  5. Xác minh render toàn bộ unit khôi phục chính xác canonical diff.
  6. Tạo detached worktree ở base với ownership marker.
  7. Preflight candidate rỗng và candidate đầy đủ.
  8. Chạy ddmin theo complement trước và cache kết quả xác định.
  9. Restart lượt bỏ từng unit mỗi khi tìm thấy thêm một unit có thể bỏ.
  10. Sinh patch từ index của worktree xác minh mới, apply lại và chạy oracle mà không dùng candidate cache.
  11. Ghi atomic patch đã xác minh và JSON report có version.

Base và target không cần quan hệ ancestor. PatchSift thu gọn khác biệt tree của hai endpoint và kiểm tra trực tiếp hành vi của chúng.

Các loại thay đổi được hỗ trợ

Bản hiện tại hỗ trợ:

  • các hunk trong regular text file UTF-8 đã sửa;
  • regular text file UTF-8 được thêm/xóa dưới dạng atomic; và
  • mode regular 100644100755.

Công cụ từ chối rename/copy, binary, mode transition, symlink, submodule, combined diff, conflict, UTF-8 không hợp lệ và endpoint diff từ 64 MiB trở lên. Đây là giới hạn an toàn rõ ràng, không phải fallback âm thầm.

Mô hình an toàn

PatchSift không reset hoặc clean worktree của người dùng. Candidate chạy trong thư mục tạm có ownership marker liên kết run ID, base SHA, Git common directory, PID và real path chính xác. Mọi reset/clean/remove phá hủy dữ liệu đều xác minh lại marker trước.

Oracle chạy trong POSIX process group riêng. Khi timeout, PatchSift gửi SIGTERM, chờ một giây rồi gửi SIGKILL theo best effort. SIGINTSIGTERM hủy lệnh đang chạy và kích hoạt cleanup.

Sau SIGKILL, crash hoặc mất điện, hãy xem trước khi dọn:

patchsift cleanup --dry-run
patchsift cleanup --older-than 24h

Cleanup chỉ xem xét temporary worktree không còn hoạt động, có ownership marker hợp lệ và thuộc repository hiện tại. Công cụ không bao giờ tự chạy git worktree prune trên toàn repository.

PatchSift chạy mã repository đáng tin bằng quyền của người dùng. Git worktree không phải security sandbox. Hãy đọc SECURITY.md trước khi chạy với mã lạ.

JSON report

Mọi report dùng schemaVersion: 1. Contract đã đóng băng và được phân phối tại schemas/report-v1.json, đồng thời qua package subpath patchsift/schemas/report-v1.json. Một report chứa:

  • phiên bản tool/run, thời gian, status và exit code;
  • input và SHA base/target đã đóng băng cùng hash full patch;
  • oracle argv, matcher, setup, timeout và output limit;
  • số unit ban đầu/còn lại cùng counter process/cache;
  • ID unit xác định, path, hunk range, hash và trạng thái retained;
  • phase của từng candidate, unit IDs, outcome, duration và cache hit;
  • minimality cuối, unresolved removals và path/hash/size artifact.

Raw stdout và stderr không bao giờ được lưu. Report chỉ chứa số byte, SHA-256, metadata exit/signal và kết quả phân loại.

Exit codes

| Code | Ý nghĩa | | ---: | --- | | 0 | Patch observed-1-minimal đã được xác minh | | 1 | Lỗi nội bộ không mong đợi | | 2 | CLI hoặc cấu hình output không hợp lệ | | 3 | Repository, unsupported diff hoặc preflight thất bại | | 4 | Patch best-found-unresolved đã được xác minh | | 5 | Fresh final verification thất bại | | 130 / 143 | Bị ngắt bởi SIGINT / SIGTERM |

Demo “The Banker's Penny”

Demo xác định có đúng 14 text hunk trong 14 file. Mười hai hunk là thay đổi gây nhiễu trung tính. Hai hunk bắt buộc đổi rounding mode trong config và khiến mã pricing bắt đầu áp dụng config đó. Mỗi hunk đứng riêng đều PASS; kết hợp lại tạo:

Expected total: 1201
Received total: 1200

Chạy demo cục bộ:

npm run build
node scripts/create-demo.mjs /tmp/patchsift-demo

cd /tmp/patchsift-demo
patchsift minimize \
  --base demo-good \
  --target demo-bad \
  --match-literal "Expected total: 1201" \
  -- node test-pricing.mjs

Acceptance test yêu cầu literal và regex cùng giữ đúng hai hunk, hoàn tất dưới 60 giây và không quá 40 lần chạy oracle.

Phát triển

npm run typecheck
npm test
npm run test:coverage
npm run docs:check
npm run schema:check
npm run metadata:check
npm run test:consumers
npm run test:packed
npm run pack:check
npm run release:check

release:check chỉ chạy cục bộ và không publish. Lệnh xác minh metadata cùng tính tương ứng của tài liệu EN/VI, chạy toàn bộ test, compile consumer JavaScript và TypeScript từ tarball, kiểm tra packed CLI bằng cả hai matcher và audit allowlist của tarball.

Bộ test bao phủ parser diff, file thêm/xóa, no-newline marker, Unicode path, tương tác ddmin, candidate unresolved, direct argv, timeout, output cap, regex worker, ownership guard, cleanup, JSON stdout, dirty-source rejection và toàn bộ demo 14→2.

Xem CONTRIBUTING.md để biết các invariant phải giữ.

Lộ trình

Cột mốc kế tiếp tập trung vào thu gọn phân cấp file → hunk → edit-group hoặc line. Xem lộ trình tiếng Anh hoặc lộ trình tiếng Việt để biết các cột mốc sau và phần được hoãn.

Giấy phép

MIT © 2026 MilkyVic.