Find the vault path for an intent by its display ID. First checks the manifest's `vault_path` field (fast path), then falls back to scanning vault entries under `intents/ /` for a file whose frontmatter `id` field matches the normalized intent ID.
(&self, full_id: &str)
| 708 | /// falls back to scanning vault entries under `intents/<current_view>/` |
| 709 | /// for a file whose frontmatter `id` field matches the normalized intent ID. |
| 710 | fn find_intent_path(&self, full_id: &str) -> Result<Option<String>, RepositoryError> { |
| 711 | // Fast path: check the manifest for a stored vault_path |
| 712 | let manifest = self.vault_manifest()?; |
| 713 | if let Some(summary) = manifest.intents.get(full_id) { |
| 714 | if !summary.vault_path.is_empty() { |
| 715 | // Verify the path still exists |
| 716 | if self.vault_retrieve(&summary.vault_path)?.is_some() { |
| 717 | return Ok(Some(summary.vault_path.clone())); |
| 718 | } |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | // Slow path: scan vault entries under the current view + manual/ |
| 723 | let prefixes = [ |
| 724 | format!("intents/{}/", self.current_view()), |
| 725 | "intents/manual/".to_string(), |
| 726 | ]; |
| 727 | for prefix in &prefixes { |
| 728 | let entries = self.vault_list(prefix, None)?; |
| 729 | for meta in entries { |
| 730 | if !meta.path.ends_with("/intent.md") { |
| 731 | continue; |
| 732 | } |
| 733 | if let Some(entry) = self.vault_retrieve(&meta.path)? { |
| 734 | if let Ok(fm) = serde_json::from_str::<serde_json::Map<String, serde_json::Value>>( |
| 735 | &entry.frontmatter_json, |
| 736 | ) { |
| 737 | if fm.get("id").and_then(|v| v.as_str()) == Some(full_id) { |
| 738 | return Ok(Some(meta.path)); |
| 739 | } |
| 740 | } |
| 741 | } |
| 742 | } |
| 743 | } |
| 744 | Ok(None) |
| 745 | } |
| 746 | |
| 747 | /// Normalize an intent ID — accept "PIMO-1", "pimo-1", or just "1". |
| 748 | fn normalize_intent_id(&self, id: &str) -> Result<String, RepositoryError> { |
no test coverage detected