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)
| 662 | /// falls back to scanning vault entries under `intents/<current_view>/` |
| 663 | /// for a file whose frontmatter `id` field matches the normalized intent ID. |
| 664 | fn find_intent_path(&self, full_id: &str) -> Result<Option<String>, RepositoryError> { |
| 665 | // Fast path: check the manifest for a stored vault_path |
| 666 | let manifest = self.vault_manifest()?; |
| 667 | if let Some(summary) = manifest.intents.get(full_id) { |
| 668 | if !summary.vault_path.is_empty() { |
| 669 | // Verify the path still exists |
| 670 | if self.vault_retrieve(&summary.vault_path)?.is_some() { |
| 671 | return Ok(Some(summary.vault_path.clone())); |
| 672 | } |
| 673 | } |
| 674 | } |
| 675 | |
| 676 | // Slow path: scan vault entries under the current view + manual/ |
| 677 | let prefixes = [ |
| 678 | format!("intents/{}/", self.current_view()), |
| 679 | "intents/manual/".to_string(), |
| 680 | ]; |
| 681 | for prefix in &prefixes { |
| 682 | let entries = self.vault_list(prefix, None)?; |
| 683 | for meta in entries { |
| 684 | if !meta.path.ends_with("/intent.md") { |
| 685 | continue; |
| 686 | } |
| 687 | if let Some(entry) = self.vault_retrieve(&meta.path)? { |
| 688 | if let Ok(fm) = serde_json::from_str::<serde_json::Map<String, serde_json::Value>>( |
| 689 | &entry.frontmatter_json, |
| 690 | ) { |
| 691 | if fm.get("id").and_then(|v| v.as_str()) == Some(full_id) { |
| 692 | return Ok(Some(meta.path)); |
| 693 | } |
| 694 | } |
| 695 | } |
| 696 | } |
| 697 | } |
| 698 | Ok(None) |
| 699 | } |
| 700 | |
| 701 | /// Normalize an intent ID — accept "PIMO-1", "pimo-1", or just "1". |
| 702 | fn normalize_intent_id(&self, id: &str) -> Result<String, RepositoryError> { |
no test coverage detected