Removing accidentally commited files

This commit is contained in:
2026-07-23 17:02:35 -05:00
parent 815eeeec44
commit 9fe510f00d
2 changed files with 0 additions and 212 deletions
-7
View File
@@ -1,7 +0,0 @@
[169] Merge origin/master into current branch
Blocks: [93]
Depends on: []
Is Blocked: false
Type: [TASK] [hal9000-worker]
Status: closed
-205
View File
@@ -1,205 +0,0 @@
[93] # History Editing Feature
Blocks: [94]
Depends on: [169]
Is Blocked: false
Type: [DOCS] [darthrubik]
Status: open
## Problem Statement
When working with an AI agent through drharness, conversations can go off track. The AI might make a mistake early in the conversation that cascades into later errors, or a user might want to try a different approach from a certain point. Currently, the only option is to start a completely new conversation, losing all the context and work that came before the mistake. Users need a way to surgically edit their conversation history—rewinding to a specific point, modifying messages, or removing problematic exchanges—without starting over.
## Solution
Add an interactive history editing mode (invoked via `-b` flag) that presents the full conversation in a git rebase-style editor. Users can mark messages to keep (`pick`), modify (`edit`), or delete (`drop`). After saving, the modified history is persisted, allowing the user to continue the conversation from their edited state. This gives users precise control over their conversation history, enabling them to correct mistakes, try alternate paths, and clean up their conversation.
## User Stories
1. As a user, I want to invoke history editing mode via a CLI flag, so that I can edit my conversation when needed
2. As a user, I want to see all messages in my conversation listed in order, so that I can identify which ones to modify
3. As a user, I want to keep messages unchanged by marking them as `pick`, so that I preserve the parts of my conversation that are correct
4. As a user, I want to delete messages by marking them as `drop`, so that I can remove problematic exchanges from my history
5. As a user, I want to delete messages by removing their line entirely, so that I have a quick way to drop messages without typing a command
6. As a user, I want to edit message content by marking it as `edit`, so that I can fix mistakes or rephrase messages
7. As a user, I want to see the previous message as context when editing, so that I understand what I'm responding to
8. As a user, I want to change the role of a message (user/assistant/tool), so that I can correct misattributed messages or restructure my conversation
9. As a user, I want to see only the first line of each message in the rebase view, so that the editor remains scannable for long conversations
10. As a user, I want to see tool calls displayed as `[tool_call: function_name]`, so that I can identify assistant messages that invoked tools
11. As a user, I want to be warned with clear error messages if I make a syntax error, so that I can fix my mistakes and retry
12. As a user, I want the editor to reject invalid roles, so that I don't accidentally create messages the API won't understand
13. As a user, I want the editor to reject out-of-range indices, so that I don't accidentally reference non-existent messages
14. As a user, I want edits processed in forward order (lowest index first), so that the editing flow matches how I read the conversation
15. As a user, I want the modified history saved to my chat file after editing, so that my changes persist
16. As a user, I want the program to exit after saving, so that I can inspect the result or continue the conversation on my terms
17. As a user, I want to edit the first message in my conversation even though there's no previous message for context, so that I can fix my initial prompt
18. As a user, I want to edit multiple messages in one session, so that I can make sweeping changes efficiently
19. As a user, I want my message content preserved when I only change the role, so that I don't lose the actual text
20. As a user, I want tool result messages to display their content preview, so that I can identify which tool results to keep or drop
21. As a user, I want empty messages to display as `(empty)`, so that I can identify and handle messages with no content
22. As a user, I want to be able to create orphaned messages by dropping a tool call without dropping its result, so that I have maximum flexibility in restructuring my conversation
23. As a user, I want comments in the rebase editor to explain the format, so that I can reference the syntax while editing
24. As a user, I want the history editor to require an existing chat file, so that I don't accidentally try to edit nothing
25. As a user, I want to see my reasoning and tool_call fields preserved when I edit content, so that I don't lose metadata by editing the text
26. As a developer, I want parsing errors aggregated and reported together, so that I can fix multiple issues in one pass
27. As a developer, I want the rebase parsing logic to be testable in isolation, so that I can verify correctness without invoking the editor
28. As a developer, I want message formatting to be testable in isolation, so that I can verify display rules for edge cases like tool calls and empty content
29. As a developer, I want integration tests that verify the full edit flow, so that I catch issues in the interaction between modules
30. As a developer, I want to mock the editor in tests using pre-staged input files, so that tests are deterministic and easy to write
## Implementation Decisions
### Modules
**RebaseEngine**: Deep module encapsulating all rebase file parsing, validation, and history transformation logic. Provides a stable interface `parse_rebase_file(content)` returning parsed commands with aggregated errors, and `apply_rebase(lines, history)` returning the transformed history. This module is pure logic with no I/O, making it highly testable.
**HistoryEditor**: Deep module encapsulating message formatting, editor interaction, and orchestration. Provides `edit_history_interactive(history)` as the main entry point, plus formatting helpers `build_rebase_content(history)` and `build_edit_prompt(history, edit_index, role)`. Handles the `>8` separator pattern consistent with the existing editor infrastructure.
### Rebase File Format
Each non-comment line follows: `<command> <index> [<role>] <display_content>`
- Command: `pick`, `edit`, or `drop` (case-sensitive)
- Index: 0-based message index
- Role: `[user]`, `[assistant]`, or `[tool]` (editable, strictly validated)
- Display content: first line of message content (truncated silently, display-only)
Lines starting with `#` are comments and ignored. Empty lines are treated as drops.
### Edit Flow
1. Load history from chat file
2. Build rebase content and spawn editor
3. Parse user's edits, validate strictly (abort on any error)
4. For each `edit` command (forward order): build edit prompt with previous message context, spawn editor, capture new content
5. Apply all changes: pick (keep), drop (remove), edit (update content and/or role)
6. Save modified history to chat file
7. Exit
### Context for Edits
When editing message N, the prompt shows only the immediate previous message (N-1) as context, followed by the `>8` separator, then the editable content. For message 0, shows `(no previous message)` instead. This balances context with brevity.
### Editable Fields
Only `content` is editable via the content editor. `role` is editable via the rebase line. All other fields (`reasoning`, `reasoning_content`, `tool_calls`, `tool_call_id`) are preserved as-is during edits. This keeps the interface simple while covering the most common edit scenarios.
### Error Handling
Strict validation mode: any parsing error (invalid command, out-of-range index, duplicate index, missing/malformed role, invalid role value) causes immediate abort with aggregated error messages. No partial application of edits. This prevents accidental history corruption.
### Tool Call Handling
Lenient mode: dropping a message with tool_calls does not automatically drop the corresponding tool result messages. Users have full power to create inconsistent histories if desired. This prioritizes flexibility over safety; validation can be added later if it proves problematic.
### CLI Integration
New flag `-b` / `--edit-history` added to main.cpp argument parsing. Requires `-F` to be specified (editing requires an existing chat file). Loads history, invokes HistoryEditor, saves result, exits. No continuation after edit (user re-invokes drharness to continue).
### Data Structures
```cpp
enum class RebaseCommand { Pick, Edit, Drop };
struct RebaseLine {
RebaseCommand command;
size_t index;
std::string role;
};
```
## Testing Decisions
### Testing Philosophy
Test external behavior, not implementation details. For deep modules (RebaseEngine, HistoryEditor formatting), test the public interfaces with various inputs and verify outputs. For integration, test the full flow using mock editors with pre-staged input files.
### Modules Under Test
**RebaseEngine** (unit tests):
- Parsing valid rebase files (all commands, mixed commands)
- Parsing edge cases (comments, empty lines, whitespace)
- Validation errors (invalid commands, out-of-range indices, duplicate indices, invalid roles)
- Application logic (pick keeps, drop removes, edit updates)
- Role changes during edit
- Empty history edge case
**HistoryEditor** (unit tests for formatting):
- Message formatting for rebase display
- First-line truncation for multi-line content
- Tool call display format `[tool_call: name]`
- Empty content display `(empty)`
- Edit prompt building with previous message context
- Edit prompt for message 0 (no context)
**Integration tests** (full flow via mock editor):
- Pick all messages (history unchanged)
- Drop a single message
- Edit message content
- Change message role
- Delete line equals drop
- Edit first message (no context)
- Empty history rejected
- Invalid command error
- Invalid index error
- Invalid role error
- Multiple edits in one session
- Edit then continue conversation normally
### Prior Art
Follows the existing test pattern in `tests/test_editor.sh` using `mock_editor.sh` with environment variables and pre-staged input files. Extends the mock editor with invocation counting (`$TEST_TEMP_DIR/.editor_invocation_count`) and staged input files (`$TEST_TEMP_DIR/.editor_input_N`).
### Mock Editor Extension
The mock editor will be extended to support sequential invocations:
- Invocation 0: rebase editor (copies from `.editor_input_0`)
- Invocation 1+: content editors (copy from `.editor_input_1`, `.editor_input_2`, etc.)
This allows tests to pre-stage exactly what the "user" types for each editor invocation.
## Out of Scope
- Branching/forking conversation history into alternate timelines
- Undo/redo of edits within the editor session
- Inline editing of multiple fields (reasoning, tool_calls) beyond content and role
- Automatic cascade deletion of orphaned tool results
- Visual diff of changes before saving
- Continuation of conversation immediately after editing (save-and-exit only)
- GUI or web-based history editing
- History editing for agent sub-conversations
- Searching/filtering messages in the rebase view
- Builtin "reverse" command to swap user/assistant roles
- Dry-run mode to preview changes before saving
## Further Notes
The `-b` flag was chosen to match git rebase terminology (`git rebase -i`), making the feature intuitive for developers familiar with git. The lenient tool call handling prioritizes user flexibility; if orphaned messages prove problematic in practice, strict cascade deletion or warnings can be added in a follow-up. The save-and-exit post-edit behavior keeps the initial implementation simple; a `--continue` flag for immediate continuation can be added later based on user feedback.