Extract optional-file synchronisation workflow owners

This commit is contained in:
vorotamoroz committed 2026-09-04 09:33:36 +00:00
1 parent 355d819f43
commit 60b093612b
29 files changed
+4017 -1768

No files matched your search

@@ -20,13 +20,15 @@ one writer for raw events, scheduled scans, and automatic database-to-local
reflection. The constructor-name add-on lookup and the `ConfigSync` and
`HiddenFileSync` add-on identities have been retired.
The Customisation Sync private context coordinates its snapshot operations,
scan queues, periodic work, and focused path and transient-state owners. The
Hidden File Sync private context coordinates reconciliation, periodic work,
and the lifetimes of focused path-admission, notification, processed-state,
change-processing, and conflict-resolution owners. Each receives live settings
and database projections, focused storage, path, and exact-revision
capabilities, and explicit host effects rather than `LiveSyncCore`.
The Customisation Sync private context coordinates lifecycle, raw-event
admission, configuration and periodic policy, view composition, and the
lifetimes of focused path, snapshot, application, scan, and catalogue owners.
The Hidden File Sync private context coordinates lifecycle and handler
admission around focused path-admission, notification, processed-state,
change-processing, conflict-resolution, and reconciliation owners. Each
receives live settings and database projections, focused storage, path, and
exact-revision capabilities, and explicit host effects rather than
`LiveSyncCore`.
The corresponding implemented topology is documented in
[Optional-file synchronisation architecture](../design_docs/optional_file_sync_architecture.md).
@@ -203,14 +205,35 @@ operations receive this capability through one narrow `processedState` port;
they do not receive bundles of individual state callbacks or implement state
keys themselves.
`CustomisationSyncCatalogueState` separately owns the transient catalogue
rows, manifest lookup and mtime cache, their reactive stores, and catalogue
update progress. A small recent-event deduplicator owns raw-event admission
history. These Customisation Sync owners are deliberately not implementations
of a shared Hidden File Sync state abstraction: the former state is a derived,
in-memory projection, while Hidden File Sync markers are persisted operational
reconciliation state with different identity, invalidation, and deletion
rules.
`CatalogueState` separately owns the transient catalogue rows, manifest lookup
and mtime cache, their reactive stores, and catalogue update progress. A small
recent-event deduplicator owns raw-event admission history. These Customisation
Sync owners are deliberately not implementations of a shared Hidden File Sync
state abstraction: the former state is a derived, in-memory projection, while
Hidden File Sync markers are persisted operational reconciliation state with
different identity, invalidation, and deletion rules.
`CatalogueOperations` owns catalogue enumeration, one queue and its progress
subscription, and composes `CatalogueV1`, `CatalogueV2`, and
`CatalogueMigration`. V1 and V2 are mutually exclusive as the selected write
format, but both persisted formats can coexist during migration. Queue work
therefore reads the live setting when it starts, and the shared state continues
to recognise V2 rows independently of that setting. `CatalogueMigration`
remains the distinct bridge from grouped V1 binders to per-file V2 documents.
`SnapshotPersistence` owns the host-neutral V1 grouped and V2 per-file writes
and logical deletion. It returns explicit mutation and refresh outcomes, so it
neither owns catalogue state nor calls back through the context.
`SnapshotOperations` applies those outcomes with the inherited awaited V1 or
fire-and-forget V2 timing. `ApplicationOperations` owns compare, apply,
duplicate, and delete workflows, while `ScanOperations` owns configuration-file
enumeration and V1/V2 reconciliation. Both depend on narrow snapshot and
catalogue ports instead of the context.
The newly extracted catalogue, snapshot, application, scan, and reconciliation
modules omit a Customisation Sync or Hidden File Sync prefix because their
feature directories already supply that scope. Public contexts and views retain
their domain names for compatibility.
`CustomisationSyncPathOperations` binds live configuration-directory, mode,
and device-name projections to the pure category and V1/V2 key functions. It
@@ -232,6 +255,12 @@ This boundary keeps event concurrency and settlement directly testable without
giving the processor full scan, initialisation, notification, or host
responsibilities.
`Reconciliation` owns storage and database enumeration, full scans, offline
comparison, rebuild direction and ordering, processed-state adoption,
initialisation sequencing, and the scoped rebuild interceptor used by maintained
real-Obsidian tests. Storage and database scans remain together because every
offline and initialisation path coordinates both sides.
The joint composition may return several views backed by those contexts:
- a Customisation Sync catalogue and operation view for its dialogue;
@@ -372,11 +401,17 @@ to the non-owner.
The private context, path module, codec module, focused presentation view, and
resource teardown are implemented. A focused path capability binds live
settings and device identity to the pure path functions. A focused
catalogue-state owner holds the rows, manifests, manifest mtime cache, reactive
stores, and update progress, while a bounded deduplicator owns recent raw-event
keys. Enumeration and scan queues remain with the orchestrating context. The
context accepts only narrow, live projections and explicit effects; an
settings and device identity to the pure path functions. A focused catalogue
owner holds one queue, its progress subscription, and shared state, while
separate V1, V2, and migration modules hold format-specific behaviour. A
bounded deduplicator owns recent raw-event keys. Host-neutral snapshot
persistence owns V1 grouped and V2 per-file writes, unchanged-content checks,
and logical deletion. A snapshot coordinator applies its explicit refresh
outcomes without a catalogue-to-context callback cycle. Focused application
and scan owners contain selected-snapshot workflows and full local/database
reconciliation, respectively. The context retains raw-event admission and
scheduling, configuration and periodic policy, owner lifetime, and view
composition. It accepts only narrow, live projections and explicit effects; an
Obsidian adapter at the composition edge owns dialogues, Notices, plug-in
reload, restart, lifecycle, Vault access, and compatibility scan telemetry.
@@ -397,9 +432,10 @@ the ownership, static-path, pattern, and ignore-file sequence. A focused change
notifier owns folder batching, delayed delivery, and teardown of its scheduled
work and Notice effect. A focused change processor owns storage and database
event processing, bounded concurrency, per-path serialisation, activity
publication, and compatibility settlement order. The context retains scan,
initialisation, and reconciliation orchestration. A focused
conflict-resolution owner owns pending-path admission,
publication, and compatibility settlement order. A focused reconciliation
owner owns storage and database scans, offline comparison, rebuilds,
processed-state adoption, initialisation direction and ordering, and its scoped
testing interceptor. A focused conflict-resolution owner owns pending-path admission,
the parallel classification and serial interaction queues, automatic merge,
newer-revision selection, interactive JSON application, settlement, and queue
disposal. An Obsidian adapter owns JSON conflict dialogue instances, progress
@@ -499,12 +535,13 @@ migration without first establishing narrow dependencies.
- The legacy add-on identity and constructor-name lookup are removed.
- The two contexts coordinate separate synchronisation workflows, but their
dependency surfaces are explicit and do not include the complete core.
Customisation Sync delegates its path binding, derived catalogue, and
recent-event state, while Hidden File Sync delegates path admission,
notification, processed-state, change-processing, and conflict lifecycles,
to focused owners. Further extraction should follow a concrete behavioural
boundary rather than create additional serviceFeatures for private
operations.
Customisation Sync delegates its path binding, snapshot persistence and
refresh sequencing, selected-snapshot application, scan reconciliation,
derived catalogue, catalogue queue, and recent-event state, while Hidden File
Sync delegates path admission, notification, processed-state,
change-processing, reconciliation, and conflict lifecycles to focused owners.
Further extraction should follow a concrete behavioural boundary rather than
create additional serviceFeatures for private operations.
## References
@@ -32,9 +32,19 @@ Obsidian composition (`main.ts`)
| |
| +--> `CustomisationSyncContext`
| | +-- `CustomisationSyncPathOperations`
| | +-- `CustomisationSyncCatalogueState`
| | +-- `SnapshotPersistence`
| | +-- `SnapshotOperations`
| | +-- `ApplicationOperations`
| | +-- `ScanOperations`
| | +-- recent-event deduplicator
| | +-- immutable service-handler and testing views
| | |
| | +--> `CatalogueOperations`
| | +-- `CatalogueState`
| | +-- one catalogue queue and progress lifecycle
| | +-- `CatalogueV1`
| | +-- `CatalogueV2`
| | +-- `CatalogueMigration`
| | ^
| | +-- narrow dependencies from
| | `customisationSyncObsidianAdapter`
@@ -64,6 +74,10 @@ Obsidian composition (`main.ts`)
| | +-- changed-folder batching and scheduled delivery
| | +-- suppression and Notice-effect teardown
| |
| +--> `Reconciliation`
| | +-- storage and database scans
| | +-- offline reconciliation, rebuilds, and initialisation
| |
| +-- immutable service-handler, command, repair, and testing views
|
+--> `useCustomisationSyncUI`
@@ -84,37 +98,65 @@ application core.
## Ownership
| Owner | Owns | Does not own |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `useOptionalFileSync` | Construction of both contexts, handler registration and removal, local-owner selection, namespace dispatch, compatibility callback order, and context disposal order. | Persisted feature state, synchronisation algorithms, commands, dialogues, or Notices. |
| `CustomisationSyncContext` | The `ix:` scan and snapshot workflow, snapshot storage and application, periodic scan state, and the lifetimes of its focused owners. | Path derivation, catalogue mutations, recent-event history, Obsidian dialogues, ribbon actions, or handler registration. |
| `CustomisationSyncPathOperations` | Binding live configuration-directory, mode, and device-name projections to the pure category, target-path, V1 key, V2 key, and device-prefix functions. | I/O, mutable state, local-owner selection, or persistence. |
| `CustomisationSyncCatalogueState` | Transient catalogue rows, manifest lookup and mtime cache, reactive catalogue and manifest stores, and catalogue update progress. | Database or storage I/O, scan scheduling, routing, or persistence. |
| Customisation Sync event deduplicator | The bounded, newest-first keys used to admit raw configuration events once. | Scheduling, path ownership, catalogue state, or persisted data. |
| `HiddenFileSyncContext` | The `i:` scan and reconciliation workflow, exact-revision repair composition, periodic scan state, and focused-owner lifetimes. | Path admission state, change-event serialisation, processed-state representation, notification batching, conflict queue state, Obsidian dialogues, or service handler registration. |
| `HiddenFileSyncProcessedState` | Three device-local autosaved maps, exact storage and database keys, retained known mtime, reset behaviour, and storage/database settlement effects. | File transfer, scan scheduling, conflict handling, or presentation. |
| `HiddenFileSyncChangeProcessor` | Storage and database change processing, same-path event serialisation, bounded concurrency, activity counts, and the inherited event-consumption and settlement order. | Full scans, initialisation policy, notification presentation, or conflict interaction. |
| `HiddenFileSyncConflictResolution` | Conflict admission and deduplication, pending paths, the parallel classification and serial interaction queues, automatic merge, newer-revision policy, interactive JSON resolution, and conflict settlement. | Obsidian dialogue instances, general Hidden File Sync scans, processed-state caches, or Service handler registration. |
| `HiddenFileSyncPathAdmission` | The ownership-first eligibility sequence, hidden-path and pattern policy, asynchronous ignore-file check, and the per-context parsed-pattern cache. | Composition-level owner selection, scans, transfer, or persistence. |
| `HiddenFileSyncChangeNotifier` | Changed-folder deduplication, delayed delivery, live suppression and configuration-directory checks, scheduled-task cancellation, and the host Notice show/hide effects. | The Obsidian Notice instance, file extraction, or scan policy. |
| Customisation Sync Obsidian adapter | Obsidian conflict selection, Notice presentation, plug-in reload, restart requests, Vault enumeration, progress telemetry, and platform-derived fallback device names. | Catalogue state, routing, or persisted document operations. |
| Hidden File Sync Obsidian adapter | JSON conflict dialogue lifetime, progress presentation, grouped change Notices, plug-in reload actions, restart scheduling, Vault enumeration, and compatibility activity publication. | Transfer, reconciliation, processed-state, or conflict decisions. |
| `useCustomisationSyncUI` | Command, ribbon, dialogue, open-request subscription, and their unload teardown. | Synchronisation state or Hidden File Sync initialisation behaviour. |
| `useHiddenFileSyncCommands` | Hidden File Sync command registration, setting-change subscription, and their unload teardown. | Synchronisation state or command implementation. |
| Owner | Owns | Does not own |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `useOptionalFileSync` | Construction of both contexts, handler registration and removal, local-owner selection, namespace dispatch, compatibility callback order, and context disposal order. | Persisted feature state, synchronisation algorithms, commands, dialogues, or Notices. |
| `CustomisationSyncContext` | Lifecycle and view composition, raw-event admission and scheduling, configuration transitions, periodic scan policy, and focused-owner lifetimes. | Scan reconciliation, snapshot writes or refresh sequencing, catalogue internals, application and comparison algorithms, Obsidian dialogues, ribbon actions, or handler registration. |
| `CustomisationSyncPathOperations` | Binding live configuration-directory, mode, and device-name projections to the pure category, target-path, V1 key, V2 key, and device-prefix functions. | I/O, mutable state, local-owner selection, or persistence. |
| `SnapshotPersistence` | V1 grouped and V2 per-file local-to-database writes, unchanged-content checks, logical deletion, and explicit catalogue-refresh outcomes. | Catalogue state or refresh execution, scans, lifecycle policy, application, dialogues, or plug-in reload. |
| `SnapshotOperations` | Applying persistence outcomes to the catalogue with the inherited awaited V1 and fire-and-forget V2 refresh timing. | Snapshot encoding, catalogue state, scans, lifecycle policy, or host effects. |
| `ApplicationOperations` | Comparing, applying, duplicating, and deleting selected Customisation Sync snapshots through narrow storage, snapshot, and catalogue ports. | Catalogue enumeration, raw-event admission, periodic scheduling, or view composition. |
| `ScanOperations` | Configuration-file enumeration and V1/V2 reconciliation with local and database state. | Periodic scheduling, raw-event admission, snapshot persistence details, or catalogue state. |
| `CatalogueOperations` | Catalogue enumeration and publication, one format-dispatching queue and its progress lifecycle, and composition of the state, V1, V2, and migration modules. | Local-file scanning, snapshot application, raw-event routing, dialogues, or handler registration. |
| `CatalogueState` | Transient catalogue rows, manifest lookup and mtime cache, reactive catalogue and manifest stores, and catalogue update progress. | Database or storage I/O, scan scheduling, routing, or persistence. |
| `CatalogueV1` | Loading and publishing grouped V1 catalogue rows. | V2 decoding, migration, queue lifetime, or local-file scanning. |
| `CatalogueV2` | Building and updating per-file V2 rows and manifests. | V1 loading, migration, queue lifetime, or local-file scanning. |
| `CatalogueMigration` | Translating a grouped V1 binder into V2 per-file documents, deleting the migrated binder, and applying its required V1 refresh. | General catalogue enumeration, queue ownership, or local-file scanning. |
| Customisation Sync event deduplicator | The bounded, newest-first keys used to admit raw configuration events once. | Scheduling, path ownership, catalogue state, or persisted data. |
| `HiddenFileSyncContext` | Lifecycle and view composition, handler admission, configuration transitions, periodic scan state, exact-revision repair composition, and focused-owner lifetimes. | Scan and rebuild algorithms, path admission state, change-event serialisation, processed-state representation, notification batching, conflict queue state, Obsidian dialogues, or service handler registration. |
| `HiddenFileSyncProcessedState` | Three device-local autosaved maps, exact storage and database keys, retained known mtime, reset behaviour, and storage/database settlement effects. | File transfer, scan scheduling, conflict handling, or presentation. |
| `HiddenFileSyncChangeProcessor` | Storage and database change processing, same-path event serialisation, bounded concurrency, activity counts, and the inherited event-consumption and settlement order. | Full scans, initialisation policy, notification presentation, or conflict interaction. |
| `Reconciliation` | Storage and database enumeration, full scans, offline reconciliation, rebuild direction and ordering, processed-state adoption, initialisation sequencing, and the scoped rebuild interceptor. | Individual transfer implementation, conflict interaction, path-pattern state, periodic scheduling, or host lifecycle. |
| `HiddenFileSyncConflictResolution` | Conflict admission and deduplication, pending paths, the parallel classification and serial interaction queues, automatic merge, newer-revision policy, interactive JSON resolution, and conflict settlement. | Obsidian dialogue instances, general Hidden File Sync scans, processed-state caches, or Service handler registration. |
| `HiddenFileSyncPathAdmission` | The ownership-first eligibility sequence, hidden-path and pattern policy, asynchronous ignore-file check, and the per-context parsed-pattern cache. | Composition-level owner selection, scans, transfer, or persistence. |
| `HiddenFileSyncChangeNotifier` | Changed-folder deduplication, delayed delivery, live suppression and configuration-directory checks, scheduled-task cancellation, and the host Notice show/hide effects. | The Obsidian Notice instance, file extraction, or scan policy. |
| Customisation Sync Obsidian adapter | Obsidian conflict selection, Notice presentation, plug-in reload, restart requests, Vault enumeration, progress telemetry, and platform-derived fallback device names. | Catalogue state, routing, or persisted document operations. |
| Hidden File Sync Obsidian adapter | JSON conflict dialogue lifetime, progress presentation, grouped change Notices, plug-in reload actions, restart scheduling, Vault enumeration, and compatibility activity publication. | Transfer, reconciliation, processed-state, or conflict decisions. |
| `useCustomisationSyncUI` | Command, ribbon, dialogue, open-request subscription, and their unload teardown. | Synchronisation state or Hidden File Sync initialisation behaviour. |
| `useHiddenFileSyncCommands` | Hidden File Sync command registration, setting-change subscription, and their unload teardown. | Synchronisation state or command implementation. |
The two domain contexts coordinate one cohesive synchronisation workflow each.
Their private operations and focused owners are not additional serviceFeatures:
they do not independently register host integration or have separate
application lifetimes. `CustomisationSyncPathOperations` is a stateless
capability which binds live inputs to pure path functions. The Hidden File Sync
path-admission owner holds the parsed-pattern cache, and its change notifier
holds the pending folder set and scheduled-task lifetime.
application lifetimes. The newly extracted catalogue, snapshot, application,
scan, and reconciliation modules omit the domain prefix because their feature
directories already supply that scope; public context and view names retain it
for compatibility. `CustomisationSyncPathOperations` is a stateless capability
which binds live inputs to pure path functions.
`SnapshotPersistence` is a host-neutral operation boundary: it returns
structured mutation and refresh outcomes without reaching into the catalogue
or presentation. `SnapshotOperations` consumes those outcomes and preserves
their refresh timing. `ApplicationOperations` and `ScanOperations` depend on
those narrow ports instead of calling back through the context.
`CatalogueOperations` owns one catalogue queue, its progress subscription, and
the shared state projected by the format-specific modules. The live V2 setting
selects V1 loading or V1-to-V2 migration when each queued item starts. Persisted
V1 and V2 documents can coexist during migration, so V2 documents remain
recognisable regardless of the currently selected write format. `CatalogueV1`
and `CatalogueV2` contain only their format-specific catalogue behaviour, while
`CatalogueMigration` remains the explicit bridge between them. The Hidden File
Sync path-admission owner holds the parsed-pattern cache, and its change
notifier holds the pending folder set and scheduled-task lifetime.
`HiddenFileSyncChangeProcessor` is a focused resource owner because its
semaphore, per-path serialisation, activity counters, and event settlement form
one independently testable lifecycle.
`HiddenFileSyncConflictResolution` is another focused resource owner because
conflict admission, pending-path identity, two serialisation stages, and
disposal form a separate lifecycle.
`Reconciliation` keeps storage and database enumeration together because
offline comparison, rebuilds, and each initialisation direction depend on both
sides and their ordered processed-state adoption.
The two state owners intentionally do not implement a common generic state
contract. Customisation Sync projects transient catalogue and presentation
@@ -214,12 +256,16 @@ than being re-exported through a broad context testing view.
The composition is created after the Service Hub and required ServiceModules
exist, and before lifecycle-driven feature work begins. Each context creates
its own periodic processor and focused resource owners.
`CustomisationSyncContext` creates one path capability, one catalogue-state
owner, and one recent-event deduplicator. `HiddenFileSyncContext` creates one
`CustomisationSyncContext` creates one path capability, one snapshot-persistence
boundary, one snapshot coordinator, one application owner, one scan owner, one
catalogue owner, and one recent-event deduplicator. The catalogue owner creates
its shared state, one queue and progress subscription, and the V1, V2, and
migration modules. `HiddenFileSyncContext` creates one
path-admission owner, one change notifier, and one processed-state owner before
composing database write and extraction operations around their narrow ports.
It then creates one change processor and one conflict-resolution owner. The
change processor owns its semaphore and activity state.
It then creates one change processor, one conflict-resolution owner, and one
reconciliation owner. The change processor owns its semaphore and activity
state; the reconciliation owner owns its scoped testing interceptor.
Full conflict scans admit discovered paths into the same queue without
suspending it, so ordinary database conflict notifications continue during a
slow scan. After enumeration, the operation waits for both classification and
@@ -255,10 +301,14 @@ appropriate, a migration decision.
Focused unit tests cover routing, path-option binding, Hidden File Sync
admission ordering and cache invalidation, semantic handler views, context
owner isolation, teardown, initial cache selection, exact-revision repair,
change-event serialisation and settlement, notification batching, conflict
queue admission, revision selection, automatic and interactive merge effect
ordering, conflict dialogue adaptation, grouped Notices, and compatibility
activity publication.
Customisation Sync scan reconciliation and context delegation, single-queue
catalogue disposal and publication, live V1/V2 dispatch, V1 and V2 snapshot
persistence outcomes, logical-deletion idempotence, refresh ordering,
application operations, Hidden File Sync change-event serialisation and
settlement, reconciliation direction and scan ordering, notification batching,
conflict queue admission, revision selection, automatic and interactive merge
effect ordering, conflict dialogue adaptation, grouped Notices, and
compatibility activity publication.
The boundary test prevents either domain context from regaining core or
Obsidian dependencies.