summaryrefslogtreecommitdiff
path: root/Omni
diff options
context:
space:
mode:
authorOmni Worker <bot@omni.agent>2025-11-22 06:51:40 -0500
committerOmni Worker <bot@omni.agent>2025-11-22 06:51:40 -0500
commitfcc58e142eef98febdd385f65d4a28a869818110 (patch)
tree1883d4805ddb0ff1b575e856236d0ed9e46b17d0 /Omni
parentefbb7cf298585cfff5336d048e7d1af2dd94d560 (diff)
fix: rename to .py and fix lint errors
Amp-Thread-ID: https://ampcode.com/threads/T-ec034efc-0ef1-43df-8abe-b0cda0f9115b Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'Omni')
-rwxr-xr-xOmni/Bild/Audit.py176
-rwxr-xr-xOmni/Bild/audit.sh143
2 files changed, 176 insertions, 143 deletions
diff --git a/Omni/Bild/Audit.py b/Omni/Bild/Audit.py
new file mode 100755
index 0000000..4df6c0b
--- /dev/null
+++ b/Omni/Bild/Audit.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python3
+"""
+Audit codebase builds.
+
+Iterates through every namespace in the project and runs 'bild'.
+For every build failure encountered, it automatically creates a new task.
+"""
+
+# : out bild-audit
+
+import argparse
+import re
+import shutil
+import subprocess
+import sys
+from pathlib import Path
+
+# Extensions supported by bild (from Omni/Bild.hs and Omni/Namespace.hs)
+EXTENSIONS = {".c", ".hs", ".lisp", ".nix", ".py", ".scm", ".rs", ".toml"}
+MAX_TITLE_LENGTH = 50
+
+
+def strip_ansi(text: str) -> str:
+ """Strip ANSI escape codes from text."""
+ ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
+ return ansi_escape.sub("", text)
+
+
+def is_ignored(path: Path) -> bool:
+ """Check if a file is ignored by git."""
+ res = subprocess.run(
+ ["git", "check-ignore", str(path)],
+ stdout=subprocess.DEVNULL,
+ stderr=subprocess.DEVNULL,
+ check=False,
+ )
+ return res.returncode == 0
+
+
+def get_buildable_files(root_dir: str = ".") -> list[str]:
+ """Find all files that bild can build."""
+ targets: list[str] = []
+
+ root = Path(root_dir)
+ if not root.exists():
+ return []
+
+ for path in root.rglob("*"):
+ # Skip directories
+ if path.is_dir():
+ continue
+
+ # Skip hidden files/dirs and '_' dirs
+ parts = path.parts
+ if any(p.startswith(".") or p == "_" for p in parts):
+ continue
+
+ if path.suffix in EXTENSIONS:
+ # Clean up path: keep it relative to cwd if possible
+ try:
+ # We want the path as a string, relative to current directory
+ # if possible
+ p_str = (
+ str(path.relative_to(Path.cwd()))
+ if path.is_absolute()
+ else str(path)
+ )
+ except ValueError:
+ p_str = str(path)
+
+ if not is_ignored(Path(p_str)):
+ targets.append(p_str)
+ return targets
+
+
+def run_bild(target: str) -> subprocess.CompletedProcess[str]:
+ """Run bild on the target."""
+ # --time 0 disables timeout
+ # --loud enables output (which we capture)
+ cmd = ["bild", "--time", "0", "--loud", target]
+ return subprocess.run(cmd, capture_output=True, text=True, check=False)
+
+
+def create_task(
+ target: str,
+ result: subprocess.CompletedProcess[str],
+ parent_id: str | None = None,
+) -> None:
+ """Create a task for a build failure."""
+ # Construct a descriptive title
+ # Try to get the last meaningful line of error output
+ lines = (result.stdout + result.stderr).strip().split("\n")
+ last_line = lines[-1] if lines else "Unknown error"
+ last_line = strip_ansi(last_line).strip()
+
+ if len(last_line) > MAX_TITLE_LENGTH:
+ last_line = last_line[: MAX_TITLE_LENGTH - 3] + "..."
+
+ title = f"Build failed: {target} - {last_line}"
+
+ cmd = ["task", "create", title, "--priority", "2", "--json"]
+
+ if parent_id:
+ cmd.append(f"--discovered-from={parent_id}")
+
+ # Try to infer namespace
+ # e.g. Omni/Bild.hs -> Omni/Bild
+ ns = Path(target).parent
+ if str(ns) != ".":
+ cmd.append(f"--namespace={ns}")
+
+ print(f"Creating task for {target}...") # noqa: T201
+ proc = subprocess.run(cmd, capture_output=True, text=True, check=False)
+
+ if proc.returncode != 0:
+ print(f"Error creating task: {proc.stderr}", file=sys.stderr) # noqa: T201
+ else:
+ # task create --json returns the created task json
+ print(f"Task created: {proc.stdout.strip()}") # noqa: T201
+
+
+def main() -> None:
+ """Run the build audit."""
+ parser = argparse.ArgumentParser(description="Audit codebase builds.")
+ parser.add_argument(
+ "--parent",
+ help="Parent task ID to link discovered tasks to",
+ )
+ parser.add_argument(
+ "paths",
+ nargs="*",
+ default=["."],
+ help="Paths to search for targets",
+ )
+ args = parser.parse_args()
+
+ # Check if bild is available
+ if not shutil.which("bild"):
+ print( # noqa: T201
+ "Warning: 'bild' command not found. Ensure it is in PATH.",
+ file=sys.stderr,
+ )
+
+ print(f"Scanning for targets in {args.paths}...") # noqa: T201
+ targets: list[str] = []
+ for path_str in args.paths:
+ path = Path(path_str)
+ if path.is_file():
+ targets.append(str(path))
+ else:
+ targets.extend(get_buildable_files(path_str))
+
+ # Remove duplicates
+ targets = sorted(set(targets))
+ print(f"Found {len(targets)} targets.") # noqa: T201
+
+ failures = 0
+ for target in targets:
+ res = run_bild(target)
+
+ if res.returncode == 0:
+ print("OK") # noqa: T201
+ else:
+ print("FAIL") # noqa: T201
+ failures += 1
+ create_task(target, res, args.parent)
+
+ print(f"\nAudit complete. {failures} failures found.") # noqa: T201
+ if failures > 0:
+ sys.exit(1)
+ else:
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Omni/Bild/audit.sh b/Omni/Bild/audit.sh
deleted file mode 100755
index 1a0acd5..0000000
--- a/Omni/Bild/audit.sh
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/env python3
-"""
-Audit codebase builds.
-
-Iterates through every namespace in the project and runs 'bild'.
-For every build failure encountered, it automatically creates a new task.
-"""
-
-# : out bild-audit
-
-import os
-import sys
-import subprocess
-import argparse
-import shutil
-import re
-
-# Extensions supported by bild (from Omni/Bild.hs and Omni/Namespace.hs)
-EXTENSIONS = {'.c', '.hs', '.lisp', '.nix', '.py', '.scm', '.rs', '.toml'}
-
-def strip_ansi(text):
- """Strip ANSI escape codes from text."""
- ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
- return ansi_escape.sub('', text)
-
-def is_ignored(path):
- """Check if a file is ignored by git."""
- res = subprocess.run(
- ['git', 'check-ignore', path],
- stdout=subprocess.DEVNULL,
- stderr=subprocess.DEVNULL
- )
- return res.returncode == 0
-
-def get_buildable_files(root_dir='.'):
- """Find all files that bild can build."""
- targets = []
- for root, dirs, files in os.walk(root_dir):
- # Skip hidden directories, build artifacts (_), and task db (.tasks)
- dirs[:] = [d for d in dirs if not d.startswith('.') and d != '_']
-
- for f in files:
- ext = os.path.splitext(f)[1]
- if ext in EXTENSIONS:
- path = os.path.join(root, f)
- # Clean up path
- if path.startswith('./'):
- path = path[2:]
-
- if not is_ignored(path):
- targets.append(path)
- return targets
-
-def run_bild(target):
- """Run bild on the target."""
- # --time 0 disables timeout
- # --loud enables output (which we capture)
- cmd = ['bild', '--time', '0', '--loud', target]
- result = subprocess.run(cmd, capture_output=True, text=True)
- return result
-
-def create_task(target, result, parent_id=None):
- """Create a task for a build failure."""
- # Construct a descriptive title
- # Try to get the last meaningful line of error output
- lines = (result.stdout + result.stderr).strip().split('\n')
- last_line = lines[-1] if lines else "Unknown error"
- last_line = strip_ansi(last_line).strip()
-
- if len(last_line) > 50:
- last_line = last_line[:47] + "..."
-
- title = f"Build failed: {target} - {last_line}"
-
- cmd = [
- 'task', 'create', title,
- '--priority', '2',
- '--json'
- ]
-
- if parent_id:
- cmd.append(f'--discovered-from={parent_id}')
-
- # Try to infer namespace
- parts = target.split('/')
- if len(parts) > 1:
- # e.g. Omni/Bild.hs -> Omni/Bild
- # Omni/Bild/Audit.py -> Omni/Bild
- ns = os.path.dirname(target)
- if ns:
- cmd.append(f'--namespace={ns}')
-
- print(f"Creating task for {target}...")
- proc = subprocess.run(cmd, capture_output=True, text=True)
-
- if proc.returncode != 0:
- print(f"Error creating task: {proc.stderr}", file=sys.stderr)
- else:
- # task create --json returns the created task json
- print(f"Task created: {proc.stdout.strip()}")
-
-def main():
- parser = argparse.ArgumentParser(description='Audit codebase builds.')
- parser.add_argument('--parent', help='Parent task ID to link discovered tasks to')
- parser.add_argument('paths', nargs='*', default=['.'], help='Paths to search for targets')
- args = parser.parse_args()
-
- # Check if bild is available
- if not shutil.which('bild'):
- print("Warning: 'bild' command not found. Ensure it is in PATH.", file=sys.stderr)
-
- print(f"Scanning for targets in {args.paths}...")
- targets = []
- for path in args.paths:
- if os.path.isfile(path):
- targets.append(path)
- else:
- targets.extend(get_buildable_files(path))
-
- # Remove duplicates
- targets = sorted(list(set(targets)))
- print(f"Found {len(targets)} targets.")
-
- failures = 0
- for i, target in enumerate(targets):
- print(f"[{i+1}/{len(targets)}] Building {target} ... ", end='', flush=True)
- res = run_bild(target)
-
- if res.returncode == 0:
- print("OK")
- else:
- print("FAIL")
- failures += 1
- create_task(target, res, args.parent)
-
- print(f"\nAudit complete. {failures} failures found.")
- if failures > 0:
- sys.exit(1)
- else:
- sys.exit(0)
-
-if __name__ == '__main__':
- main()