Skip to main content

ensure_devflow_dir

Function ensure_devflow_dir 

Source
pub fn ensure_devflow_dir(dir: &Path) -> Result<()>
Expand description

Create dir (and any missing parents), then self-protect any .devflow directory found in its path by writing <that-dir>/.gitignore containing * — so a downstream user’s routine git add . && git commit never sweeps DevFlow’s runtime artifacts (agent stdout, gate context, state) into their repository, independent of whether their own root .gitignore mentions .devflow at all (closes 19a-WR-01, 19-CONTEXT.md D-14).

This is deliberately a different function from the pure path accessor devflow_dir above: devflow_dir(project_root) takes a project root and returns project_root/.devflow with zero filesystem I/O — it is invoked from read-only paths (doctor, status) and from tests that assert on the returned path, so giving it side effects would be exactly the class of behavioral change this phase exists to avoid. This function, ensure_devflow_dir(dir), instead takes the directory to create, which may itself be .devflow, a subdirectory of it, or something with no .devflow ancestor at all. Do not confuse the two.

Contract:

  1. create_dir_all(dir) — create dir and all missing parents.
  2. Find the shallowest .devflow path component (see [find_devflow_marker]).
  3. If found, write <marker>/.gitignore with the bytes *\n, using create_new(true) so an existing file — whatever its content — is left untouched; a lost race against a concurrent creator surfaces as AlreadyExists, which this function maps to Ok(()). Any other I/O error propagates via ?.
  4. If no .devflow component exists, this function is exactly equivalent to create_dir_all.

Returns std::io::Result<()>, not a crate-specific error enum: this plan’s seven conversion sites each live in a different module with their own error enum (WorkflowError, GateError, MonitorError, ResultError, ShipError, LockError), and every one already carries an Io(#[from] std::io::Error) variant, so ? converts at every call site with zero signature churn.

Deleted-marker note: if .devflow/.gitignore is deleted after creation, subsequent calls will not recreate it — the protection is established once per directory lifetime. Recreating a deleted marker would violate the rule that this function must never overwrite an existing .gitignore a user or another tool may own, and it cannot distinguish “user deleted it” from “never created.”