summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmni Worker <bot@omni.agent>2025-11-22 06:39:54 -0500
committerOmni Worker <bot@omni.agent>2025-11-22 06:39:54 -0500
commit242903ce18b3a85f45db1888f8944ab036d5df23 (patch)
tree07fd8fcbc3e22101836779b9d4e297ffe425854d
parent6f4b2c97a24967508f3970b46999052fd1f44e67 (diff)
feat: implement t-rWcmRMaWX.4
-rw-r--r--.tasks/tasks.jsonl1
-rwxr-xr-xOmni/Bild/audit.sh143
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()