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,
)
| 114 | /// Intent paths are view-scoped and session-scoped: |
| 115 | /// `intents/<view>/<session>/<turn>/intent.md` |
| 116 | pub fn vault_intent_create( |
| 117 | &self, |
| 118 | options: IntentCreateOptions, |
| 119 | ) -> Result<IntentCreateResult, RepositoryError> { |
| 120 | if !self.has_vault()? { |
| 121 | return Err(RepositoryError::InvalidOperation { |
| 122 | message: "Vault not initialized. Run `atomic vault init` first.".to_string(), |
| 123 | }); |
| 124 | } |
| 125 | |
| 126 | let priority = options.priority.unwrap_or_else(|| "medium".to_string()); |
| 127 | // Classification, defaulting to `feature`. Stored on the summary always; |
| 128 | // written to frontmatter only when non-default (so ordinary intents keep |
| 129 | // no `kind` key and their canonical hashes are unchanged). |
| 130 | let kind = options |
| 131 | .kind |
| 132 | .clone() |
| 133 | .unwrap_or_else(|| "feature".to_string()); |
| 134 | let view_name = self.current_view().to_string(); |
| 135 | let identity = self.resolve_vault_identity(); |
| 136 | let author = slug_author(&identity.name); |
| 137 | |
| 138 | // Stable primary identity: a ULID. The path, URN, and KG node all key |
| 139 | // off this, so it never collides regardless of team size or offline |
| 140 | // work. The human key is a per-author display alias. |
| 141 | let uid = ulid::Ulid::new().to_string(); |
| 142 | let intent_dir = self.intent_dir_for(&uid); |
| 143 | let intent_file = self.intent_file_for(&uid); |
| 144 | |
| 145 | // Allocate the human key inside a write transaction. |
| 146 | let human_key; |
| 147 | let project; |
| 148 | let seq; |
| 149 | { |
| 150 | let mut txn = self |
| 151 | .pristine |
| 152 | .write_txn() |
| 153 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 154 | let mut manifest = txn |
| 155 | .get_vault_manifest() |
| 156 | .map_err(|e| RepositoryError::Database(e.to_string()))?; |
| 157 | |
| 158 | // Set the project code on first use, derived from the project dir. |
| 159 | if manifest.intent_prefix.is_empty() { |
| 160 | let project_name = self |
| 161 | .root |
| 162 | .file_name() |
| 163 | .and_then(|n| n.to_str()) |
| 164 | .unwrap_or("vault"); |
| 165 | manifest.intent_prefix = VaultManifest::derive_intent_prefix(project_name); |
| 166 | if manifest.intent_prefix.is_empty() { |
| 167 | manifest.intent_prefix = "VAULT".to_string(); |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | project = manifest.project_code().to_string(); |
| 172 | seq = manifest.allocate_author_seq(&author); |
| 173 | human_key = VaultManifest::compose_human_key(&project, &author, seq); |