Iteration 6: --resume + persistent input history + migration scaffold
Closes out track 2's ADR-0015 backlog. * `--resume` CLI flag (L1a, ADR-0015 §7) opens the most- recently-used project, tracked in <data-root>/last_project. Mutually exclusive with a positional <project-path>; errors cleanly to stderr (above the shell prompt) on missing file or stale recorded path. last_project is rewritten on every successful project open (startup, load, new, save as, import). * Persistent input history (I2-persist, ADR-0015 §12). On project open, the in-memory navigable history is hydrated from the tail of history.log (capped at the in-memory cap). ProjectSwitched gains a `history_entries` payload field; App::seed_history is the entry point. Pipes inside source text round-trip via splitn(3); unknown escape sequences are passed through literally. * Migration framework scaffold (F3, ADR-0015 §9). New persistence::migrations module with MigratorRegistry + migrate_to_latest + ensure_project_yaml_migrated. Empty in v1 (production registry has no migrators); the loader runs through it on every project open and is exercised by tests with a fake v1→v2 migrator. Writes project.yaml.v<N>.bak before any migrator runs; verifies each step bumps the version field. Refreshes docs/requirements.md (A1 / I2 / F3 / E1 / L1a / test baseline) and adds docs/handoff/20260508-handoff-3.md covering both Iter 5 and Iter 6. Total tests: 408 passing, 0 failing, 0 skipped (up from 345 at handoff-2). Clippy clean.
This commit is contained in:
@@ -26,6 +26,7 @@ use crate::project::{DATA_DIR, HISTORY_LOG, PROJECT_YAML};
|
||||
// during rebuild (ADR-0015 §7) are re-exported below.
|
||||
mod csv_io;
|
||||
mod history;
|
||||
pub mod migrations;
|
||||
mod yaml;
|
||||
|
||||
pub(crate) use csv_io::{decode_cell, parse_csv};
|
||||
@@ -212,6 +213,15 @@ impl Persistence {
|
||||
let line = history::format_record(command_text, history::utc_iso8601_now());
|
||||
history::append(&path, &line)
|
||||
}
|
||||
|
||||
/// Read the most-recent `max_n` sources out of
|
||||
/// `history.log` for input-history hydration on project
|
||||
/// open (ADR-0015 §12). Returned in chronological order
|
||||
/// (oldest first). A missing file is `Ok(Vec::new())`.
|
||||
pub fn read_recent_history(&self, max_n: usize) -> Result<Vec<String>, PersistenceError> {
|
||||
let path = self.project_path.join(HISTORY_LOG);
|
||||
history::read_recent_sources(&path, max_n)
|
||||
}
|
||||
}
|
||||
|
||||
/// Write `body` to `path` atomically via temp file + fsync +
|
||||
|
||||
Reference in New Issue
Block a user