feat(import): a folder of one CSV keeps its File category and view (improvise-lpzu)

The user's ruling on PR #314: a folder always merges, so even a single
CSV in it records its file identity. A CSV named directly still imports
alone. The "(none)" question is answered as no position, per the user.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
Claude (agent-lpzu)
2026-09-24 21:36:00 -07:00
committed by Edward Langley
parent 4e68372c25
commit 005b7a769a
6 changed files with 79 additions and 11 deletions
+27 -7
View File
@@ -646,10 +646,28 @@ columns not in a given CSV file." So files with different headers merge into
takes the arguments in order and replaces each folder with its `*.csv`
entries. The extension check is case-insensitive, the listing is not recursive,
and the order is `Storage::list`'s, which is sorted by contract. Then the
existing path runs unchanged: two or more files merge through `merge_csvs_from`
with a `File` category, and one file imports alone. So `import dir/` is
`import dir/*.csv`, including when the folder holds a single CSV. Four cases
follow from that equivalence rather than being chosen one by one:
existing path runs, with one difference: **a folder always merges**. Two or more
files merge through `merge_csvs_from` with a `File` category, and so does a
folder holding a single CSV. That gives the one file its `File` item and its
per-file view.
The single-CSV rule is **the user's ruling (2026-09-25)**, which replaced this
PR's first answer, "`import dir/` is exactly `import dir/*.csv`". Their words:
"yes, we might want to have some kind of update import eventually (don't plan
this yet, but we'd want file identity for this)". A folder names a collection
that may grow, so a document built from it should record which file each
record came from from the start.
**A single CSV named directly, not through a folder, still imports alone,
without `File`.** That is deliberate. Naming one file asks for that file, not
for a collection, and the shipped recipes (`examples/demo.improv` from
`examples/demo.csv`) and every existing single-file script would otherwise gain
a `File` category and a second view. File identity for update-import can be
asked for by naming a folder. The test is
`a_folder_of_one_csv_still_gets_a_file_category_and_its_view_but_a_lone_file_does_not`.
Apart from that, a folder still behaves as the glob would, and four cases follow
from that rather than being chosen one by one:
- **Non-CSV entries are skipped**, not refused, because a glob skips them. This
includes the output `.improv`, which a second run finds in the folder.
@@ -764,9 +782,11 @@ test is `a_record_with_no_coordinate_is_drawn_only_where_that_category_is_off_th
- **`.improv`:** its Data line omits the category, and it round-trips.
- **Drill:** a drill that does not constrain the category reaches it.
Whether Row/Column/Page should give such records a place of their own (a
"(none)" position) is **open, and it is the user's call**. It is raised on the
lpzu PR. Nothing here invents one.
**No "(none)" position, by the user's decision (2026-09-25).** They were asked
whether Row, Column or Page should give such records a place of their own. Their
answer: "I think leaving it out for now is fine, maybe a UI element somewhere
that shows the number of records underneath the current view?" That indicator
is improvise-gtn7.10, and it is not an import concern.
### Colliding records are a question, not a default (improvise-cgqt)