Add distributed settings and workspace import/export (M5)

This commit is contained in:
2026-06-07 15:51:00 +03:00
parent 80bedd2a8d
commit 548aa199d9
38 changed files with 3150 additions and 101 deletions
@@ -310,6 +310,31 @@ export function dedupeIncomingDatasetNames(
> §6 over the imported snippet set, or run `renameDatasetEverywhere` per applied
> rename after the import is committed.
### 5.1 Where the import/export flow lives, and its rules
**Flow:** header (Import/Export buttons in `App.tsx`) → `services/transfer.ts`
(the only store-touching layer) → pure core (`core/import-normalize.ts` shape
detection + normalization + the dedupe/rename/id-reassign helpers; `core/export-envelope.ts`)
- browser IO (`infrastructure/file-transfer.ts`). The pure helpers are unit-tested
hardest; `transfer.ts` only orchestrates (read stores → call core → commit →
notify). The behavioral contract is spec §08.
Three rules a future change must keep:
- **Datasets commit before snippets** (`DatasetStore.addDatasets` then
`SnippetStore.addSnippets`) so a snippet's by-name reference resolves against the
just-added (possibly suffixed) dataset.
- **Imported datasets get fresh monotonic numeric ids** (`addDatasets`), not their
envelope ids. Safe — and necessary — because datasets are linked **by name, not
id** (§1): id reuse would collide in IndexedDB, but renaming the _id_ breaks
nothing. (This is why the old `Date.now()`-collision TODO on `add` doesn't bite import.)
- **Rename propagation reads the spec, not only `datasetRefs`.**
`applyDatasetRenamesToSnippets` finds the referenced name via
`extractDatasetRefs(spec)` `datasetRefs`, so an imported snippet whose
`datasetRefs` is absent/stale (a hand-crafted or foreign file) still gets its
spec rewritten — the renderer resolves by spec, so a missed rename would break it.
**Do**
- Reserve each chosen name immediately so collisions _within_ one import are