@oh-my-pi/hashline 16.1.1 → 16.1.2

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.1.2] - 2026-06-19
6
+
7
+ ### Changed
8
+
9
+ - Refined documentation and prompt instructions for clarity and brevity
10
+
5
11
  ## [16.0.2] - 2026-06-16
6
12
 
7
13
  ### Fixed
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/hashline",
4
- "version": "16.1.1",
4
+ "version": "16.1.2",
5
5
  "description": "Hashline: a compact, line-anchored patch language and applier. Pluggable FS/IO so it works over disk, in-memory, or any custom backend.",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
package/src/prompt.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Your patch language names lines to replace, delete, or insert at, then lists the new content. Rule of thumb: a header ending in `:` is followed by `+` body rows; `DEL` has no body.
2
2
 
3
3
  <headers>
4
- Every file section starts with `[PATH#TAG]`. `TAG` is the 4-hex snapshot tag from your latest `read`/`search`, and is REQUIRED on every section — there is no hashless form. To create a new file, use the `write` tool; hashline only edits files that already exist.
4
+ Every file section starts with `[PATH#TAG]`. `TAG` = 4-hex snapshot tag from your latest `read`/`search`, REQUIRED on every section — no hashless form. Create new files with `write`; hashline only edits existing files.
5
5
  </headers>
6
6
 
7
7
  <ops>
@@ -12,33 +12,30 @@ Every file section starts with `[PATH#TAG]`. `TAG` is the 4-hex snapshot tag fro
12
12
  `INS.PRE N:` — insert the body rows immediately before line N.
13
13
  `INS.POST N:` — insert the body rows immediately after line N.
14
14
  `INS.BLK.POST N:` — insert the body rows after the END of the block that BEGINS on line N — outside it, at sibling depth. To append inside a block, use `INS.POST`.
15
- `INS.HEAD:` — insert the body rows at the very start of the file.
16
- `INS.TAIL:` — insert the body rows at the very end of the file.
15
+ `INS.HEAD:` / `INS.TAIL:` — insert the body rows at the very start / end of the file.
17
16
  Single line: `SWAP N.=N:` / `DEL N`. The range is the ORIGINAL lines you touch; body length is irrelevant (replacing 1 line with 10 is still `SWAP N.=N:`).
18
17
  </ops>
19
18
 
20
19
  <body-rows>
21
- Body rows appear only under a `:` header. Every body row is:
22
- +TEXT add a new literal line `TEXT`, verbatim (leading whitespace kept). `+` alone adds a blank line.
23
- There is NO other body row kind. NEVER write `-old` or a bare/context line. To keep a line, leave it out of every range. To insert a literal line starting with `-` or `+`, prefix it: `+-x`, `++x`.
20
+ Body rows appear only under a `:` header. Every body row is `+TEXT` — add a literal line `TEXT`, verbatim (leading whitespace kept); `+` alone adds a blank line. No other row kind. NEVER write `-old` or a bare/context line. To keep a line, leave it out of every range. To insert a literal line starting with `-` or `+`, prefix it: `+-x`, `++x`.
24
21
  </body-rows>
25
22
 
26
23
  <rules>
27
- - Line numbers and the `[PATH#TAG]` header come from your latest `read`/`search` (`LINE:TEXT` rows).
28
- - Numbers refer to the ORIGINAL file; they do not shift as hunks apply.
24
+ - Line numbers + `[PATH#TAG]` header come from your latest `read`/`search` (`LINE:TEXT` rows).
25
+ - Numbers refer to the ORIGINAL file; never shift as hunks apply.
29
26
  - They die with the call: every applied edit mints a fresh `#TAG` and renumbers — anchor the next edit on the edit response or a fresh `read`.
30
- - Touch only lines your latest `read`/`search` literally displayed as `LINE:TEXT`; the tag certifies the snapshot, not your memory of it. A hunk anchored on a line you never displayed is REJECTED — re-`read` those exact lines first. (Seeing a line ≠ it holding the code you mean: confirm the numbers map to the construct you intend, especially far from your last-read window.)
31
- - Elided regions are UNSEEN: `…`/`..` markers and a collapsed `N-M:` summary row (only boundary lines N and M were shown) hide their interior. NEVER place or span a hunk inside one — `read` the range first.
27
+ - Touch only lines your latest `read`/`search` literally displayed as `LINE:TEXT`; the tag certifies the snapshot, not your memory. A hunk anchored on a line you never displayed is REJECTED — re-`read` first. Seeing a line ≠ it holds the code you mean; confirm numbers map to the construct you intend, especially far from your read window.
28
+ - Elided regions are UNSEEN: `…`/`..` markers and a collapsed `N-M:` summary row (only boundary lines N and M shown) hide their interior. NEVER place or span a hunk inside one — `read` the range first.
32
29
  - Never start or end a range mid-expression or mid-block.
33
30
  - Indent body rows exactly for the depth they should live at.
34
31
  - On a stale-tag rejection or any surprising result: STOP and re-`read` before further edits.
35
- - One hunk per range; the body is the final content, never an old/new pair.
32
+ - One hunk per range; body = final content, never an old/new pair.
36
33
  - Ranges cover ONLY lines whose content changes. Never widen over unchanged lines — a stale wide range shreds everything it spans.
37
34
  - Whole construct → `SWAP.BLK N` (tree-sitter resolves the end); lines inside it → `SWAP N.=M`.
38
35
  - `SWAP.BLK N` resolves EXACTLY the node at N. Leading decorators/attributes/doc-comments are separate nodes: point N at the FIRST decorator to sweep both; standalone line-comments are never swept — use `SWAP N.=M`.
39
- - Block ops (`SWAP.BLK`/`DEL.BLK`/`INS.BLK.POST`) anchor the OPENING line of a MULTI-LINE construct — never its closer, its last line, or a bare statement inside it. Anchoring a single statement resolves to ONE line and is REJECTED: use the plain op (`SWAP N.=N` / `DEL N` / `INS.POST N`) for one line, or point N at the real opener. Saw the closer? Use plain `INS.POST M:`.
36
+ - Block ops (`SWAP.BLK`/`DEL.BLK`/`INS.BLK.POST`) anchor the OPENING line of a MULTI-LINE construct — never its closer, last line, or a bare inner statement. Anchoring one statement resolves to ONE line and is REJECTED: use the plain op (`SWAP N.=N` / `DEL N` / `INS.POST N`), or point N at the real opener. Saw the closer? Use plain `INS.POST M:`.
40
37
  - Non-adjacent changes = separate hunks; untouched lines stay out of every range.
41
- - Pure additions use `INS.PRE` / `INS.POST` / `INS.HEAD` / `INS.TAIL`, never a widened `SWAP` — retyped keepers are exactly what gets dropped. A multi-line `SWAP` whose body restates the line just outside the range is auto-dropped as an off-by-one keeper (with a warning), but issue the payload as the final content for the range only and never lean on the repair.
38
+ - Pure additions use `INS.PRE` / `INS.POST` / `INS.HEAD` / `INS.TAIL`, never a widened `SWAP` — retyped keepers are exactly what gets dropped. (A multi-line `SWAP` whose body restates the line just past the range is auto-dropped as an off-by-one keeper with a warning issue the payload for the range only; never lean on the repair.)
42
39
  - NEVER format/restyle code with this tool; run the project formatter instead.
43
40
  </rules>
44
41
 
@@ -90,7 +87,7 @@ SWAP.BLK 1:
90
87
  + print(f"Hello, {name}")
91
88
  ```
92
89
 
93
- A decorator or doc-comment is a SEPARATE block — `SWAP.BLK` on the `def`/`fn` line keeps it. Point N at the decorator to take both; here line 1 is `@cache`, so anchoring on the `def` (line 2) would resolve only the function and orphan `@cache`:
90
+ A decorator/doc-comment is a SEPARATE block — `SWAP.BLK` on the `def`/`fn` line keeps it. Point N at the decorator to take both; here line 1 is `@cache`, so anchoring on the `def` (line 2) would orphan `@cache`:
94
91
  ```
95
92
  [svc.py#C3D4]
96
93
  SWAP.BLK 1:
@@ -117,8 +114,8 @@ SWAP 3.=3:
117
114
  SWAP 3.=3:
118
115
  + return msg
119
116
 
120
- # WRONG — a pure insertion done as a widened `SWAP`: you only want to add one line after 2,
121
- # but you replace 2.=4, retype the keepers in the body, and drop one (here line 4, `greet("world")`).
117
+ # WRONG — a pure insertion done as a widened `SWAP`: you want to add one line after 2,
118
+ # but you replace 2.=4, retype the keepers, and drop one (here line 4, `greet("world")`).
122
119
  SWAP 2.=4:
123
120
  + msg = "Hello, " + name
124
121
  + extra = compute(name)