overwatcher-ai 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- overwatcher/__init__.py +24 -0
- overwatcher/__main__.py +8 -0
- overwatcher/cli.py +56 -0
- overwatcher/cross_examiner.py +226 -0
- overwatcher_ai-0.1.0.dist-info/METADATA +277 -0
- overwatcher_ai-0.1.0.dist-info/RECORD +10 -0
- overwatcher_ai-0.1.0.dist-info/WHEEL +5 -0
- overwatcher_ai-0.1.0.dist-info/entry_points.txt +2 -0
- overwatcher_ai-0.1.0.dist-info/licenses/LICENSE +21 -0
- overwatcher_ai-0.1.0.dist-info/top_level.txt +1 -0
overwatcher/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Overwatcher
|
|
3
|
+
Hierarchical Multi-Agent Supervisor & Adversarial Red-Team Cross-Examiner.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "0.1.0"
|
|
7
|
+
__author__ = "Fahad Bin Nasir"
|
|
8
|
+
|
|
9
|
+
from overwatcher.cross_examiner import (
|
|
10
|
+
CrossExaminer,
|
|
11
|
+
check_file_boundaries,
|
|
12
|
+
audit_diff_for_slop,
|
|
13
|
+
format_rejection_notice,
|
|
14
|
+
FORBIDDEN_DIFF_PATTERNS,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"__version__",
|
|
19
|
+
"CrossExaminer",
|
|
20
|
+
"check_file_boundaries",
|
|
21
|
+
"audit_diff_for_slop",
|
|
22
|
+
"format_rejection_notice",
|
|
23
|
+
"FORBIDDEN_DIFF_PATTERNS",
|
|
24
|
+
]
|
overwatcher/__main__.py
ADDED
overwatcher/cli.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Overwatcher CLI Entrypoint
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
from overwatcher.cross_examiner import CrossExaminer
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main(argv=None):
|
|
12
|
+
parser = argparse.ArgumentParser(
|
|
13
|
+
prog="overwatcher",
|
|
14
|
+
description="Overwatcher: Hierarchical Multi-Agent Supervisor & Adversarial Red-Team Cross-Examiner"
|
|
15
|
+
)
|
|
16
|
+
parser.add_argument("--worker", default="worker_subagent", help="Worker subagent ID or role")
|
|
17
|
+
parser.add_argument("--domain", default="core", help="Target domain name")
|
|
18
|
+
parser.add_argument("--allowed-files", nargs="*", default=[], help="Allowed file path glob patterns")
|
|
19
|
+
parser.add_argument("--verify-cmd", default="", help="Command to execute for verification (e.g. pytest, npm test)")
|
|
20
|
+
parser.add_argument("--repo-dir", default=".", help="Path to target git repository")
|
|
21
|
+
|
|
22
|
+
args = parser.parse_args(argv)
|
|
23
|
+
repo_dir = os.path.abspath(args.repo_dir)
|
|
24
|
+
|
|
25
|
+
print("==================================================")
|
|
26
|
+
print(" OVERWATCHER ADVERSARIAL CROSS-EXAMINATION ")
|
|
27
|
+
print("==================================================")
|
|
28
|
+
print(f"Worker Subagent : {args.worker}")
|
|
29
|
+
print(f"Target Domain : {args.domain}")
|
|
30
|
+
print(f"Repository Root : {repo_dir}")
|
|
31
|
+
print("--------------------------------------------------")
|
|
32
|
+
|
|
33
|
+
examiner = CrossExaminer(
|
|
34
|
+
repo_dir=repo_dir,
|
|
35
|
+
allowed_files=args.allowed_files,
|
|
36
|
+
verify_cmd=args.verify_cmd,
|
|
37
|
+
worker_id=args.worker,
|
|
38
|
+
domain=args.domain
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
passed, notice, flaws = examiner.run_audit()
|
|
42
|
+
|
|
43
|
+
if not passed:
|
|
44
|
+
print("\nADJUDICATION RESULT: REJECTED\n")
|
|
45
|
+
print(notice)
|
|
46
|
+
sys.exit(1)
|
|
47
|
+
else:
|
|
48
|
+
print("\nADJUDICATION RESULT: AUDITED & VERIFIED")
|
|
49
|
+
print("All contract boundaries respected. No slop anti-patterns detected.")
|
|
50
|
+
if args.verify_cmd:
|
|
51
|
+
print("Verification command passed with exit code 0.")
|
|
52
|
+
sys.exit(0)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
main()
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Overwatcher Cross-Examiner Engine
|
|
3
|
+
Deterministic Red-Team Auditor and Contract Validator for AI Multi-Agent Pipelines.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import fnmatch
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
import subprocess
|
|
10
|
+
import sys
|
|
11
|
+
from typing import List, Dict, Tuple, Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
FORBIDDEN_DIFF_PATTERNS = [
|
|
15
|
+
(r"^\+\s*except\s*:\s*pass", "Bare exception swallowing (`except: pass`)"),
|
|
16
|
+
(r"^\+\s*except\s+Exception\s*:\s*pass", "Exception swallowing (`except Exception: pass`)"),
|
|
17
|
+
(r"^\+\s*catch\s*\([^)]*\)\s*\{\s*\}", "Silent catch block (`catch (e) {}`)"),
|
|
18
|
+
(r"^\+\s*assert\s+True\b", "Trivial test assertion (`assert True`)"),
|
|
19
|
+
(r"^\+\s*assert\s+1\s*==\s*1\b", "Trivial test assertion (`assert 1 == 1`)"),
|
|
20
|
+
(r"^\+\s*expect\s*\(\s*true\s*\)\.toBe\s*\(\s*true\s*\)", "Trivial test assertion (`expect(true).toBe(true)`)"),
|
|
21
|
+
(r"^\+\s*debugger\b", "Leftover debugger statement"),
|
|
22
|
+
(r"^\+\s*breakpoint\(\)", "Leftover breakpoint() statement"),
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def run_command(cmd: str, cwd: Optional[str] = None) -> Tuple[int, str]:
|
|
27
|
+
"""Execute a shell command and return (exit_code, output)."""
|
|
28
|
+
try:
|
|
29
|
+
proc = subprocess.run(
|
|
30
|
+
cmd,
|
|
31
|
+
shell=True,
|
|
32
|
+
cwd=cwd,
|
|
33
|
+
stdout=subprocess.PIPE,
|
|
34
|
+
stderr=subprocess.STDOUT,
|
|
35
|
+
text=True,
|
|
36
|
+
encoding="utf-8",
|
|
37
|
+
errors="replace"
|
|
38
|
+
)
|
|
39
|
+
return proc.returncode, proc.stdout
|
|
40
|
+
except Exception as e:
|
|
41
|
+
return 1, str(e)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def get_git_modified_files(cwd: str) -> List[str]:
|
|
45
|
+
"""Return list of modified or untracked files relative to working tree."""
|
|
46
|
+
code, out = run_command("git status --porcelain", cwd=cwd)
|
|
47
|
+
files = []
|
|
48
|
+
if code == 0:
|
|
49
|
+
for line in out.splitlines():
|
|
50
|
+
line = line.strip()
|
|
51
|
+
if not line:
|
|
52
|
+
continue
|
|
53
|
+
parts = line[2:].strip().split(" -> ")
|
|
54
|
+
filepath = parts[-1].strip().strip('"')
|
|
55
|
+
files.append(filepath.replace("\\", "/"))
|
|
56
|
+
return sorted(list(set(files)))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def get_git_diff(cwd: str) -> str:
|
|
60
|
+
"""Return the current unstaged and staged git diff."""
|
|
61
|
+
code, out = run_command("git diff -U3 HEAD", cwd=cwd)
|
|
62
|
+
if code != 0 or not out.strip():
|
|
63
|
+
code, out = run_command("git diff -U3", cwd=cwd)
|
|
64
|
+
return out
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def check_file_boundaries(
|
|
68
|
+
modified_files: List[str],
|
|
69
|
+
allowed_patterns: List[str]
|
|
70
|
+
) -> List[str]:
|
|
71
|
+
"""Identify files modified outside the allowed contract boundaries."""
|
|
72
|
+
violations = []
|
|
73
|
+
for f in modified_files:
|
|
74
|
+
norm_f = f.replace("\\", "/")
|
|
75
|
+
matched = False
|
|
76
|
+
for pat in allowed_patterns:
|
|
77
|
+
pat = pat.replace("\\", "/").strip()
|
|
78
|
+
if not pat:
|
|
79
|
+
continue
|
|
80
|
+
if fnmatch.fnmatch(norm_f, pat) or fnmatch.fnmatch(os.path.basename(norm_f), pat):
|
|
81
|
+
matched = True
|
|
82
|
+
break
|
|
83
|
+
if not matched:
|
|
84
|
+
violations.append(norm_f)
|
|
85
|
+
return violations
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def audit_diff_for_slop(diff_text: str) -> List[Dict[str, str]]:
|
|
89
|
+
"""Inspect git diff for anti-patterns and forbidden shortcuts."""
|
|
90
|
+
issues = []
|
|
91
|
+
current_file = "unknown"
|
|
92
|
+
current_line = 0
|
|
93
|
+
|
|
94
|
+
for line in diff_text.splitlines():
|
|
95
|
+
if line.startswith("+++ b/"):
|
|
96
|
+
current_file = line[6:].strip()
|
|
97
|
+
current_line = 0
|
|
98
|
+
continue
|
|
99
|
+
elif line.startswith("@@"):
|
|
100
|
+
m = re.search(r"\+(\d+)", line)
|
|
101
|
+
if m:
|
|
102
|
+
current_line = int(m.group(1))
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
if line.startswith("+") and not line.startswith("+++"):
|
|
106
|
+
for pattern, description in FORBIDDEN_DIFF_PATTERNS:
|
|
107
|
+
if re.search(pattern, line):
|
|
108
|
+
issues.append({
|
|
109
|
+
"file": current_file,
|
|
110
|
+
"line": str(current_line),
|
|
111
|
+
"issue": description,
|
|
112
|
+
"evidence": line.strip()
|
|
113
|
+
})
|
|
114
|
+
current_line += 1
|
|
115
|
+
elif not line.startswith("-"):
|
|
116
|
+
current_line += 1
|
|
117
|
+
|
|
118
|
+
return issues
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def format_rejection_notice(
|
|
122
|
+
worker_id: str,
|
|
123
|
+
domain: str,
|
|
124
|
+
flaws: List[Dict[str, str]],
|
|
125
|
+
verification_cmd: str,
|
|
126
|
+
remediations: List[str]
|
|
127
|
+
) -> str:
|
|
128
|
+
"""Generate structured Overwatcher Rejection Notice."""
|
|
129
|
+
flaw_lines = []
|
|
130
|
+
for f in flaws:
|
|
131
|
+
flaw_lines.append(
|
|
132
|
+
f" - File: {f.get('file', 'N/A')}:{f.get('line', 'N/A')}\n"
|
|
133
|
+
f" Issue: {f.get('issue', 'Defect detected')}\n"
|
|
134
|
+
f" Evidence: `{f.get('evidence', '').strip()}`"
|
|
135
|
+
)
|
|
136
|
+
flaws_formatted = "\n".join(flaw_lines)
|
|
137
|
+
remedy_lines = [f" - {r}" for r in remediations]
|
|
138
|
+
remedy_formatted = "\n".join(remedy_lines)
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
f"[OVERWATCHER REJECTION NOTICE]\n"
|
|
142
|
+
f"Worker ID: {worker_id}\n"
|
|
143
|
+
f"Target Domain: {domain}\n"
|
|
144
|
+
f"Status: REJECTED — REWORK REQUIRED\n\n"
|
|
145
|
+
f"1. Flaws Detected:\n"
|
|
146
|
+
f"{flaws_formatted}\n\n"
|
|
147
|
+
f"2. Required Remediation:\n"
|
|
148
|
+
f"{remedy_formatted}\n\n"
|
|
149
|
+
f"Re-submit only after executing and passing: `{verification_cmd}`.\n"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class CrossExaminer:
|
|
154
|
+
"""
|
|
155
|
+
Programmatic Auditor for Python Multi-Agent Frameworks (LangGraph, CrewAI, AutoGen).
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def __init__(
|
|
159
|
+
self,
|
|
160
|
+
repo_dir: str = ".",
|
|
161
|
+
allowed_files: Optional[List[str]] = None,
|
|
162
|
+
verify_cmd: str = "",
|
|
163
|
+
worker_id: str = "worker_subagent",
|
|
164
|
+
domain: str = "core"
|
|
165
|
+
):
|
|
166
|
+
self.repo_dir = os.path.abspath(repo_dir)
|
|
167
|
+
self.allowed_files = allowed_files or []
|
|
168
|
+
self.verify_cmd = verify_cmd
|
|
169
|
+
self.worker_id = worker_id
|
|
170
|
+
self.domain = domain
|
|
171
|
+
|
|
172
|
+
def run_audit(self) -> Tuple[bool, Optional[str], List[Dict[str, str]]]:
|
|
173
|
+
"""
|
|
174
|
+
Executes cross-examination audit.
|
|
175
|
+
Returns:
|
|
176
|
+
Tuple of (is_passed: bool, rejection_notice: Optional[str], raw_flaws: List[Dict])
|
|
177
|
+
"""
|
|
178
|
+
flaws = []
|
|
179
|
+
remediations = []
|
|
180
|
+
|
|
181
|
+
# 1. Boundary Check
|
|
182
|
+
if self.allowed_files:
|
|
183
|
+
modified = get_git_modified_files(self.repo_dir)
|
|
184
|
+
violations = check_file_boundaries(modified, self.allowed_files)
|
|
185
|
+
if violations:
|
|
186
|
+
for v in violations:
|
|
187
|
+
flaws.append({
|
|
188
|
+
"file": v,
|
|
189
|
+
"line": "1",
|
|
190
|
+
"issue": "Contract Boundary Breach: Unauthorized file modified outside worker contract",
|
|
191
|
+
"evidence": f"Modified file '{v}' is not in allowed list: {self.allowed_files}"
|
|
192
|
+
})
|
|
193
|
+
remediations.append("Revert changes in unauthorized files using `git checkout -- <file>`.")
|
|
194
|
+
|
|
195
|
+
# 2. Diff Slop & Anti-pattern Check
|
|
196
|
+
diff_content = get_git_diff(self.repo_dir)
|
|
197
|
+
if diff_content:
|
|
198
|
+
diff_issues = audit_diff_for_slop(diff_content)
|
|
199
|
+
if diff_issues:
|
|
200
|
+
flaws.extend(diff_issues)
|
|
201
|
+
remediations.append("Remove all silent exception catchers, trivial assertions, or leftover debuggers.")
|
|
202
|
+
|
|
203
|
+
# 3. Verification Command Check
|
|
204
|
+
if self.verify_cmd:
|
|
205
|
+
code, out = run_command(self.verify_cmd, cwd=self.repo_dir)
|
|
206
|
+
if code != 0:
|
|
207
|
+
flaws.append({
|
|
208
|
+
"file": "Workspace Test Suite",
|
|
209
|
+
"line": "N/A",
|
|
210
|
+
"issue": f"Verification command failed with exit code {code}",
|
|
211
|
+
"evidence": "\n".join(out.strip().splitlines()[-10:])
|
|
212
|
+
})
|
|
213
|
+
remediations.append(f"Fix failing test cases and ensure `{self.verify_cmd}` exits 0.")
|
|
214
|
+
|
|
215
|
+
# 4. Adjudication
|
|
216
|
+
if flaws:
|
|
217
|
+
notice = format_rejection_notice(
|
|
218
|
+
worker_id=self.worker_id,
|
|
219
|
+
domain=self.domain,
|
|
220
|
+
flaws=flaws,
|
|
221
|
+
verification_cmd=self.verify_cmd or "git diff",
|
|
222
|
+
remediations=remediations
|
|
223
|
+
)
|
|
224
|
+
return False, notice, flaws
|
|
225
|
+
else:
|
|
226
|
+
return True, None, []
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: overwatcher-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Hierarchical Multi-Agent Supervisor & Adversarial Red-Team Cross-Examiner
|
|
5
|
+
Author-email: Fahad Bin Nasir <fahad@fahadbinnasir.tech>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/FahadBinNasir/overwatcher
|
|
8
|
+
Project-URL: Documentation, https://github.com/FahadBinNasir/overwatcher#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/FahadBinNasir/overwatcher
|
|
10
|
+
Project-URL: Issues, https://github.com/FahadBinNasir/overwatcher/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/FahadBinNasir/overwatcher/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: ai-agents,multi-agent,supervisor,cross-examiner,orchestrator,red-team,code-review,claude-code,antigravity,llm-ops
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Operating System :: OS Independent
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
<div align="center">
|
|
31
|
+
|
|
32
|
+
<img src="assets/banner.svg" alt="Overwatcher - Hierarchical Multi-Agent Supervisor" width="100%" />
|
|
33
|
+
|
|
34
|
+
# <img src="assets/icons/logo.svg" width="32" height="32" align="center" alt="" /> Overwatcher
|
|
35
|
+
|
|
36
|
+
**A supervisor skill for multi-agent coding workflows. Splits work into disjoint file domains, then rejects worker output that breaks its contract or fails verification.**
|
|
37
|
+
|
|
38
|
+
[](LICENSE)
|
|
39
|
+
[](https://python.org)
|
|
40
|
+
|
|
41
|
+
[Quick start](#quick-start) · [How it works](#how-it-works) · [CLI](#cross-examiner-cli) · [Examples](#examples) · [Contributing](#contributing)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Why
|
|
48
|
+
|
|
49
|
+
Unsupervised agent pipelines tend to fail in three ways:
|
|
50
|
+
|
|
51
|
+
- **Drift:** workers edit files outside their task and break shared config.
|
|
52
|
+
- **Collisions:** parallel workers edit the same files and create merge conflicts.
|
|
53
|
+
- **False "done":** workers report "all tests pass" after deleting assertions, adding `assert True`, or wrapping errors in `except: pass`.
|
|
54
|
+
|
|
55
|
+
Overwatcher counters each:
|
|
56
|
+
|
|
57
|
+
| Failure | Defense |
|
|
58
|
+
| :-- | :-- |
|
|
59
|
+
| Drift | Per-worker contract listing authorized files; out-of-scope diffs are rejected |
|
|
60
|
+
| Collisions | Contracts are disjoint; no two workers share a file |
|
|
61
|
+
| False "done" | Claims are ignored. The diff is scanned for known shortcuts and a verify command must exit 0 |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Quick start
|
|
66
|
+
|
|
67
|
+
### 1. Install CLI & Python package
|
|
68
|
+
```bash
|
|
69
|
+
# Install via pip:
|
|
70
|
+
pip install overwatcher-ai
|
|
71
|
+
|
|
72
|
+
# Or install directly from GitHub:
|
|
73
|
+
pip install git+https://github.com/FahadBinNasir/overwatcher.git
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 2. Install as an Agent Skill
|
|
77
|
+
Claude Code shown; other platforms [below](#platform-install-paths):
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
mkdir -p .claude/skills/overwatcher
|
|
81
|
+
cp SKILL.md .claude/skills/overwatcher/SKILL.md
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Then ask your agent:
|
|
85
|
+
|
|
86
|
+
> Use the overwatcher skill to refactor auth and the DB layer in parallel.
|
|
87
|
+
|
|
88
|
+
The agent acts as supervisor: it partitions the task, dispatches workers, audits each result, and returns a verification report.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## How it works
|
|
93
|
+
|
|
94
|
+
```mermaid
|
|
95
|
+
flowchart TD
|
|
96
|
+
A[1. Partition & contracts] --> B[2. Parallel dispatch]
|
|
97
|
+
B --> C[3. Cross-examination]
|
|
98
|
+
C -->|fail| D[Rejection notice]
|
|
99
|
+
D --> B
|
|
100
|
+
C -->|pass| E[4. Synthesis & report]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Rules
|
|
104
|
+
|
|
105
|
+
1. **No trust in summaries.** Output is unverified until inspected and executed.
|
|
106
|
+
2. **Adversarial review.** Look for edge cases, race conditions, leaks, and swallowed errors.
|
|
107
|
+
3. **Disjoint ownership.** Workers never touch overlapping files.
|
|
108
|
+
4. **Reject, don't patch.** Send failures back with line-numbered proof. The supervisor only patches after repeated worker failures.
|
|
109
|
+
|
|
110
|
+
### Phases
|
|
111
|
+
|
|
112
|
+
**1. Partition.** Split the goal into 2–4 independent domains (e.g. Auth, DB, API, UI). Give each worker a [contract](templates/worker_contract.md):
|
|
113
|
+
- *Authorized targets:* exact file paths
|
|
114
|
+
- *Acceptance criteria:* deliverables and test targets
|
|
115
|
+
- *Forbidden:* mock fallbacks, leaked secrets, API breakage
|
|
116
|
+
|
|
117
|
+
**2. Dispatch.** Start workers concurrently with domain-specific prompts. Wait on completion signals; don't poll.
|
|
118
|
+
|
|
119
|
+
**3. Cross-examine.** When a worker reports done:
|
|
120
|
+
1. **Diff:** confirm changes stay inside the contract; reject mocks, boilerplate, and new dependencies. The CLI automates the file-boundary and pattern checks.
|
|
121
|
+
2. **Build:** run the project's compilers and linters (`tsc --noEmit`, `ruff`, `flake8`, ...).
|
|
122
|
+
3. **Test:** run the targeted tests; check that assertions are real.
|
|
123
|
+
4. **Verdict:** `REJECTION NOTICE` on any defect, otherwise `AUDITED & VERIFIED`.
|
|
124
|
+
|
|
125
|
+
**4. Synthesize.** Run the full regression suite, then produce the [master report](templates/master_adjudication_report.md) with logs.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Cross-examiner CLI
|
|
130
|
+
|
|
131
|
+
Run via the installed `overwatcher` command or directly via `scripts/cross_examiner.py`. It requires only Python 3.8+ and git; no LLM needed.
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Run via installed CLI:
|
|
135
|
+
overwatcher \
|
|
136
|
+
--worker "auth_guard" \
|
|
137
|
+
--domain "Authentication" \
|
|
138
|
+
--allowed-files "src/core/auth.py" "tests/test_auth.py" \
|
|
139
|
+
--verify-cmd "pytest tests/test_auth.py -v" \
|
|
140
|
+
--repo-dir .
|
|
141
|
+
|
|
142
|
+
# Or run via standalone script:
|
|
143
|
+
python scripts/cross_examiner.py ...
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Flag | Default | Purpose |
|
|
147
|
+
| :-- | :-- | :-- |
|
|
148
|
+
| `--worker` | `worker_subagent` | Worker ID, shown in the notice |
|
|
149
|
+
| `--domain` | `core` | Domain name, shown in the notice |
|
|
150
|
+
| `--allowed-files` | none | Glob patterns the worker may change. Boundary check is skipped if empty |
|
|
151
|
+
| `--verify-cmd` | none | Shell command that must exit 0 |
|
|
152
|
+
| `--repo-dir` | `.` | Git repository to audit |
|
|
153
|
+
|
|
154
|
+
**Checks**
|
|
155
|
+
1. **Boundaries:** files from `git status` must match an allowed glob (full path or basename, via `fnmatch`).
|
|
156
|
+
2. **Diff patterns:** added lines in `git diff HEAD` are regex-scanned for:
|
|
157
|
+
- `except: pass`, `except Exception: pass`, empty `catch (...) {}`
|
|
158
|
+
- `assert True`, `assert 1 == 1`, `expect(true).toBe(true)`
|
|
159
|
+
- `debugger`, `breakpoint()`
|
|
160
|
+
3. **Verify command:** run in the repo; non-zero exit is a failure (last 10 output lines are reported).
|
|
161
|
+
|
|
162
|
+
**Exit codes:** `0` = `AUDITED & VERIFIED`, `1` = `REJECTED` (prints a rejection notice).
|
|
163
|
+
|
|
164
|
+
### Limitations
|
|
165
|
+
- Pattern matching is regex on diff text, not AST analysis. It catches common shortcuts, not all.
|
|
166
|
+
- Audits the **working tree** against `HEAD`. Uncommitted changes only.
|
|
167
|
+
- With parallel workers in one working tree, each audit sees the others' edits as violations. Give each worker its own `git worktree` or branch.
|
|
168
|
+
- Basename matching means `auth.py` also matches `other/dir/auth.py`. Use full-path globs.
|
|
169
|
+
- Untracked files count toward the boundary check, but their contents are not pattern-scanned.
|
|
170
|
+
- `--verify-cmd` runs with `shell=True`. Pass only trusted commands.
|
|
171
|
+
- Linters and builds run only if you put them in `--verify-cmd`.
|
|
172
|
+
|
|
173
|
+
Run its tests:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
python tests/test_cross_examiner.py
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Platform install paths
|
|
182
|
+
|
|
183
|
+
| Platform | Target |
|
|
184
|
+
| :-- | :-- |
|
|
185
|
+
| Claude Code | `.claude/skills/overwatcher/SKILL.md` |
|
|
186
|
+
| Antigravity | `.agents/skills/overwatcher/SKILL.md` |
|
|
187
|
+
| Cursor | `.cursor/rules/overwatcher.mdc` |
|
|
188
|
+
| Cline / Roo-Code | `.clinerules` or `.roomodes` |
|
|
189
|
+
| OpenHands | `.openhands/microagents/overwatcher.md` |
|
|
190
|
+
| LangGraph / CrewAI | Call `scripts/cross_examiner.py` from a supervisor node |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Message formats
|
|
195
|
+
|
|
196
|
+
<details>
|
|
197
|
+
<summary><b>Rejection notice</b> (sent to a worker on failure)</summary>
|
|
198
|
+
|
|
199
|
+
```markdown
|
|
200
|
+
[OVERWATCHER REJECTION NOTICE]
|
|
201
|
+
Worker ID: {worker_name}
|
|
202
|
+
Target Domain: {domain_name}
|
|
203
|
+
Status: REJECTED — REWORK REQUIRED
|
|
204
|
+
|
|
205
|
+
1. Flaws Detected:
|
|
206
|
+
- File: {file_path}:{line_number}
|
|
207
|
+
Issue: {defect}
|
|
208
|
+
Evidence: {failing_test_output_or_diff_snippet}
|
|
209
|
+
|
|
210
|
+
2. Required Remediation:
|
|
211
|
+
- {instruction}
|
|
212
|
+
|
|
213
|
+
Re-submit only after passing: `{verification_command}`.
|
|
214
|
+
```
|
|
215
|
+
</details>
|
|
216
|
+
|
|
217
|
+
<details>
|
|
218
|
+
<summary><b>Master report</b> (delivered to the user)</summary>
|
|
219
|
+
|
|
220
|
+
```markdown
|
|
221
|
+
# Overwatcher Master Verification Report
|
|
222
|
+
|
|
223
|
+
## Summary
|
|
224
|
+
- Domains audited: 2
|
|
225
|
+
- Workers: 2
|
|
226
|
+
- Cross-examination rounds: 3
|
|
227
|
+
- Status: VERIFIED / ZERO REGRESSIONS
|
|
228
|
+
|
|
229
|
+
## Breakdown
|
|
230
|
+
| Domain | Worker | Files | Status | Evidence |
|
|
231
|
+
| :-- | :-- | :-- | :-- | :-- |
|
|
232
|
+
| Auth | auth_guard | src/core/auth.py | PASSED | 8/8 tests |
|
|
233
|
+
| DB | db_reliability | src/core/db.py | PASSED | 14/14 tests |
|
|
234
|
+
```
|
|
235
|
+
</details>
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Examples
|
|
240
|
+
|
|
241
|
+
| File | Shows |
|
|
242
|
+
| :-- | :-- |
|
|
243
|
+
| [sample_workflow.md](examples/sample_workflow.md) | End-to-end supervised refactor |
|
|
244
|
+
| [sample_worker_contract.md](examples/sample_worker_contract.md) | A filled-in contract |
|
|
245
|
+
| [sample_rejection_order.md](examples/sample_rejection_order.md) | A real rejection notice |
|
|
246
|
+
| [sample_adjudication_report.md](examples/sample_adjudication_report.md) | A passing report |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Repository layout
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
pyproject.toml # PEP 517 / PEP 621 package config
|
|
254
|
+
SKILL.md # skill spec
|
|
255
|
+
src/overwatcher/ # core Python package & CLI implementation
|
|
256
|
+
templates/ # contract, rejection, report templates
|
|
257
|
+
scripts/ # standalone wrapper script
|
|
258
|
+
tests/ # cross_examiner tests
|
|
259
|
+
examples/ # worked examples
|
|
260
|
+
assets/ # logo, icons, and social banner
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Contributing
|
|
266
|
+
|
|
267
|
+
New audit rules, heuristics, and language support are welcome.
|
|
268
|
+
|
|
269
|
+
1. Fork and branch: `git checkout -b feature/audit-rule`
|
|
270
|
+
2. Add tests; run `python tests/test_cross_examiner.py`
|
|
271
|
+
3. Open a PR
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## License
|
|
276
|
+
|
|
277
|
+
[MIT](LICENSE) © 2026 Fahad Bin Nasir
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
overwatcher/__init__.py,sha256=-NyKo19LfT5Axr1zdpQqWHaBOBh6cqPCH8MAcEjFjsE,495
|
|
2
|
+
overwatcher/__main__.py,sha256=lON8or9P7JsGWExO7A7UGYPWajFPrkMxZ2h-8dAfJ08,136
|
|
3
|
+
overwatcher/cli.py,sha256=y7wgJVxLafpTAs5KGiFxO-PQSixj0Wluine8gZT2H6w,1967
|
|
4
|
+
overwatcher/cross_examiner.py,sha256=cQ35W08gFgjIfXxZyN5iyNwaNGKban_mqfT9Hgegvx4,7950
|
|
5
|
+
overwatcher_ai-0.1.0.dist-info/licenses/LICENSE,sha256=q6KZghm-d6Y0EW7FTs40_gShXXYPmXdUzBe9POhECLk,1072
|
|
6
|
+
overwatcher_ai-0.1.0.dist-info/METADATA,sha256=avfQ2Vb8I-YBLhmqLzICxb6qZPdXnOnE_IOSsAOuEXM,9826
|
|
7
|
+
overwatcher_ai-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
8
|
+
overwatcher_ai-0.1.0.dist-info/entry_points.txt,sha256=VBksf8YGLl0ZDEJxP8BlhP0GVb2NTd8Luy2f8PbMlco,53
|
|
9
|
+
overwatcher_ai-0.1.0.dist-info/top_level.txt,sha256=J8aI7PPGAZpBfgokKnSsCrAI1nCnEACauHsVpjP01ow,12
|
|
10
|
+
overwatcher_ai-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fahad Bin Nasir
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
overwatcher
|