Append-only History Tracking
Relevant source files
The following files were used as context for generating this wiki page:
Append-only History Tracking is a core persistence feature in PlanQueue designed to ensure that no user effort is lost during the prompt planning process. It functions by recording every change made to a session's note into a dedicated history file. This includes explicit saves from the editor, automatic updates from the prompt queue (such as marking tasks as in-flight or done), and even drafts that the user chooses to discard.
Sources: README.md:120-123, src/main.ts:258-265, CHANGELOG.md:31-31
Architecture and Storage
The history tracking system operates on a per-session basis, mirroring the primary note storage structure. History files are stored as plain Markdown siblings to the active note files within the user's home directory.
Storage Hierarchy
Files are organized by the repository name and the current git branch to maintain context isolation. The system uses the following path convention:
~/.planqueue/{repo}/{branch}/{session-id}.history.md
Sources: README.md:118-123, src/main.ts:241-244, SECURITY.md:27-29
The following diagram illustrates the relationship between the session environment, the active note, and the append-only history log.
Sources: README.md:118-123, src/main.ts:241-244
Data Flow and Triggers
History entries are generated by the persist function within the main extension logic. This function is the central gateway for all state changes to the note buffer.
Event Triggers
History is updated under three primary conditions:
- Manual Edits: When a user saves changes via the
CustomEditor(Ctrl+N or/note). - Queue State Changes: When the
queue-controllerupdates a task state (e.g., frompendingtoin-flightordone). - Discarded Drafts: If a user exits the editor with unsaved changes and chooses not to "Save", the current buffer is still appended to the history file to prevent total loss of work.
Sources: src/main.ts:161-175, src/main.ts:256-267, src/queue-controller.ts:167-171
Update Logic
The system performs a change detection check before appending. If the next content is different from the current content buffer, the appendHistory utility is invoked.
async function persist(ctx: ExtensionContext, next: string): Promise<void> {
if (notePath === undefined) return;
const changed = next !== content;
content = next;
// ... logic for debounced saving ...
if (changed && historyPath !== undefined) {
try {
await appendHistory(historyPath, content);
} catch (err) {
// Error handling for failed writes
}
}
}
Sources: src/main.ts:256-267
The sequence of a note update involving the history log is shown below:
Key Components and Functions
The history tracking relies on specific utilities and configuration paths defined in the core package and managed by the extension.
| Component | Responsibility | Source |
|---|---|---|
historyPathFor | Resolves the absolute path for the .history.md file based on session metadata. | src/main.ts:26 |
appendHistory | Performs the physical file append operation, including timestamping for discarded drafts. | src/main.ts:166, src/main.ts:262 |
applyEditorResult | Orchestrates the decision to save or discard, ensuring "discarded" flags are passed to history. | src/main.ts:153-176 |
persist | High-level function that coordinates the primary note save and the history append. | src/main.ts:256-270 |
Discarded Draft Handling
When a user closes the editor with unsaved changes (Esc), the applyEditorResult function triggers a confirmation prompt. If the user chooses not to save, the system explicitly appends the draft to history with a specific metadata flag.
if (action === "ask" && !(await ctx.ui.confirm("Unsaved notes", "Save your changes?"))) {
if (historyPath !== undefined)
await appendHistory(historyPath, result.text, new Date(), "discarded");
ctx.ui.notify("Notes discarded (kept in history)", "info");
return;
}
Sources: src/main.ts:162-170
Significance in Project Scope
The Append-only History Tracking system serves as a safety net for "Human-in-the-loop" workflows. By maintaining a non-destructive log of every version of a note, PlanQueue provides a mechanism for developers to recover accidental deletions or lost plan iterations without complex version control overhead. This is particularly relevant given that coding agents can also modify the note via tools like note_add and make_note.
Sources: README.md:120-123, CHANGELOG.md:20-31, SECURITY.md:27-31