23 KiB
23 KiB
Changelog
[Unreleased]
Changed
- Improved snapshot recovery line remapping by utilizing native line diffing.
[17.0.4] - 2026-07-18
Fixed
- Rejected
DEL N:headers with a trailing colon instead of silently tolerating the colon, so delete-with-body mistakes surface the corrective "has no colon" guidance.
[17.0.0] - 2026-07-15
Added
- Added
enforceSeenLinesoption toPatcherOptions(defaulting totrue) to control whether seen-line validation is enforced on anchored edits, allowing tags to validate on content hash alone when disabled.
[16.5.0] - 2026-07-13
Fixed
- Fixed a critical issue where ambiguous swaps could silently delete range boundaries.
- Prevented incorrect auto-repairing of structural closing lines when payload placement is ambiguous.
- Fixed a bug in stale-hash recovery that could incorrectly relocate edits onto duplicated context after the original target changed.
[16.3.3] - 2026-07-02
Breaking Changes
- Removed SnapshotStore.byHashExact. Consumers should now use byHash, which resolves collisions by returning the most recently recorded version.
Changed
- Improved patch application robustness by resolving 16-bit snapshot tag collisions to the most recent version instead of rejecting them.
Fixed
- Fixed frequent edit rejections after a structural-summary read (affecting parseable code over 100 lines) by automatically inlining unseen anchor lines and merging them into the snapshot's seen lines, allowing immediate retries to succeed without requiring a separate range re-read.
[16.3.0] - 2026-07-02
Changed
- Significantly improved performance on large files by optimizing stale-anchor remap validation.
Fixed
- Fixed an issue where snapshot tag collisions could cause line-anchored edits to be incorrectly applied to unrelated content, improving recovery and edit-preview safety.
- Fixed tracking of edit anchors when earlier in-session insertions or deletions shift unchanged target lines.
- Fixed hashline edit guidance and parsing errors for Markdown list rows.
[16.2.8] - 2026-06-30
Fixed
- Fixed hashline writes preserving UTF-8 BOM bytes when the host text decoder hides the leading
U+FEFF. (#3867)
[16.2.6] - 2026-06-29
Fixed
- Fixed a parser error ("payload line has no preceding hunk header") caused by stray dots before the trailing colon in hunk headers, improving compatibility with GLM 5.2 outputs.
[16.2.0] - 2026-06-27
Added
- Added
REM(remove) andMV(move/rename) section operations to hashline patches, allowing files to be deleted or relocated (with snapshot history migration) directly within the edit tool.
[16.1.23] - 2026-06-26
Added
- Updated prompt documentation to include support for Markdown section operations
Fixed
- Improved file path recovery to correctly handle read-only or incorrectly typed paths
[16.1.14] - 2026-06-22
Fixed
- Improved delimiter-balance repair to correctly identify and spare deleted structural closers
- Prevented premature deletion of structural closers when existing code below the range covers them
- Accurate tracking of inserted lines to improve boundary repair logic for surrounding code blocks
- Fixed delimiter-balance repair so deleted closer suffixes are kept only when the replacement prefix still has unmatched openers for them, avoiding duplicated trailing braces while preserving omitted outer closers.
[16.1.8] - 2026-06-20
Fixed
- Fixed multi-hunk delimiter-balance repair so a
SWAPthat drops a structural closer no longer keeps it when another hunk already removed the matching opener (a deliberate wrapper removal); the missing-closer repair now weighs each group against the whole patch's residual delimiter balance — summed per hunk so quote/comment state never bleeds across non-contiguous hunks — and consumes that residual per repair so a genuine missing closer elsewhere still fires. (#3142)
[16.1.2] - 2026-06-19
Changed
- Refined documentation and prompt instructions for clarity and brevity
[16.0.2] - 2026-06-16
Fixed
- Auto-repaired duplicated JSX/XML closing boundary lines at the end of single-line replacement expansions. (#2705)
[16.0.1] - 2026-06-15
Fixed
- Auto-repaired one-sided multi-line boundary echoes by dropping delimiter-neutral duplicated boundary lines and emitted a boundary-echo warning
- Parser now treats a leading
\on inline payload bodies as the payload delimiter, matching standalone payload rows. - Restored the warning emitted when escaped indented payload rows (
\\ TEXT) are accepted as payload delimiters.
[15.13.3] - 2026-06-15
Changed
- Changed the recommended hashline range separator from
..to.=(e.g.SWAP 1.=3:,DEL 4.=5) so the inclusive<=-style end is self-evident.HL_RANGE_SEPis now.=; the prompt, grammar, error messages, and emitted headers all use it. The lenient parser still accepts the legacy..(and-/…/space) forms.
[15.13.2] - 2026-06-15
Breaking Changes
- Renamed all hashline DSL operators to concise abbreviated keywords:
replace->SWAPdelete->DELinsert before/after/head/tail->INS.PRE/POST/HEAD/TAILreplace_block->SWAP.BLKdelete_block->DEL.BLKinsert_after_block->INS.BLK.POST
[15.13.1] - 2026-06-15
Breaking Changes
- Rejected edits anchored to lines not displayed in the tagged read/search output, requiring unseen ranges to be re-read before reapplying
Changed
- Rejected
replace block,delete block, andinsert after blockoperations that resolve to a single line and instructed users to use the plain single-line form or anchor the true construct opener
Fixed
- Normalized cwd-relative hashline paths to forward-slash form on Windows.
[15.12.5] - 2026-06-13
Fixed
- Fixed delimiter-balance boundary repair so it does not keep a deleted structural closer when the replacement payload already restates that closer.
[15.12.0] - 2026-06-12
Changed
- Condensed all parser/applier/patcher error and warning messages: shorter wording, same diagnostic anchors (op names, line numbers, suggested fallback forms)
[15.11.4] - 2026-06-12
Added
- Added inward landing correction for
insert after block N:: a body indented deeper than the block's closing line now slides back across the block's trailing closer lines and lands inside the block at its claimed depth, with a warning naming the landing line. Same conservative guards as the outward shift — comparable indentation only, closers only, abandoned when another hunk targets a crossed line; plaininsert after M:stays literal - Added closer-anchor lowering for
insert after block N:: anchoring on a pure closing-delimiter line (where no block begins, so resolution previously failed the whole patch) now applies as plaininsert after N:with a warning teaching the opener-only rule.resolveBlockEditsgained anonWarningcallback; apply, preview, and patcher paths surface it onwarnings
Changed
- Condensed the edit-tool prompt: one-line op definitions, 5–20-word rules, and a tighter
<critical>recap; landing-correction mechanics are no longer described to the agent
[15.11.1] - 2026-06-11
Fixed
- Fixed the
insert after block N:prompt guidance so it explicitly says N must be the block opener, not the closing delimiter or last visible line, and points visible closing-line edits to plaininsert after M:. (#2292)
[15.11.0] - 2026-06-10
Changed
- Block-unresolved errors (
replace block N:/delete block N/insert after block N:failing to resolve a syntactic block) now append a numbered preview of the file around the anchor line — same*-marked context rows the hash-mismatch error shows — so the offending line is visible without a re-read
[15.10.11] - 2026-06-10
Breaking Changes
- Changed
BlockResolution.isDeletetoBlockResolution.op("replace" | "delete" | "insert_after") so resolutions can describe every block-anchored op
Added
- Added
insert after block N:patch syntax to insert body rows after the last line of the tree-sitter-resolved block beginning on line N, so a statement can be placed after a construct without counting to its closing line - Added depth-guided landing correction for
insert after N:hunks: a body indented shallower than its anchor line slides past the structural closer lines below the anchor until depth returns to the body's level, with a warning naming the final landing line. The shift never crosses content lines, skips incomparable indentation styles and pure-closer bodies, and is abandoned when another hunk targets a crossed line - Added a global byte ceiling to
InMemorySnapshotStore(maxTotalBytes, default 64 MiB): the cap was previously per-file only, so a session reading many large files retained up to 30 paths × 4 full-text versions indefinitely
Changed
- Trimmed the
replace block N:ops entry in the patch prompt to grammar and pointing rules; the usage doctrine it duplicated stays in the rules section - Changed
buildCompactDiffPreviewto treat blank rows as gap separators alongside…markers: separators never stack (removed lines omitted from the preview no longer leave two adjacent), and leading/trailing separators are trimmed
Fixed
- Fixed the boundary-echo repair stripping payload edges without the balance-neutrality guard its own documentation promised: in brace-heavy code where bare
}lines repeat, a payload intentionally beginning/ending with lines identical to the range's neighbors had both edges silently dropped, writing content that differed from what was authored - Fixed lenient bare-body handling silently mutating payloads: interior blank rows in an un-prefixed body were dropped outright, and a body of numeric-keyed literals (
1: "one"dict/YAML shapes) satisfied the uniform line-prefix check and had its keys stripped from every line — blank rows are now preserved when proven interior, and the uniform strip refuses lone-literal remainders - Fixed the multi-section "all-or-nothing" claim being false for write failures: commits run serially, so a mid-batch write error left earlier sections on disk while the thrown error said nothing — the error now lists exactly which sections were written and which were not
- Fixed
delete/replaceranges ending on the phantom trailing line of a newline-terminated file silently stripping the file's final newline; such anchors are now rejected with guidance towardN-1/insert tail:(inserts there remain valid, and genuine empty last lines of unterminated files stay deletable)
[15.10.5] - 2026-06-08
Added
- Added
maxAddedRunContextoption to control how many added lines are shown at each side of collapsed inserted runs, withmaxUnchangedRunkept as a backward-compatible alias
Changed
- Changed
buildCompactDiffPreviewto omit removed lines from the preview while preserving removal counts for offset tracking - Changed
buildCompactDiffPreviewto collapse long contiguous added runs with a bare…marker, keeping only the first and lastmaxAddedRunContextlines visible (the surrounding line numbers convey how many were elided)
Fixed
- Fixed compact edit previews to omit deleted content, keep visible lines anchored to the current file, and collapse long inserted runs with a bare
…elision marker. - Fixed compact edit previews to render added/current lines without diff-prefix padding and normalize adjacent ASCII/Unicode elision markers to one
….
[15.10.3] - 2026-06-08
Added
- Added a
BlockResolutiontype and surfaced resolved block spans onApplyResult.blockResolutions/PatchSectionResult.blockResolutions.resolveBlockEditsnow accepts anonResolvedcallback that reports eachreplace block N:/delete block Nanchor's resolved[start, end]span (and whether it was a delete). Spans are surfaced only on the no-drift apply paths, where the resolved line numbers line up with the tag the caller read.
Changed
- Reworked the
edittool prompt (prompt.md): added areplace block Nvsreplace N..Mdecision rule, documented that a leading decorator/attribute/doc-comment is a separate node not swept into the block (point N at the first decorator line, or usereplace N..Mfor a Rust-style///sibling comment), reframed the blast-radius guidance so "block replace" no longer reads as the dangerous option, and added a decorated-definition example.
[15.10.2] - 2026-06-08
Fixed
- Stripped read-output line-number prefixes (
N:) from auto-piped bare body rows so that pasting3:textwithout a+prefix no longer injects3:as literal content. Stripping is applied only when every bare row in the hunk carries the prefix (the signature of a pasted snapshot) and removes at most one prefix per row, so a genuine body that merely starts withdigits:(YAML port maps, timestamps) is left intact (#1492).
[15.9.67] - 2026-06-06
Breaking Changes
- Changed hashline file section headers from
¶PATH#TAGto[PATH#TAG]so model-authored edits use ASCII delimiters instead of a pilcrow sigil.
Fixed
- Fixed missing-header diagnostics and copied-content prefix stripping to consistently teach and recognize 4-hex snapshot tags.
[15.8.2] - 2026-06-03
Fixed
- Fixed delimiter-balance boundary repair to also drop a single duplicated structural opener (e.g. a restated
foo(/if (x) {signature line surviving just above the range), not only duplicated closers. Zero-balance duplicates remain untouched.
[15.8.0] - 2026-06-02
Fixed
- Fixed hashline replacements that accidentally restated unchanged lines above and below the selected range so they no longer duplicate both boundary lines (#1664).
[15.7.0] - 2026-05-31
Added
- Added
replace block N:anddelete block Npatch syntax to replace or delete the entire syntactic block that begins on line N using tree-sitter-resolved spans - Added
BlockResolversupport inPatcherandPatchSection.applyTo/applyPartialToto wire language-specific block-resolution at apply time - Added
resolveBlockEditsand block edit type definitions to the package API for resolving deferredreplace block/delete blockedits
[15.5.13] - 2026-05-29
Breaking Changes
- Changed hashline section tags from 3-hex to 4-hex content-hash tags, so legacy 3-digit tags are no longer valid
- Changed hashline syntax to verb-based v4: body-bearing ops are
replace N..M:,insert before N:,insert after N:,insert head:, andinsert tail:, while bodylessdelete N..Mhandles deletion. Removed>A..Brepeat rows and the oldprepend:/append:virtual insert headers;-rows remain rejected with a teaching error.
Added
- Added
maxPathsandmaxVersionsPerPathoptions toInMemorySnapshotStoreto bound tracked paths and per-path snapshot history - Re-introduced balance-validated boundary repair in
applyEdits. A replacement hunk (replace N..M:+ body) is normalized so its payload preserves the deleted region's delimiter balance: when the body restates a closing delimiter that survives just outside the range (duplicate}/);/]) the echo is dropped, and when the range deletes a structural closer the body never restates (missing closer) the closer is spared instead of deleted. A repair fires only when one boundary operation drives the per-channel()/[]/{}imbalance to exactly zero while leaving surrounding text byte-identical (single-line ops are limited to pure structural-closer lines), so balance-preserving edits and intentional balanced duplicates are never touched. Bracket counting skips strings, template literals, and comments. Each repair surfaces adelimiter-balancewarning throughApplyResult.warnings.
Changed
- Changed patch application to accept edits whenever the live file's normalized content hash matches the section tag, even when that anchor was not covered by a stored snapshot
Removed
- Removed
SnapshotStore.recordContiguousandSnapshotStore.recordSparsein favor of full-filerecord(path, fullText)snapshots
Fixed
- Fixed hash mismatch rejections caused by CRLF or trailing spaces/tabs by normalizing those characters before computing file-hash tags
[15.5.12] - 2026-05-29
Changed
InMemorySnapshotStorenow coalesces consecutive same-path reads into one tag whenever their views agree on every shared line. Overlapping or directly abutting range reads extend the existing snapshot's contiguous run in place; reads separated by a gap union into aSparseSnapshotspanning both ranges. A disagreeing shared line is treated as "the file changed on disk" and mints a fresh tag, preserving the prior superset-dedup behavior. This stops sequential range reads of an unchanged file (e.g.:50-100then:100-200, or:1-100then:150-200) from fragmenting into separate anchors.
[15.5.11] - 2026-05-29
Added
MismatchErrornow distinguishes "hash recognized but file content drifted" from "hash never recorded for this path". The latter (likely fabricated or carried over from a prior session) emits a dedicatedhash #X is not from this sessionrejection message with explicit "never invent the tag" guidance. TheMismatchDetailsinterface gains an optionalhashRecognized?: boolean(defaults totruefor backward compatibility);MismatchErrorexposes it as a readonly field so callers can branch on the cause.
[15.5.8] - 2026-05-28
Breaking Changes
- Removed the single-number hunk header shorthand. A hunk header now REQUIRES two line numbers (
A Afor a single line,A Bfor a range); a bareArow throwssingle-number hunk header "A" is no longer accepted. The&Abody-row shorthand for&A..Ais unchanged. - Changed hunk header syntax from
A-B:to@@ A..B @@with@@ A @@shorthand for single lines - Changed repeat payload sigil from
^A-Bto&A..Bwith&Ashorthand for single lines - Changed range separator from
-to..in all contexts (anchors and repeats) - Changed empty hunk behavior: concrete ranges now delete (no blank-line insertion); BOF/EOF empty hunks are now no-ops
- Removed
ApplyOptionsparameter fromapplyEdits()and related APIs; auto-absorb behavior is no longer configurable - Removed diagnostic warnings for auto-absorbed duplicates from
ApplyResult; warnings now come only from parser, patcher, or recovery - Removed legacy hashline block syntax
A-B:,A-B:-, and^A-Band replaced edits with@@ A..B @@hunks using+and&body rows - Removed
A:shorthand syntax; use explicitA-A:for single-line anchors - Removed
↑and↓payload sigils; use|TEXTfor literal rows and^A-Bfor repeating original lines - Removed standalone delete rows; use inline
A-B:-syntax instead - Removed
after_anchorcursor kind; all inserts now usebefore_anchorpositioning - Replaced insert-above/insert-below payload sigils with linear body rows:
|TEXTemits literal text and^A-Brepeats original file lines inline. - Replaced standalone delete rows with inline range deletes: use
A-B:-. - Changed empty
A-B:,BOF:, andEOF:blocks to write one blank line instead of being rejected.
Added
- Added compatibility parsing for apply_patch-style and unified-diff row noise by stripping path noise and converting context/delete body rows into hashline-compatible operations with warnings
- Added
A-B:-inline delete syntax for concrete range anchors - Added
^A-Brepeat payload syntax to emit original file lines inline - Added support for empty anchor blocks to write one blank line at the anchor position
Changed
- Changed unified-diff compatibility mode to silently drop
-oldrows and convert context rows to+TEXTliterals with a warning instead of rejecting them - Changed
ABORT_MARKERbehavior to terminate parsing without surfacing a warning - Changed numeric ranges to
A..Bform and accepted@@ A @@as shorthand for@@ A..A @@ - Changed empty hunk behavior so a concrete empty hunk deletes the selected range and
BOF/EOFempty hunks no longer insert a blank line - Changed parse behavior for
*** Abortto stop processing without returning a speculative truncation warning - Changed payload row format from three sigils (
|,↑,↓) to two (|,^) - Changed range anchor syntax to require explicit
A-Bform (no single-line shorthand) - Changed error messages to reference new syntax and remove references to removed sigils
[15.5.5] - 2026-05-27
Breaking Changes
- Changed hashline payload continuations from
+TEXTto\TEXT; use\for an explicit blank payload line.
Added
- Added
parsePatchStreaming(diff)andPatchSection.applyPartialTo(text, options)for incremental diff previews. Both tolerate a trailing in-flight op (no payload yet, or a per-token parse error mid-stream) instead of throwing or emitting a phantom empty-payload edit. - Added
Executor.endStreaming()— sibling ofend()that drops a pending op with no accumulated payload rather than flushing it.
Fixed
- Parser now skips markdown-style
# ...lines when they directly precede a hashline operation, making model-generated explanatory rows in prompt examples non-blocking.
Removed
- Removed the
A-B!/A!deletion operator. UseA-B:with the desired payload (or empty payload to blank the range) instead.
All notable changes to this package will be documented in this file.
[15.5.4] - 2026-05-27
Added
- Added a high-level
PatcherAPI with all-or-nothingapplyand stagedprepare/commitflows for multi-file patch updates - Added pluggable
FilesystemandSnapshotStoreabstractions with built-inNodeFilesystem,InMemoryFilesystem, andInMemorySnapshotStoreadapters - Added patch parsing that consumes
¶PATH#HASHhunk headers, validates section file hashes, and supports optional patch envelope markers - Added tolerant input handling that strips read/search prefixes and supports optional
cwd/fallback-path resolution when parsing patch payloads - Added automatic line-ending and BOM normalization on read, with original encoding shape restored on write
- Added follow-up helpers
buildCompactDiffPreviewandstreamHashLinesfor compact diff previews and chunked streaming of numbered lines - Added stale-file-hash recovery that replays edits against snapshots and merges results onto current file content when direct hash validation fails
- Initial standalone release. Extracted from
@oh-my-pi/pi-coding-agent.
Fixed
- Fixed repeated patch application mutating cached
after_anchoredits between target snapshots - Fixed multi-section patching to preflight write policies and reject duplicate canonical targets before any section is committed
- Fixed mixed line-ending restoration to preserve the first newline style instead of rewriting ties to LF