- Migrated test mocking from bun:test mock API to vitest spyOn pattern across 9 test files.
- Extracted mock setup logic into reusable helper functions with Symbol.dispose cleanup pattern.
- Replaced manual beforeEach/afterEach and try-finally blocks with TypeScript 5.2 using declarations.
- Removed 178 lines of boilerplate mock initialization and restoration code from test suite.
- Renamed hashline operation types for clarity: append->append_at, prepend->prepend_at, append_eof->append_file, prepend_bof->prepend_file.
- Updated all operation type references in patch implementation, tests, and documentation to reflect new naming convention.
- Restructured hashline tool documentation with hierarchical sections and simplified examples for improved clarity.
- Consolidated validation rules and added explicit warning about invalid anchors and operation/field combinations.
- Added autoresearch extension with autonomous experiment loop supporting init, run, and log experiment tools for metric-driven optimization.
- Added widget placement system enabling extensions to position UI components above or below the editor via ExtensionWidgetOptions.
- Added dashboard controller with interactive overlay for viewing experiment results, metrics, and progress with keyboard navigation.
- Removed auto-correction logic for off-by-one range edits in hashline editor to preserve user intent in patch operations.
- Added state reconstruction utilities to parse autoresearch.jsonl logs and rebuild experiment state across sessions.
- Added comprehensive type definitions and helper utilities for metric parsing, ASI validation, and process management.
- Changed bash interceptor configuration from boolean flags to customizable pattern-based rules array.
- Clarified hashline range replace semantics: end parameter is now strictly exclusive boundary.
- Fixed bash interceptor to apply built-in default rules when no custom patterns are configured.
- Updated hashline range validation and calculations to enforce exclusive end semantics throughout.
- Added auto-reconnect capability for MCP servers with SSE stream monitoring and exponential retry backoff.
- Added tool-level reconnect handling for retriable connection errors (ECONNREFUSED, ECONNRESET, 404/502/503).
- Added `/mcp reconnect <name>` command for manual MCP server recovery.
- Improved reconnect robustness by aborting retries when MCP configuration changes via epoch checking.
- Extended transport reconnect handling to all transport types (stdio, HTTP/SSE) with unified onClose logic.
- Added comprehensive test coverage for MCPManager reconnect behavior and tool-level abort propagation.
- Added line hashes to compact diff preview for unchanged and added lines to enable integrity verification.
- Modified compact diff preview to track line number synchronization between old and new files when processing insertions and deletions.
- Fixed line number parsing in compact diff preview to handle variable-width line number fields with leading whitespace.
- Extracted parsing and formatting logic into dedicated functions (parseNumberedDiffLine, formatCompactHashlineLine, syncOldLineCounters, syncNewLineCounters) for maintainability.
- Updated 4 test cases to verify line hash generation, line number synchronization, and handling of variable-width fields.
- Fixed line normalization to trim trailing whitespace and strip carriage returns instead of removing all whitespace.
- Fixed no-op detection to check array length equality before comparing lines, preventing false classification of multi-line expansions.
- Added clarification to hashline tool documentation on `replace` operation semantics and `lines` boundary constraints.
- Added test case validating single-line to multi-line expansion behavior and firstChangedLine calculation.
* fix(patch): HASHLINE_PREFIX_RE strips comment lines with word: pattern
The regex used [0-9a-zA-Z]{1,16} for the hash ID segment, which matched
common comment patterns like '# Note:', '# TODO:', '# FIXME:'. When a
single-line replacement contained such a comment, nonEmpty===1 and
hashPrefixCount===1, triggering stripping and eating the comment prefix.
Actual hashline IDs are always exactly 2 chars from ZPMQVRWSNKTXJBYH.
Constrain the regex to that exact alphabet so no English word can match.
Also update tests that used fake IDs (AB, CD, EF) not in the real alphabet.
* test(patch): add regression tests for comment line prefix stripping bug
Three new tests in hashlineParseContent describe block:
- hashlineParseText preserves '# Word:' comment lines (unit)
- full pipeline: replacing '# Note:' comment line preserves prefix
- full pipeline: replacing '# TODO:' comment line preserves prefix
These would have caught the HASHLINE_PREFIX_RE bug where [0-9a-zA-Z]{1,16}
matched comment words, causing stripNewLinePrefixes to eat the '# Note:'
prefix when a single comment line was the sole replacement entry.
---------
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
- Extracted fetch mocking logic into reusable `hookFetch()` utility function with middleware-style handler pattern.
- Replaced manual `globalThis.fetch` assignment and restoration across 10 test files with `hookFetch()` calls using `using` statement for automatic cleanup.
- Implemented Disposable pattern with Symbol.dispose for fetch hook resource management, eliminating try-finally blocks.
- Exported `hookFetch` from utils public API to enable consistent fetch mocking across packages.
- Added incremental history mode to OpenAI responses .
- Changed OpenAI Codex to exclusively use websockets v2 protocol with fatal error detection for automatic SSE fallback.
- Fixed Gemini model parsing to strip `-preview` suffix for consistent model identification across API calls.
- Improved websocket error handling to extract and report detailed error messages from error events.
- Removed deprecated BETA_RESPONSES_WEBSOCKETS constant and websocket v2 feature flag branching logic.
- Added serviceTier option to OpenAI providers for controlling processing priority and cost across agent, completions, responses, and codex APIs.
- Added providerPayload field to messages for transport-native history reconstruction in OpenAI Responses and Codex APIs.
- Added /fast slash command and serviceTier setting to coding-agent for toggling OpenAI priority mode with fast mode indicator.
- Added remote compaction support with encrypted reasoning preservation for OpenAI models in coding-agent.
- Removed usage caching layer across all providers and refactored UsageFetchContext to eliminate cache and now dependencies.
- Fixed OpenAI Codex streaming service_tier inclusion, provider retry logic with exponential backoff, and email-based credential deduplication.
- Added auto-correction logic for off-by-one range start errors in hashline edits.
- Added safety check to prevent false-positive auto-correction when position already includes boundary.
- Added test coverage for off-by-one range correction and duplicate leading line handling.
- Extracted turn-aborted-guidance prompt to external markdown file for better maintainability.
- Added buildCompactHashlineDiffPreview() function to generate collapsed diff previews for tool responses.
- Enhanced EditTool response to include diff summary with added/removed line counts and compact preview.
- Added project-level discovery for .agent/ and .agents/ directories walking up to repository root.
- Implemented helper functions for truncating long diff runs (collapseFromStart, collapseFromEnd, collapseFromMiddle).
- Refactored hlineref Handlebars helper to return JSON-quoted strings for safer JSON embedding in prompts.
- Improved hashlineParseText to preserve blank lines and trailing empty strings while normalizing line endings.
- Optimized duplicate line detection in range replacements using trimmed comparison to reduce whitespace false positives.
- Added auto-correction for escaped tab indentation in edits via PI_HASHLINE_AUTOCORRECT_ESCAPED_TABS environment variable.
- Added warning detection for suspicious Unicode escape placeholder \uDDDD in edit content.
- Clarified hashline documentation that \t in JSON represents real tab characters, not literal backslash-t strings.
- Added comprehensive test coverage for escaped tab auto-correction and Unicode escape detection.
Clarify inclusive end semantics in the hashline prompt with bad/good examples.
Add range-replace duplicate-boundary auto-correction with a safety guard so correction only triggers for off-by-one ends.
Expand hashline heuristics tests to cover brace/); correction, blank-line guard, and boundary-already-in-range false-positive prevention.
- Consolidated @oh-my-pi/pi-utils subpath imports into single package root import across 100+ files.
- Moved tryParseJson utility from local web scrapers module to @oh-my-pi/pi-utils package for centralized JSON parsing.
- Renamed loadSkillsFromDir to scanSkillsFromDir and refactored skill discovery to use fs.promises.readdir instead of glob-based approach.
- Replaced custom parseJSON with tryParseJson across discovery modules for consistent error handling.
- Removed emitCustomToolSessionEvent method and cleanupSshResources function, consolidating shutdown logic into dispose method.
- Updated glob pattern construction to use GlobBuilder with literal_separator(true) for improved path handling.
DIFF_PLUS_RE matched both '+' and '-' (unified-diff markers), but '-'
is also a valid Markdown/YAML list prefix. When all replacement lines
start with '- ', the 50%-threshold heuristic in stripNewLinePrefixes
fires and strips every leading '-', corrupting list-item content.
Narrow the regex to match only '+' (added-line markers), which is the
stated intent of the docstring and the safe strip target. Removed
lines ('-') are never valid replacement content in any case.
Reproducer: passing content=["- [x] item"] as a bare string to a
set/replace op — the '-' is silently dropped, writing ' [x] item'.
Passing content as string[] bypasses stripNewLinePrefixes entirely and
was the workaround, but the root cause should be fixed.
- Consolidated truncation and output utilities from tools/truncate.ts and tools/output-utils.ts into session/streaming-output.ts with improved UTF-8 boundary handling.
- Renamed formatSize() to formatBytes() across codebase for consistency and clarity in byte-level formatting.
- Refactored OutputSink to use windowed byte truncation instead of full-buffer encoding, improving memory efficiency on large outputs.
- Migrated from Buffer to Uint8Array in web scrapers for better cross-platform compatibility and native browser support.
- Added getArtifactManager() lazy-initialization method to ToolSession for deferred artifact manager instantiation.
- Simplified API surface with wildcard exports from tools and session modules, reducing import complexity.
- Changed hashline format separator from pipe (|) to colon (:) for improved readability across all tools and output formats.
- Refactored hashline edit API with operation-based structure: renamed delete->rm, rename->mv, set->target/new_content, and added explicit op field for operation types.
- Updated hashline hash encoding from 4-character base36 to 2-character hexadecimal for more compact representation.
- Replaced anchor terminology with tags throughout hashline documentation and API for clearer semantics.
- Redesigned hashline edit API with new operation names (set, set_range, insert) and structured body parameter accepting string arrays for multiline edits.
- Changed hashline reference format from LINE:HASH to LINE#ID throughout tools and documentation for improved clarity.
- Enhanced insert operation to support optional before/after anchors enabling flexible insertion positioning and boundary echo stripping.
- Made hashline autocorrect heuristics conditional on PI_HL_AUTOCORRECT environment variable for controlled behavior.
- Added benchmark reports for claude-haiku-4-5 and GPT-5.2-Codex models demonstrating hashline edit variant performance.
- Added provider failure detection and exponential backoff retry logic to handle authentication and authorization errors in benchmark tasks.
- Implemented HashlineMismatchError behavior in coding-agent to fail on stale hash references instead of silently relocating edits.
- Simplified hashline validation by removing automatic line relocation logic and hash tracking infrastructure.
- Added benchmark report for claude-sonnet-4-6 model showing 85% task success rate with detailed failure analysis and performance metrics.
- Replaced all direct `process.cwd()` calls with `getProjectDir()` utility function across 40+ files to centralize project directory resolution logic.
- Added `getProjectDir()` and `setProjectDir()` functions to `@oh-my-pi/pi-utils/dirs` module to provide abstracted project directory management.
- Made `SessionManager.list()` method asynchronous to support asynchronous session discovery operations.
- Updated default working directory resolution throughout codebase to use `getProjectDir()` instead of `process.cwd()` for improved project directory detection.
- Extracted directory path utilities from multiple packages into a centralized '@oh-my-pi/pi-utils/dirs' module.
- Moved 30+ path helper functions (getAgentDir, getConfigRootDir, getPluginsDir, getMCPConfigPath, etc.) from scattered locations into a single shared utility module.
- Consolidated APP_NAME, CONFIG_DIR_NAME, and VERSION constants into the centralized dirs module for reuse across packages.
- Updated 70+ import statements across packages/ai, packages/coding-agent, packages/stats, and packages/tui to use the new centralized module.
- Removed local path construction logic and replaced with utility function calls for improved maintainability and consistency.
- Deleted packages/coding-agent/src/extensibility/plugins/paths.ts as its functions were moved to the centralized dirs module.
- Removed support for `.pi` configuration directory alias in favor of `.omp` across all packages.
- Updated all configuration paths and references from `.pi` to `.omp` in user and project directories.
- Refactored configuration discovery in builtin.ts to simplify directory traversal logic and remove multi-alias support.
- Simplified Python module discovery to use single directory paths instead of arrays of aliases.
- Updated debug and crash log paths from `.pi/agent/` to `.omp/agent/` in TUI package.
- Changed hashline format separator from two spaces to pipe character (|) throughout codebase for consistency.
- Simplified ollama installation checks in test files by replacing execSync with Bun.which() and inverting PI_NO_LOCAL_LLM to PI_LOCAL_LLM environment variable.
- Added early return guards in test beforeAll hooks to skip tests when required tools (ollama, magick) are unavailable.
- Added debug instrumentation to system prompt building via PI_DEBUG_STARTUP environment variable for startup performance monitoring.
- Removed prompt cache retention assertion from openai-codex streaming test.
- Changed hashline display format separator from pipe to two spaces for improved readability.
- Removed `lines` and `hashes` parameters from read tool in favor of automatic file display mode resolution.
- Added `resolveFileDisplayMode` utility to centralize file display mode configuration logic.
- Integrated file display mode settings into grep and read tools for consistent output formatting.
- Consolidated tool parameter types to use schema-derived types via Typebox `Static` utility.
- Updated parseLineRef to handle both legacy pipe-separator and new two-space hashline formats.
- Added new `replace` hashline edit operation for substring-style fuzzy text replacement without line references, with optional `all` flag for replace-all behavior.
- Added `noopEdits` array to `applyHashlineEdits` return value to report edits that produced no changes, including edit index, location, and current content for diagnostics.
- Added validation to detect and reject hashline edits using wrong-format fields (`old_text`/`new_text` from replace mode, `diff` from patch mode) with helpful error messages.
- Renamed hashline edit operation keys from `single`/`range`/`insertAfter` to `set_line`/`replace_lines`/`insert_after` for clearer semantics.
- Enhanced error messages for wrong-format hashline edits to guide users toward correct operation syntax.
- Added noopEdits array to applyHashlineEdits return type to track edits that produce no changes.
- Added validation to reject edits with wrong-format fields (old_text/new_text from replace mode, diff from patch mode) that indicate model confusion.
- Added additionalProperties tolerance to hashline edit schemas to allow flexible field handling.
- Added deduplication logic to remove duplicate edits targeting the same line(s) with identical destination content.
- Improved error handling for missing end fields in edit ranges by returning single-line specs instead of requiring both start and end.
- Enhanced no-op error recovery guidance in prompts with detailed instructions to re-read file and function context after consecutive no-op errors.
- Removed whitespace preservation logic that was overriding model-generated formatting choices in patch application.
- Deleted `preserveWhitespaceOnlyLines` and `preserveWhitespaceOnlyLinesLoose` functions that were incorrectly reverting intentional formatting changes.
- Updated test to reflect that model whitespace choices are now respected without override.
- Renamed hashline edit operation types from replaceLine/replaceLines to single/range for improved clarity.
- Renamed content field to replacement in hashline edit operations to better reflect its purpose.
- Enhanced no-op edit diagnostics to perform line-by-line comparisons and distinguish between identical and normalized replacements.
- Improved error messages for hashline edits to clarify differences between literal identical content and whitespace-normalized content.
- Removed timeout-retries configuration option from react-edit-benchmark CLI and simplified retry logic.
- Updated all test cases and documentation to reflect renamed hashline edit operation types and fields.
- Removed insertBefore and substr hashline edit operations, simplifying the edit API to support only replaceLine, replaceLines, and insertAfter operations.
- Updated hashline edit schema and type definitions to remove insertBefore and substr operation types from the ParsedRefs union and edit validation logic.
- Removed insertBefore and substr test cases from hashline test suite, including tests for insert-before functionality, anchor echo stripping, and substring matching.
- Updated benchmark runner to refactor edit operations from src/dst format to discriminated union types (replaceLine, replaceLines, insertAfter) and adjusted insertAfter line references.
- Redesigned hashline edit API to use discriminated union variants (replaceLine, replaceLines, insertAfter, insertBefore, substr) instead of nested src/dst structure.
- Changed hash algorithm from xxHash64 hex to xxHash32 base36 encoding and increased hash length from 2 to 3 characters.
- Added substr edit variant to match and replace content by unique substring when line hashes are unavailable.
- Implemented line relocation heuristics to resolve stale line references when hash uniquely identifies a moved line.
- Moved substr needle search from edit application phase to pre-validation phase for earlier error detection.
- Migrated hashline edit type definitions from manual TypeScript interfaces to schema-derived types using Static<typeof schema> pattern.
- Added `substr` source specification kind to match and replace lines by unique substring without requiring line-hash references.
- Implemented substring matching logic in hashline edits with validation for uniqueness and error handling for not-found and ambiguous cases.
- Added schema definition and type guards for the new `substr` operation type across patch system.
- Added mutation preview hints to error messages when edits fail with 'No changes made' errors, showing line numbers, hashes, and added/removed lines.
- Changed formatter to pin JavaScript fixtures to the flow parser to avoid parser-dependent formatting drift.
- Added whitespace preservation logic to treat whitespace-only differences as passing in file verification.
- Removed substring source specification kind from hashline edits, requiring users to use line-hash references instead.
- Simplified SrcSpec type to use generic type parameter for line references, removing substring variant from union.
- Updated react-edit-benchmark to use --max-tasks option for deterministic task sampling and changed default batch sizes to 1.
- Added streaming functions `streamHashLinesFromUtf8` and `streamHashLinesFromLines` for processing large files with configurable chunking.
- Added `HashlineStreamOptions` interface to control streaming behavior with `startLine`, `maxChunkLines`, and `maxChunkBytes` options.
- Changed hashline format from 4-character to 2-character hex hashes for more compact output.
- Updated `computeLineHash` function to normalize whitespace and removed line number from hash seed for consistency.
- Improved CLI argument parsing with explicit handling of `--help`, `--version`, and subcommand detection.
- Removed `@types/diff` dev dependency as it is no longer needed.
- Changed `HashlineEdit.src` from string format (e.g., `"5:ab"`, `"5:ab..9:ef"`) to structured `SrcSpec` object with discriminated union types (`{ kind: "single", ref: "..." }`, `{ kind: "range", start: "...", end: "..." }`, `{ kind: "insertAfter", after: "..." }`, `{ kind: "insertBefore", before: "..." }`, `{ kind: "substring", needle: "..." }`).
- Refactored `parseSrc` function to `parseSrcSpec` to handle structured `SrcSpec` objects instead of string parsing, replacing string validation and delimiter parsing logic with explicit case handling for each operation kind.
- Updated tool schema in `index.ts` to define `srcSpecSchema` as a discriminated union type with five variants, replacing the previous simple string-based `src` parameter definition.