Skip to content

Commit 7c481f8

Browse files
author
Arena Agent
committed
Merge branch codex/proof-stack-merge-20260907 into coderabbit/document-pr-functions/04c50ac3 (resolve PR #521 conflicts)
1 parent eaa3ceb commit 7c481f8

3 files changed

Lines changed: 22 additions & 56 deletions

File tree

‎robot-repo-automaton/src/fixer.rs‎

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,15 @@ const BINARY_EXTENSIONS: &[&str] = &[
7272
];
7373

7474
impl Fixer {
75-
/// Create a fixer rooted at `repo_path`.
76-
///
77-
/// When `dry_run` is true, policy and boundary checks still run, but eligible
78-
/// fixes are only reported and no files or commits are changed.
75+
/// Create a new fixer for a repository
7976
pub fn new(repo_path: PathBuf, dry_run: bool) -> Self {
8077
// Keep one root representation for ignore rules and index paths.
8178
// Invalid roots are retained so apply's boundary check reports the error.
8279
let repo_path = repo_path.canonicalize().unwrap_or(repo_path);
8380
Fixer { repo_path, dry_run }
8481
}
8582

86-
/// Apply a fix after checking the exclusion registry and repository boundary.
87-
///
88-
/// Policy rejections and action-level non-applicability are represented in
89-
/// [`FixResult`]; failures that prevent the operation itself may be returned
90-
/// as errors. In dry-run mode, eligible fixes report their intended changes
91-
/// without writing them.
83+
/// Apply a fix for a detected issue
9284
pub fn apply(&self, issue: &DetectedIssue, fix: &Fix) -> Result<FixResult> {
9385
// EXCLUSION REGISTRY GUARD: refuse the write if the target repo,
9486
// origin, or target path is on the estate-wide denylist. In dry-run
@@ -387,10 +379,10 @@ impl Fixer {
387379
})
388380
}
389381

390-
/// Modify a text file without exposing partially written content.
382+
/// Modify a file with safety checks and rollback support
391383
///
392-
/// Binary files are rejected. For supported structured formats, the complete
393-
/// result is parsed before the original file is atomically replaced.
384+
/// Reads the modification specification from the fix, applies it to the file,
385+
/// and rolls back if the modification produces invalid content.
394386
fn apply_modify(
395387
&self,
396388
target_path: &Path,
@@ -510,12 +502,13 @@ impl Fixer {
510502
})
511503
}
512504

513-
/// Create a file from explicit fallback content or a built-in template.
505+
/// Create a file with template expansion
514506
///
515-
/// Existing or ignored targets are not written, and publication uses
516-
/// no-clobber semantics. Template expansion replaces the literal
517-
/// `gitbot-fleet` name and the `{{LICENSE}}`, `{{YEAR}}`, `{{AUTHOR}}` and
518-
/// `{{EMAIL}}` placeholders.
507+
/// Supports template variables:
508+
/// - `gitbot-fleet` - Repository name
509+
/// - `hyperpolymath` - Repository owner
510+
/// - `{{LICENSE}}` - License identifier
511+
/// - `{{YEAR}}` - Current year
519512
fn apply_create(
520513
&self,
521514
target_path: &Path,
@@ -611,9 +604,7 @@ impl Fixer {
611604
})
612605
}
613606

614-
/// Disable a file by renaming it with a `yml.disabled` extension.
615-
///
616-
/// The rename does not replace an existing destination.
607+
/// Disable a workflow (rename to .disabled)
617608
fn apply_disable(
618609
&self,
619610
target_path: &Path,
@@ -680,9 +671,7 @@ impl Fixer {
680671
false
681672
}
682673

683-
/// Return explicit fallback content or the built-in template for `target`.
684-
///
685-
/// Targets without either source return an empty string.
674+
/// Get template content for a file creation
686675
fn get_template_content(&self, target: &str, fix: &Fix) -> String {
687676
// If the fix has explicit content in the fallback field, use it
688677
if let Some(ref fallback) = fix.fallback {
@@ -698,7 +687,7 @@ impl Fixer {
698687
}
699688
}
700689

701-
/// Expand the repository-specific and fixed metadata placeholders in a template.
690+
/// Expand template variables in content
702691
fn expand_template(&self, content: &str) -> String {
703692
let repo_name = self
704693
.repo_path
@@ -716,11 +705,7 @@ impl Fixer {
716705
.replace("{{EMAIL}}", "j.d.a.jewell@open.ac.uk")
717706
}
718707

719-
/// Stage the listed paths and commit the resulting repository index.
720-
///
721-
/// Deleted paths are removed from the index, while paths outside the canonical
722-
/// repository root are ignored. Dry-run mode performs the exclusion check but
723-
/// neither stages nor commits changes.
708+
/// Commit changes to the repository
724709
pub fn commit(&self, message: &str, files: &[PathBuf]) -> Result<()> {
725710
// EXCLUSION REGISTRY GUARD: a commit is a write action even though
726711
// apply() has already checked each file individually, because some
@@ -776,11 +761,7 @@ impl Fixer {
776761
Ok(())
777762
}
778763

779-
/// Apply each issue/fix pair and commit files reported as modified.
780-
///
781-
/// No commit is created when nothing changes or dry-run mode is enabled. The
782-
/// separate `issues` slice is retained for caller compatibility and is not
783-
/// consulted; each tuple in `fixes` supplies its associated issue.
764+
/// Apply multiple fixes and commit
784765
pub fn apply_and_commit(
785766
&self,
786767
_issues: &[DetectedIssue],
@@ -908,14 +889,12 @@ fn resolve_from_existing_ancestor(path: &Path) -> Result<PathBuf> {
908889
}
909890
}
910891

911-
/// Return whether the character at `index` follows an odd run of backslashes.
912892
fn is_escaped(value: &str, index: usize) -> bool {
913893
value[..index].bytes().rev()
914894
.take_while(|byte| *byte == b'\\')
915895
.count() % 2 == 1
916896
}
917897

918-
/// Replace each escaped colon with a literal colon, preserving other backslashes.
919898
fn unescape_colons(value: &str) -> String {
920899
let mut output = String::with_capacity(value.len());
921900
let mut characters = value.chars().peekable();

‎robot-repo-automaton/src/hypatia.rs‎

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,7 @@ impl CicdHyperAClient {
237237
self.load_local_ruleset(ruleset_id)
238238
}
239239

240-
/// Load a local ruleset from the first configured recipes directory that exists.
241-
///
242-
/// Data-root environment variables take precedence over `REPOS_BASE`, the
243-
/// default estate directory and legacy locations. Built-in RSR rules are used
244-
/// when that selected directory yields no valid recipes.
240+
/// Load rules from local verisimdb-data recipes directory.
245241
fn load_local_ruleset(&self, ruleset_id: &str) -> crate::Result<Ruleset> {
246242
let mut recipes_dirs = Vec::new();
247243
for key in ["HYPATIA_DATA", "VERISIMDB_DATA"] {
@@ -263,10 +259,6 @@ impl CicdHyperAClient {
263259
self.load_recipes_from(ruleset_id, &recipes_dirs)
264260
}
265261

266-
/// Build a ruleset from JSON recipes in the first existing candidate directory.
267-
///
268-
/// Unreadable entries and malformed or incomplete recipes are skipped. If no
269-
/// rules remain, the built-in RSR rules are returned instead.
270262
fn load_recipes_from(&self, ruleset_id: &str, recipes_dirs: &[PathBuf]) -> crate::Result<Ruleset> {
271263
let recipes_dir = recipes_dirs.iter().find(|d| d.is_dir());
272264

@@ -623,10 +615,7 @@ impl CicdHyperAClient {
623615
}
624616
}
625617

626-
/// Convert a verisimdb-data recipe into a rule.
627-
///
628-
/// A string `id` and either `file_glob` or `pattern` are required; recipes
629-
/// missing those fields are ignored.
618+
/// Convert a verisimdb-data recipe JSON to a Rule.
630619
fn recipe_to_rule(recipe: &serde_json::Value) -> Option<Rule> {
631620
let id = recipe.get("id")?.as_str()?.to_string();
632621
let name = recipe.get("name").and_then(|v| v.as_str()).unwrap_or(&id).to_string();

‎robot-repo-automaton/src/main.rs‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,9 @@ fn cmd_catalog(path: &Path, severity_filter: Option<&str>) -> anyhow::Result<()>
744744

745745
/// Base directory holding local repo checkouts.
746746
///
747-
/// Uses a non-empty `REPOS_BASE` value when set; otherwise returns
748-
/// `$HOME/developer/hyper-repos`, relative to the current directory when no home
749-
/// directory is available.
747+
/// Override with `REPOS_BASE`; otherwise defaults to the canonical estate tree.
748+
/// Legacy checkout locations can also be selected through `REPOS_BASE`; the
749+
/// former literal `/var$REPOS_DIR` path did not expand a shell variable in Rust.
750750
fn repos_base() -> PathBuf {
751751
if let Ok(base) = std::env::var("REPOS_BASE") {
752752
if !base.is_empty() {
@@ -761,9 +761,7 @@ fn repos_base() -> PathBuf {
761761

762762
/// Resolve a repo argument to a local path.
763763
///
764-
/// Existing paths are returned directly. Other values are resolved relative to
765-
/// [`repos_base`], including nested `owner/name` paths, and an error lists the
766-
/// attempted location when neither exists.
764+
/// Accepts either a local path or a GitHub owner/name format.
767765
fn resolve_repo_path(repo: &str) -> anyhow::Result<PathBuf> {
768766
let path = PathBuf::from(repo);
769767
if path.exists() {

0 commit comments

Comments
 (0)