Create a new vault intent. Allocates a JIRA-style ID (e.g., "PIMO-1") and creates an intent directory with an `intent.md` scaffold. The prefix is derived from the project directory name on first use (first 4 alphanumeric chars, uppercased). Intent paths are view-scoped and session-scoped: `intents/ / / /intent.md`
(
&self,
options: IntentCreateOptions,
)
| 110 | /// Intent paths are view-scoped and session-scoped: |
| 111 | /// `intents/<view>/<session>/<turn>/intent.md` |
| 112 | pub fn vault_intent_create( |
| 113 | &self, |
| 114 | options: IntentCreateOptions, |
| 115 | ) -> Result<IntentCreateResult, RepositoryError> { |
| 116 | if !self.has_vault()? { |
| 117 | return Err(RepositoryError::InvalidOperation { |
| 118 | message: "Vault not initialized. Run `atomic vault init` first.".to_string(), |
| 119 | }); |
| 120 | } |
| 121 | |
| 122 | let priority = options.priority.unwrap_or_else(|| "medium".to_string()); |
| 123 | let view_name = self.current_view().to_string(); |
| 124 | let identity = self.resolve_vault_identity(); |
| 125 | let author = slug_author(&identity.name); |
| 126 | |
| 127 | // Stable primary identity: a ULID. The path, URN, and KG node all key |
| 128 | // off this, so it never collides regardless of team size or offline |
| 129 | // work. The human key is a per-author display alias. |
| 130 | let uid = ulid::Ulid::new().to_string(); |
| 131 | let intent_dir = self.intent_dir_for(&uid); |
| 132 | let intent_file = self.intent_file_for(&uid); |
| 133 | |
| 134 | // Allocate the human key inside a write transaction. |
| 135 | let human_key; |
| 136 | let project; |
| 137 | let seq; |
| 138 | { |
| 139 | let mut txn = self |
| 140 | .pristine |
| 141 | .write_txn() |
| 142 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 143 | let mut manifest = txn |
| 144 | .get_vault_manifest() |
| 145 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 146 | |
| 147 | // Set the project code on first use, derived from the project dir. |
| 148 | if manifest.intent_prefix.is_empty() { |
| 149 | let project_name = self |
| 150 | .root |
| 151 | .file_name() |
| 152 | .and_then(|n| n.to_str()) |
| 153 | .unwrap_or("vault"); |
| 154 | manifest.intent_prefix = VaultManifest::derive_intent_prefix(project_name); |
| 155 | if manifest.intent_prefix.is_empty() { |
| 156 | manifest.intent_prefix = "VAULT".to_string(); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | project = manifest.project_code().to_string(); |
| 161 | seq = manifest.allocate_author_seq(&author); |
| 162 | human_key = VaultManifest::compose_human_key(&project, &author, seq); |
| 163 | |
| 164 | // The manifest is keyed by the human key; the ULID is stored on the |
| 165 | // summary as the stable identity. Per-author keys never collide |
| 166 | // across teammates, and the ULID disambiguates the rare |
| 167 | // same-author-two-clones case. |
| 168 | manifest.intents.insert( |
| 169 | human_key.clone(), |