Commit Graph

4 Commits

Author SHA1 Message Date
claude@clouddev1 d6c5674bf5 feat: ADR-0006 §8 step 6 — .snapshots/ gitignore + export + cleanup
The undo ring is local working state, handled at all three
project-file seams (R13):
- .gitignore template ignores /.snapshots/
- export excludes .snapshots/ (like playground.db / history.log)
- safely_delete_temp_project allowlists .snapshots/ so a temp that
  was modified then undone back to empty stays auto-deletable
- undo::SNAPSHOTS_DIR is now a pub const referenced by all three
- tests: gitignore content, export exclusion, cleanup allowlist

1693 passed / 0 failed / 1 ignored; clippy clean.
2026-05-24 20:53:00 +00:00
claude@clouddev1 d9a98bbd49 Grammar: with-pk column specs use name(type), matching add column
`create table … with pk` parsed column types as `name:type`,
while `add column` uses `name(type)`. Unify on the parens
form so column-type syntax is consistent across the DSL:

    create table T with pk id(serial), name(text)

Only `COL_SPEC` changes (`:` → `( … )`); `build_create_table`
reads columns by role, so it is unaffected. The `:` that
separates table from column in `add column` / `drop column`
is unchanged. Sweeps the test suite, the typing-surface
matrix (two `after_colon` cells renamed to `after_paren`,
4 snapshots regenerated), the friendly catalog's usage
templates, ADR-0009's example, and requirements.md.

1039 passing / 0 failing / 1 ignored; clippy clean.
2026-05-18 21:51:52 +00:00
claude@clouddev1 6ca297579e round-5 follow-up r2: migrate all thiserror Display attributes to catalog
Completes the i18n sweep started in the previous commit. All
remaining hand-rolled user-facing English strings inside
thiserror #[error(...)] attributes have been moved into the
catalog. Drops the thiserror dependency entirely.

Twelve error types migrated:

- dsl::action::UnknownAction         → parse.custom.unknown_action
- dsl::parser::ParseError            → parse.error_wrapper + parse.empty
- dsl::value::ValueError             → value.{type_mismatch,format}
- persistence::csv_io::CsvError      → persistence.csv.*
- persistence::mod::PersistenceError → persistence.{io,encode}
- persistence::yaml::YamlError       → persistence.yaml.*
- persistence::migrations::MigrateError → persistence.migrate.*
- project::lock::LockError           → project.lock.*
- project::naming::NamingError       → project.naming.*
- project::naming::UserNameError     → project.user_name.*
- project::mod::ProjectError         → project.{path_not_found,...}
- project::mod::SafeDeleteError      → project.safe_delete.*
- archive::ArchiveError              → archive.*
- cli::ArgsError                     → cli.*
- db::DbError                        → db.error.*

Pattern per type: drop thiserror::Error derive, write manual
Display calling crate::t!(), keep #[from] semantics via
explicit From impls, override Error::source() where applicable
so #[source]-style chaining is preserved.

Why this matters (user rationale): "fine to have fallbacks for
errors that are purely technical, but lift the output to a
place where it can be localized later and where an adjustment
with friendly text is easily possible if any of them become
part of the happy path." All surface strings now live in
en-US.yaml and can be reworded or localized without touching
Rust source.

Tests: 769 passing, 0 failed, 1 ignored. Clippy clean with
-D warnings. Cargo.toml: drop thiserror = "2.0.18".
2026-05-13 21:24:51 +00:00
claude@clouddev1 c6cf3df6dc Iteration 5: export / import commands
Implements the `export` and `import` app-level commands per
ADR-0015 §11 + ADR-0007 amendment 1.

- `export [<path>]` writes a zip of project.yaml + data/ to
  <data-root>/YYYYMMDD-<projectname>-export-NN.zip by default,
  preserving the project's directory name as the single
  top-level folder inside the archive.
- `import <zip> [as <target>]` extracts an exported zip into
  a new named project and switches to it. Target name is
  derived from the zip's top-level folder by default; on
  collision the destination auto-suffixes -02, -03, ... up
  to -99 instead of refusing (deviates from §2's refuse-on-
  collision rule for save/save as; recorded as an amendment
  to ADR-0015 §11).
- Excludes playground.db and history.log from the zip.
- Path-traversal protection via zip::enclosed_name + post-
  resolution check that the extraction path stays inside
  the target directory.

Adds the zip = "5" dep with default-features = false +
features = ["deflate"] to keep the binary-size cost modest.

Test baseline: 370 passing, 0 failing, 0 skipped.
2026-05-08 08:24:45 +00:00