diff options
| author | Omni Worker <bot@omni.agent> | 2025-11-22 06:39:54 -0500 |
|---|---|---|
| committer | Omni Worker <bot@omni.agent> | 2025-11-22 06:39:54 -0500 |
| commit | 242903ce18b3a85f45db1888f8944ab036d5df23 (patch) | |
| tree | 07fd8fcbc3e22101836779b9d4e297ffe425854d | |
| parent | 6f4b2c97a24967508f3970b46999052fd1f44e67 (diff) | |
feat: implement t-rWcmRMaWX.4
| -rw-r--r-- | .tasks/tasks.jsonl | 1 | ||||
| -rwxr-xr-x | Omni/Bild/audit.sh | 143 |
2 files changed, 144 insertions, 0 deletions
diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl index d92021c..90f23d5 100644 --- a/.tasks/tasks.jsonl +++ b/.tasks/tasks.jsonl @@ -170,3 +170,4 @@ {"taskCreatedAt":"2025-11-22T02:26:44.02456019Z","taskDependencies":[],"taskDescription":"Modify Omni/Agent/Git.hs to check for .git/rebase-merge or .git/rebase-apply before running git rebase --abort. This avoids blindly running abort commands.","taskId":"t-rWbPQPLps","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Detect in-progress rebase before aborting in Agent","taskType":"WorkTask","taskUpdatedAt":"2025-11-22T02:27:45.377866012Z"} {"taskCreatedAt":"2025-11-22T03:01:36.84628158Z","taskDependencies":[],"taskDescription":"Modify Omni/Agent/Worker.hs to check if the task branch already exists before trying to create it. If it exists, simply checkout the branch. This prevents 'fatal: a branch named ... already exists' errors when restarting the worker.","taskId":"t-rWbS8t1Wv","taskNamespace":"Omni/Agent.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Handle existing task branch in Worker Agent","taskType":"WorkTask","taskUpdatedAt":"2025-11-22T03:02:31.746506652Z"} {"taskCreatedAt":"2025-11-22T03:09:54.022974779Z","taskDependencies":[],"taskDescription":"Implement the 2-line status UI described in Omni/Agent/DESIGN.md (Section 4.3). It should reserve 2 lines at the bottom for Meta (Task ID, Time) and Activity (current thought/action), allowing history to scroll above. Use ANSI codes for cursor management.","taskId":"t-rWbSG78jq","taskNamespace":"Omni/Agent/Log.hs","taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"Implement 2-line Agent Status UI","taskType":"WorkTask","taskUpdatedAt":"2025-11-22T03:21:54.480763142Z"} +{"taskCreatedAt":"2025-11-22T11:34:17.854509264Z","taskDependencies":[],"taskDescription":null,"taskId":"t-rWcpIf5ov","taskNamespace":null,"taskParent":null,"taskPriority":"P2","taskStatus":"Done","taskTitle":"--help","taskType":"WorkTask","taskUpdatedAt":"2025-11-22T11:39:43.304029721Z"} diff --git a/Omni/Bild/audit.sh b/Omni/Bild/audit.sh new file mode 100755 index 0000000..1a0acd5 --- /dev/null +++ b/Omni/Bild/audit.sh @@ -0,0 +1,143 @@ +#!/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() |
