Deflate changed vault files from disk into redb. Scans the vault working copy, detects changes, and updates the database. Returns the list of paths that were updated. This is the inverse of `vault_materialize_all`. Together they form the inflate/deflate cycle: - `vault_materialize_all`: redb -> disk (for humans to read/edit) - `vault_record_working_copy`: disk -> redb (after humans edit)
(&self)
| 652 | /// - `vault_materialize_all`: redb -> disk (for humans to read/edit) |
| 653 | /// - `vault_record_working_copy`: disk -> redb (after humans edit) |
| 654 | pub fn vault_record_working_copy(&self) -> Result<Vec<String>, RepositoryError> { |
| 655 | let changes = self.vault_scan_working_copy()?; |
| 656 | |
| 657 | let mut updated_paths = Vec::new(); |
| 658 | |
| 659 | for change in &changes { |
| 660 | match change.change_type { |
| 661 | VaultChangeType::New | VaultChangeType::Modified => { |
| 662 | // Infer entry type from path |
| 663 | let entry_type = infer_entry_type(&change.path); |
| 664 | |
| 665 | // T5b record-time grant-lapse (gap #2): a raw on-disk |
| 666 | // substance edit to a `done` Draft intent reaches the vault |
| 667 | // through THIS path (not `vault_intent_update`), so apply the |
| 668 | // same demote-only lapse here. `record_time_lapse_frontmatter` |
| 669 | // is Intent-only, demote-only, and returns the demoted |
| 670 | // frontmatter iff a lapse applied; otherwise the incoming |
| 671 | // frontmatter is stored unchanged. Single store, no recursion. |
| 672 | let lapsed_fm = self.record_time_lapse_frontmatter(change, entry_type); |
| 673 | let frontmatter_json = lapsed_fm |
| 674 | .clone() |
| 675 | .unwrap_or_else(|| change.frontmatter_json.clone()); |
| 676 | |
| 677 | self.vault_store( |
| 678 | &change.path, |
| 679 | entry_type, |
| 680 | change.content.clone(), |
| 681 | frontmatter_json, |
| 682 | )?; |
| 683 | |
| 684 | // `vault_store` maintains only counts/merkle for Intent |
| 685 | // entries — it does not sync the IntentSummary status/pin. On |
| 686 | // a lapse, mirror the demoted status/reason into the manifest |
| 687 | // so lists and triage stay consistent (as vault_intent_update |
| 688 | // does on its path). |
| 689 | if let Some(new_fm_json) = lapsed_fm { |
| 690 | self.sync_intent_summary_after_lapse(&change.path, &new_fm_json)?; |
| 691 | } |
| 692 | |
| 693 | updated_paths.push(change.path.clone()); |
| 694 | } |
| 695 | VaultChangeType::Deleted => { |
| 696 | self.vault_delete(&change.path)?; |
| 697 | updated_paths.push(change.path.clone()); |
| 698 | } |
| 699 | } |
| 700 | } |
| 701 | |
| 702 | // Index any intent entries the manifest is missing — even when no |
| 703 | // file changed. Entries can predate this call (clone bootstrap |
| 704 | // deflates inherited files) and `update_manifest_for_store` leaves |
| 705 | // intent summaries to higher-level methods; without this, inherited |
| 706 | // intents exist in redb but never show up in `intent list`. |
| 707 | self.vault_reconcile_intent_manifest()?; |
| 708 | |
| 709 | Ok(updated_paths) |
| 710 | } |
| 711 |