Commit Graph

8 Commits

Author SHA1 Message Date
wassname b03651855d fix: revert to XML dcp-id tags and add strip-before-inject to prevent echo loop
HTML comment format offered no benefit over XML tags since LLMs see raw
text, not rendered output. Revert to original <dcp-id>m001</dcp-id> and
<dcp-block-id>bN</dcp-block-id> format which is more token-efficient.

Add strip-before-inject in injectMessageIds: each context event strips any
existing dcp-id tags before appending the fresh one. For clean messages
this is idempotent (no cache bust). For model-echoed tags it removes the
duplicate on the next context event, breaking the accumulation loop that
reinforced echoing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 13:59:46 +08:00
wassname b83b3f8c53 fix: use HTML comment format for dcp-id tags to prevent model echo
XML-style <dcp-id>m001</dcp-id> tags get echoed by models because they
look like semantic content. HTML comments <!-- dcp-id: m001 --> are
invisible in rendered markdown and models are trained to skip them.
2026-04-16 15:39:24 +08:00
wassname a0d9945830 fix: prevent Infinity anchorTimestamp ghost block spiral
The root cause of the compression spiral (101 failures, 2 hours):
resolveAnchorTimestamp returned Infinity when no message followed the
compression range. Infinity corrupted JSON serialization (became null),
and null timestamps in JS overlap checks coerced to 0, making every
range appear to overlap the ghost block b7.

Fixes:
- resolveAnchorTimestamp returns endTimestamp + 1 instead of Infinity
- Validate all timestamps are finite before creating a block (fail fast)
- Skip blocks with non-finite timestamps in overlap checks and compression
- Include existing block range in overlap error messages (diagnostic)
- Filter out corrupted blocks on session restore
- Guard synthetic message timestamp creation against non-finite values
- Add regression tests for Infinity anchor and null-timestamp blocks
2026-04-10 20:28:22 +00:00
Greg Harvell 8681bd833b fix: prevent orphaned tool_use/tool_result after compression with passthrough roles
Backward and forward expansion now skip PI-internal passthrough roles
(compaction, branch_summary, custom_message) when scanning for paired
assistant↔toolResult messages, ensuring atomic removal. Added a
post-compression repair safety net and deep-cloning to prevent content
mutation across context events.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 20:03:27 -04:00
Greg Harvell 24cf4e5b80 Bugfix for tool crash on compression 2026-03-30 17:30:53 -04:00
Greg Harvell e62d04dfe8 Fixing some errors and issues 2026-03-27 19:38:35 -04:00
Greg Harvell e4b4d13ac7 fix: prevent orphaned tool_use blocks from compression and harden autocomplete
Bug 1 (400 API error): applyCompressionBlocks could remove toolResult
messages while leaving their paired assistant(tool_use) message intact.
This produced invalid API sequences that Claude rejected with:
  messages.N: tool_use ids found without tool_result blocks immediately after

The fix adds two boundary expansions before the splice:
- Expand lo backward: if messages[lo-1] is an assistant whose toolCall
  ids appear as toolResult.toolCallId values inside [lo..hi], pull the
  assistant into the range
- Expand hi forward: for assistants inside [lo..hi], extend hi to include
  any consecutive toolResult messages that immediately follow hi

This ensures tool_use/tool_result pairs are always removed together.

Bug 2 (autocomplete crash): harden getArgumentCompletions to return an
explicitly typed AutocompleteItem[] | null, filter on value (not label,
matching pi-tui's internal contract), and add a typeof guard ensuring no
item with a non-string value can reach getBestAutocompleteMatchIndex.
2026-03-27 18:50:56 -04:00
Greg Harvell 60b4249501 Initial Commit 2026-03-27 17:47:33 -04:00