{"record":{"id":"01d45e55a9734910","repo":"can1357/oh-my-pi","slug":"operation-operationnumber-has-selection-markers","errorCode":null,"errorMessage":"Operation ${operationNumber} has selection markers in REWRITE; PATTERN is current text, REWRITE is final text.","messagePattern":"Operation (.+?) has selection markers in REWRITE; PATTERN is current text, REWRITE is final text\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/edit/sloppy.ts","lineNumber":2624,"sourceCode":"\t\t\t.split(\"\\n\")\n\t\t\t.map(line => line.trim()),\n\t);\n\tfor (let forward = 0; forward < 12 && forward < after.length; forward++) {\n\t\tconst line = after[forward];\n\t\tif (!usable(line)) continue;\n\t\tif (othersAfter.every(lines => !lines.includes(line))) return { side: \"after\", line };\n\t}\n\treturn undefined;\n}\n\nfunction renderRewrite(\n\trewrite: string,\n\tselectedCaptureIndices: number[],\n\tcaptures: string[],\n\toperationNumber: number,\n): string {\n\tif (rewrite.includes(SELECT_OPEN) || rewrite.includes(SELECT_CLOSE)) {\n\t\tthrow new Error(\n\t\t\t`Operation ${operationNumber} has selection markers in REWRITE; PATTERN is current text, REWRITE is final text.`,\n\t\t);\n\t}\n\tconst sentinels = selectedCaptureIndices.map((_, index) => `\\u0000V8GAP${index}\\u0000`);\n\tlet markerIndex = 0;\n\tlet marked = \"\";\n\tfor (let index = 0; index < rewrite.length; ) {\n\t\tconst gapMarker = rewrite.startsWith(GAP, index) ? GAP : undefined;\n\t\tif (gapMarker) {\n\t\t\tconst lineStart = rewrite.lastIndexOf(\"\\n\", index - 1) + 1;\n\t\t\tconst nextNewline = rewrite.indexOf(\"\\n\", index);\n\t\t\tconst lineEnd = nextNewline === -1 ? rewrite.length : nextNewline;\n\t\t\tconst line = rewrite.slice(lineStart, lineEnd);\n\t\t\tif (markerIndex >= sentinels.length) {\n\t\t\t\t// An unclaimed gap alone on its line is context elision, never final\n\t\t\t\t// text; writing it verbatim splices a literal `…` into the file.\n\t\t\t\tif (line.trim() === GAP) {\n\t\t\t\t\tthrow new Error(","sourceCodeStart":2606,"sourceCodeEnd":2642,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/edit/sloppy.ts#L2606-L2642","documentation":"The sloppy edit DSL validates each operation's REWRITE block before applying it. Selection markers (the SELECT_OPEN/SELECT_CLOSE delimiters used in PATTERN to mark selected spans) are not valid in REWRITE, because PATTERN describes the current file text and REWRITE is the final replacement text written verbatim. The library throws this in renderRewrite to stop the user from leaking pattern-only syntax into the output file.","triggerScenarios":"Calling the sloppy apply path with an operation whose REWRITE block contains the selection open/close markers (copied from PATTERN instead of retyped), e.g. pasting the whole PATTERN block as REWRITE unchanged.","commonSituations":"Authors copy the PATTERN block as a starting point for REWRITE and forget to delete the selection markers; generation pipelines that template REWRITE from PATTERN; hand-edited payloads where the marker alphabet is easy to confuse with ordinary text.","solutions":["Remove the selection markers from the REWRITE block; REWRITE must contain only final text.","Rebuild REWRITE by typing the intended final lines rather than copying PATTERN.","Verify the marker alphabet in docs (markers are re-skinned per variant) and ensure REWRITE contains none of them."],"exampleFix":"// before\n» 1\n<sel>const x = 1</sel>\n====\n<sel>const x = 2</sel>\n\n// after\n» 1\n<sel>const x = 1</sel>\n====\nconst x = 2","handlingStrategy":"validation","validationCode":"const SELECT_OPEN = \"<sel>\"; const SELECT_CLOSE = \"</sel>\";\nfunction assertNoSelectionMarkers(operation: { rewriteText: string; n: number }) {\n  if (operation.rewriteText.includes(SELECT_OPEN) || operation.rewriteText.includes(SELECT_CLOSE)) {\n    throw new Error(`Operation ${operation.n}: REWRITE must not contain selection markers`);\n  }\n}","typeGuard":"const hasSelectionMarkers = (s: string, open: string, close: string): boolean =>\n  s.includes(open) || s.includes(close);","tryCatchPattern":"try {\n  applySloppyEdit(payload);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"selection markers in REWRITE\")) {\n    payload = stripSelectionMarkersFromRewrites(payload);\n    applySloppyEdit(payload);\n  } else throw err;\n}","preventionTips":["Never copy the PATTERN block verbatim as REWRITE; type final text instead","Run a lint/regex check for selection-marker tokens in REWRITE blocks before submitting","Keep PATTERN (current text) and REWRITE (final text) in separate buffers/templates"],"tags":["edit-dsl","input-validation","rewrite-syntax"],"backgroundTag":"invalid-edit-payload","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}