pi-hashline-edit-pro 0.6.0 → 0.6.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-hashline-edit-pro",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Strict hashline read/replace tool for pi-coding-agent with hash-anchored edits (4-char, 24-bit)",
5
5
  "main": "index.ts",
6
6
  "repository": {
@@ -57,6 +57,7 @@ Rules:
57
57
  - Copy anchors from the most recent `read` of the file. Do not guess or construct them.
58
58
  - All edits in one call must be non-conflicting. The runtime rejects with `[E_EDIT_CONFLICT]` if two ranges overlap.
59
59
  - If `lines` matches current content, the replace is classified as `noop` (file unchanged).
60
+ - The `start`/`end` range is inclusive — both anchors and every line between them are replaced. If your replacement content includes lines that already exist in the file (e.g. closing brackets), make sure those lines are within your range, otherwise they will appear twice.
60
61
 
61
62
  On success, the response contains an `--- Anchors ---` block with fresh HASH anchors for the changed region. Use those for nearby follow-up replaces instead of re-reading.
62
63
 
@@ -220,7 +220,6 @@ export function applyHashlineEdits(
220
220
  edits: import("./resolve").HashlineEdit[],
221
221
  signal?: AbortSignal,
222
222
  precomputedHashes?: string[],
223
- filePath?: string,
224
223
  ): {
225
224
  content: string;
226
225
  firstChangedLine: number | undefined;
@@ -262,7 +261,7 @@ export function applyHashlineEdits(
262
261
  );
263
262
  }
264
263
 
265
- const barePrefixWarnings = assertNoBareHashPrefixLines(edits, lineIndex.fileLines, fileHashes, filePath);
264
+ const barePrefixWarnings = assertNoBareHashPrefixLines(edits, lineIndex.fileLines, fileHashes);
266
265
  warnings.push(...barePrefixWarnings);
267
266
  maybeWarnSuspiciousUnicodeEscapePlaceholder(edits, warnings);
268
267
 
@@ -78,15 +78,15 @@ export function formatMismatchError(
78
78
 
79
79
  if (notFound.length > 0) {
80
80
  const refList = notFound.map((m) => `"${m.ref.hash}"`).join(", ");
81
- out.push(
82
- `[E_STALE_ANCHOR] ${notFound.length} stale anchor${notFound.length > 1 ? "s" : ""}: ${refList}. Re-read the file to refresh.`
83
- );
81
+ out.push(
82
+ `[E_STALE_ANCHOR] ${notFound.length} stale anchor${notFound.length > 1 ? "s" : ""}: ${refList}. Call read() to get fresh anchors, then copy the 4-character HASH from each line into your next replace call.`
83
+ );
84
84
  }
85
85
  if (ambiguous.length > 0) {
86
86
  if (out.length > 0) out.push("");
87
- out.push(
88
- `[E_AMBIGUOUS_ANCHOR] ${ambiguous.length} ambiguous anchor${ambiguous.length > 1 ? "s" : ""}. Re-read the file to refresh.`
89
- );
87
+ out.push(
88
+ `[E_AMBIGUOUS_ANCHOR] ${ambiguous.length} ambiguous anchor${ambiguous.length > 1 ? "s" : ""}. Call read() to get fresh anchors, then copy the 4-character HASH from each line into your next replace call.`
89
+ );
90
90
  for (const m of ambiguous) {
91
91
  const sample = (m.candidates ?? []).slice(0, 5);
92
92
  const more =
@@ -105,15 +105,6 @@ export function formatMismatchError(
105
105
  }
106
106
  }
107
107
 
108
- out.push("");
109
- out.push("Current state (first lines):");
110
- const sampleSize = Math.min(fileLines.length, 5);
111
- for (let i = 0; i < sampleSize; i++) {
112
- out.push(`>>> ${fileHashes[i]}│${fileLines[i]}`);
113
- }
114
- if (fileLines.length > sampleSize) {
115
- out.push(`... ${fileLines.length - sampleSize} more.`);
116
- }
117
108
 
118
109
  return out.join("\n");
119
110
  }
@@ -198,7 +189,6 @@ export function assertNoBareHashPrefixLines(
198
189
  edits: HashlineEdit[],
199
190
  fileLines: string[],
200
191
  fileHashes: string[],
201
- filePath?: string,
202
192
  ): string[] {
203
193
  if (fileHashes.length !== fileLines.length) {
204
194
  throw new Error(
@@ -216,18 +206,11 @@ export function assertNoBareHashPrefixLines(
216
206
  }
217
207
  if (suspects.length === 0) return [];
218
208
 
219
- const isPython = filePath?.endsWith('.py');
220
209
  const fileHashSet = new Set(fileHashes);
221
210
  const matched = suspects.filter((s) => fileHashSet.has(s.hash));
222
211
  const matchedCount = matched.length;
223
212
  const exampleLine = `${suspects[0]!.hash}│${suspects[0]!.line}`;
224
213
 
225
- if (isPython) {
226
- const hint = matchedCount > 0
227
- ? `${matchedCount} prefix(es) match file line hashes.`
228
- : `None match file line hashes — likely Python syntax.`;
229
- return [`[W_BARE_HASH_PREFIX] ${suspects.length} edit line(s) start with a hash-like prefix (e.g. ${JSON.stringify(exampleLine)}). ${hint}`];
230
- }
231
214
 
232
215
  const linesHint =
233
216
  matchedCount === 0
package/src/replace.ts CHANGED
@@ -368,7 +368,6 @@ async function executeEditPipeline(
368
368
  resolved,
369
369
  signal,
370
370
  originalHashes,
371
- absolutePath,
372
371
  );
373
372
 
374
373
  return {