adversarial-workflow 0.6.5__tar.gz → 0.7.0__tar.gz
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.
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/PKG-INFO +3 -1
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/__init__.py +1 -1
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/cli.py +159 -1
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/evaluators/runner.py +1 -0
- adversarial_workflow-0.7.0/adversarial_workflow/utils/citations.py +643 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/PKG-INFO +3 -1
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/SOURCES.txt +2 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/requires.txt +2 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/pyproject.toml +4 -1
- adversarial_workflow-0.7.0/tests/test_citations.py +525 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/LICENSE +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/README.md +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/__main__.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/evaluators/__init__.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/evaluators/builtins.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/evaluators/config.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/evaluators/discovery.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/.aider.conf.yml.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/.env.example.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/README.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/agent-context/AGENT-SYSTEM-GUIDE.md +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/agent-context/README.md.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/agent-context/agent-handoffs-minimal.json.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/agent-context/agent-handoffs.json.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/agent-context/current-state.json.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/config.yml.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/evaluate_plan.sh.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/example-task.md.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/proofread_content.sh.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/review_implementation.sh.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/templates/validate_tests.sh.template +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/utils/__init__.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/utils/colors.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/utils/config.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/utils/file_splitter.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow/utils/validation.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/dependency_links.txt +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/entry_points.txt +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/adversarial_workflow.egg-info/top_level.txt +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/setup.cfg +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/setup.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_cli.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_cli_dynamic_commands.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_config.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_env_loading.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_evaluate.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_evaluator_config.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_evaluator_discovery.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_evaluator_runner.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_file_splitter.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_list_evaluators.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_python_version.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_scripts_project.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_split_command.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_timeout_integration.py +0 -0
- {adversarial_workflow-0.6.5 → adversarial_workflow-0.7.0}/tests/test_utils_validation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: adversarial-workflow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Multi-stage AI evaluation system for task plans, code review, and test validation
|
|
5
5
|
Author: Fredrik Matheson
|
|
6
6
|
License: MIT
|
|
@@ -24,9 +24,11 @@ License-File: LICENSE
|
|
|
24
24
|
Requires-Dist: pyyaml>=6.0
|
|
25
25
|
Requires-Dist: python-dotenv>=0.19.0
|
|
26
26
|
Requires-Dist: aider-chat>=0.86.0
|
|
27
|
+
Requires-Dist: aiohttp>=3.8.0
|
|
27
28
|
Provides-Extra: dev
|
|
28
29
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
29
30
|
Requires-Dist: pytest-cov>=3.0; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
30
32
|
Requires-Dist: black>=22.0; extra == "dev"
|
|
31
33
|
Requires-Dist: isort>=5.0; extra == "dev"
|
|
32
34
|
Requires-Dist: flake8>=4.0; extra == "dev"
|
|
@@ -13,6 +13,7 @@ Commands:
|
|
|
13
13
|
review - Run Phase 3: Code review
|
|
14
14
|
validate - Run Phase 4: Test validation
|
|
15
15
|
split - Split large task files into smaller evaluable chunks
|
|
16
|
+
check-citations - Verify URLs in documents before evaluation
|
|
16
17
|
"""
|
|
17
18
|
|
|
18
19
|
import argparse
|
|
@@ -29,7 +30,7 @@ from typing import Dict, List, Optional, Tuple
|
|
|
29
30
|
import yaml
|
|
30
31
|
from dotenv import dotenv_values, load_dotenv
|
|
31
32
|
|
|
32
|
-
__version__ = "0.
|
|
33
|
+
__version__ = "0.7.0"
|
|
33
34
|
|
|
34
35
|
# ANSI color codes for better output
|
|
35
36
|
RESET = "\033[0m"
|
|
@@ -2819,6 +2820,106 @@ def list_evaluators() -> int:
|
|
|
2819
2820
|
return 0
|
|
2820
2821
|
|
|
2821
2822
|
|
|
2823
|
+
def check_citations(
|
|
2824
|
+
file_path: str,
|
|
2825
|
+
output_tasks: Optional[str] = None,
|
|
2826
|
+
mark_inline: bool = False,
|
|
2827
|
+
concurrency: int = 10,
|
|
2828
|
+
timeout: int = 10,
|
|
2829
|
+
) -> int:
|
|
2830
|
+
"""
|
|
2831
|
+
Check citations (URLs) in a document.
|
|
2832
|
+
|
|
2833
|
+
Args:
|
|
2834
|
+
file_path: Path to document to check
|
|
2835
|
+
output_tasks: Optional path to write blocked URL tasks
|
|
2836
|
+
mark_inline: Whether to mark URLs inline with status badges
|
|
2837
|
+
concurrency: Maximum concurrent URL checks
|
|
2838
|
+
timeout: Timeout per URL in seconds
|
|
2839
|
+
|
|
2840
|
+
Returns:
|
|
2841
|
+
0 on success, 1 on error
|
|
2842
|
+
"""
|
|
2843
|
+
from adversarial_workflow.utils.citations import (
|
|
2844
|
+
URLStatus,
|
|
2845
|
+
check_urls,
|
|
2846
|
+
extract_urls,
|
|
2847
|
+
generate_blocked_tasks,
|
|
2848
|
+
mark_urls_inline,
|
|
2849
|
+
print_verification_summary,
|
|
2850
|
+
)
|
|
2851
|
+
|
|
2852
|
+
# Check file exists
|
|
2853
|
+
if not os.path.exists(file_path):
|
|
2854
|
+
print(f"{RED}Error: File not found: {file_path}{RESET}")
|
|
2855
|
+
return 1
|
|
2856
|
+
|
|
2857
|
+
# Validate parameters
|
|
2858
|
+
if concurrency < 1:
|
|
2859
|
+
print(f"{RED}Error: Concurrency must be at least 1, got {concurrency}{RESET}")
|
|
2860
|
+
return 1
|
|
2861
|
+
if timeout < 1:
|
|
2862
|
+
print(f"{RED}Error: Timeout must be at least 1 second, got {timeout}{RESET}")
|
|
2863
|
+
return 1
|
|
2864
|
+
|
|
2865
|
+
print(f"🔗 Checking citations in: {file_path}")
|
|
2866
|
+
print()
|
|
2867
|
+
|
|
2868
|
+
# Read document
|
|
2869
|
+
with open(file_path, encoding="utf-8") as f:
|
|
2870
|
+
document = f.read()
|
|
2871
|
+
|
|
2872
|
+
# Extract URLs
|
|
2873
|
+
extracted = extract_urls(document)
|
|
2874
|
+
urls = [e.url for e in extracted]
|
|
2875
|
+
|
|
2876
|
+
if not urls:
|
|
2877
|
+
print(f"{YELLOW}No URLs found in document.{RESET}")
|
|
2878
|
+
return 0
|
|
2879
|
+
|
|
2880
|
+
print(f" Found {len(urls)} URLs to check")
|
|
2881
|
+
print(f" Checking with concurrency={concurrency}, timeout={timeout}s...")
|
|
2882
|
+
print()
|
|
2883
|
+
|
|
2884
|
+
# Check URLs
|
|
2885
|
+
results = check_urls(
|
|
2886
|
+
urls,
|
|
2887
|
+
concurrency=concurrency,
|
|
2888
|
+
timeout=timeout,
|
|
2889
|
+
)
|
|
2890
|
+
|
|
2891
|
+
# Print summary
|
|
2892
|
+
print_verification_summary(results)
|
|
2893
|
+
|
|
2894
|
+
# Count blocked/broken
|
|
2895
|
+
blocked_count = sum(1 for r in results if r.status in (URLStatus.BLOCKED, URLStatus.BROKEN))
|
|
2896
|
+
|
|
2897
|
+
# Mark document inline if requested
|
|
2898
|
+
if mark_inline and results:
|
|
2899
|
+
marked_document = mark_urls_inline(document, results)
|
|
2900
|
+
if marked_document != document:
|
|
2901
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
2902
|
+
f.write(marked_document)
|
|
2903
|
+
print("\n ✅ Updated document with status badges")
|
|
2904
|
+
|
|
2905
|
+
# Generate blocked tasks if requested or if there are blocked URLs
|
|
2906
|
+
if blocked_count > 0:
|
|
2907
|
+
if output_tasks:
|
|
2908
|
+
output_path = Path(output_tasks)
|
|
2909
|
+
else:
|
|
2910
|
+
# Default to .adversarial/blocked-citations/
|
|
2911
|
+
output_dir = Path.cwd() / ".adversarial" / "blocked-citations"
|
|
2912
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
2913
|
+
base_name = Path(file_path).stem
|
|
2914
|
+
output_path = output_dir / f"{base_name}-blocked-urls.md"
|
|
2915
|
+
|
|
2916
|
+
task_content = generate_blocked_tasks(results, file_path, output_path)
|
|
2917
|
+
if task_content:
|
|
2918
|
+
print(f" 📋 Blocked URL tasks: {output_path}")
|
|
2919
|
+
|
|
2920
|
+
return 0
|
|
2921
|
+
|
|
2922
|
+
|
|
2822
2923
|
def main():
|
|
2823
2924
|
"""Main CLI entry point."""
|
|
2824
2925
|
import logging
|
|
@@ -2862,6 +2963,7 @@ def main():
|
|
|
2862
2963
|
"validate",
|
|
2863
2964
|
"review",
|
|
2864
2965
|
"list-evaluators",
|
|
2966
|
+
"check-citations",
|
|
2865
2967
|
}
|
|
2866
2968
|
|
|
2867
2969
|
parser = argparse.ArgumentParser(
|
|
@@ -2879,6 +2981,7 @@ Examples:
|
|
|
2879
2981
|
adversarial review # Review implementation
|
|
2880
2982
|
adversarial validate "npm test" # Validate with tests
|
|
2881
2983
|
adversarial split large-task.md # Split large files
|
|
2984
|
+
adversarial check-citations doc.md # Verify URLs in document
|
|
2882
2985
|
|
|
2883
2986
|
For more information: https://github.com/movito/adversarial-workflow
|
|
2884
2987
|
""",
|
|
@@ -2961,6 +3064,38 @@ For more information: https://github.com/movito/adversarial-workflow
|
|
|
2961
3064
|
help="List all available evaluators (built-in and local)",
|
|
2962
3065
|
)
|
|
2963
3066
|
|
|
3067
|
+
# check-citations command
|
|
3068
|
+
citations_parser = subparsers.add_parser(
|
|
3069
|
+
"check-citations",
|
|
3070
|
+
help="Verify URLs in a document before evaluation",
|
|
3071
|
+
)
|
|
3072
|
+
citations_parser.add_argument("file", help="Document to check citations in")
|
|
3073
|
+
citations_parser.add_argument(
|
|
3074
|
+
"--output-tasks",
|
|
3075
|
+
"-o",
|
|
3076
|
+
help="Output file for blocked URL tasks (markdown)",
|
|
3077
|
+
)
|
|
3078
|
+
citations_parser.add_argument(
|
|
3079
|
+
"--mark-inline",
|
|
3080
|
+
action="store_true",
|
|
3081
|
+
default=False,
|
|
3082
|
+
help="Mark URLs inline with status badges (modifies document)",
|
|
3083
|
+
)
|
|
3084
|
+
citations_parser.add_argument(
|
|
3085
|
+
"--concurrency",
|
|
3086
|
+
"-c",
|
|
3087
|
+
type=int,
|
|
3088
|
+
default=10,
|
|
3089
|
+
help="Maximum concurrent URL checks (default: 10)",
|
|
3090
|
+
)
|
|
3091
|
+
citations_parser.add_argument(
|
|
3092
|
+
"--timeout",
|
|
3093
|
+
"-t",
|
|
3094
|
+
type=int,
|
|
3095
|
+
default=10,
|
|
3096
|
+
help="Timeout per URL in seconds (default: 10)",
|
|
3097
|
+
)
|
|
3098
|
+
|
|
2964
3099
|
# Dynamic evaluator registration
|
|
2965
3100
|
try:
|
|
2966
3101
|
evaluators = get_all_evaluators()
|
|
@@ -3009,6 +3144,11 @@ For more information: https://github.com/movito/adversarial-workflow
|
|
|
3009
3144
|
default=None,
|
|
3010
3145
|
help="Timeout in seconds (default: from evaluator config or 180, max: 600)",
|
|
3011
3146
|
)
|
|
3147
|
+
eval_parser.add_argument(
|
|
3148
|
+
"--check-citations",
|
|
3149
|
+
action="store_true",
|
|
3150
|
+
help="Verify URLs in document before evaluation",
|
|
3151
|
+
)
|
|
3012
3152
|
# Store config for later execution
|
|
3013
3153
|
eval_parser.set_defaults(evaluator_config=config)
|
|
3014
3154
|
|
|
@@ -3044,6 +3184,16 @@ For more information: https://github.com/movito/adversarial-workflow
|
|
|
3044
3184
|
# Log actual timeout and source
|
|
3045
3185
|
print(f"Using timeout: {timeout}s ({source})")
|
|
3046
3186
|
|
|
3187
|
+
# Check citations first if requested (read-only, doesn't modify file)
|
|
3188
|
+
if getattr(args, "check_citations", False):
|
|
3189
|
+
print()
|
|
3190
|
+
result = check_citations(args.file, mark_inline=False)
|
|
3191
|
+
if result != 0:
|
|
3192
|
+
print(
|
|
3193
|
+
f"{YELLOW}Warning: Citation check had issues, continuing with evaluation...{RESET}"
|
|
3194
|
+
)
|
|
3195
|
+
print()
|
|
3196
|
+
|
|
3047
3197
|
return run_evaluator(
|
|
3048
3198
|
args.evaluator_config,
|
|
3049
3199
|
args.file,
|
|
@@ -3083,6 +3233,14 @@ For more information: https://github.com/movito/adversarial-workflow
|
|
|
3083
3233
|
)
|
|
3084
3234
|
elif args.command == "list-evaluators":
|
|
3085
3235
|
return list_evaluators()
|
|
3236
|
+
elif args.command == "check-citations":
|
|
3237
|
+
return check_citations(
|
|
3238
|
+
args.file,
|
|
3239
|
+
output_tasks=args.output_tasks,
|
|
3240
|
+
mark_inline=args.mark_inline,
|
|
3241
|
+
concurrency=args.concurrency,
|
|
3242
|
+
timeout=args.timeout,
|
|
3243
|
+
)
|
|
3086
3244
|
else:
|
|
3087
3245
|
parser.print_help()
|
|
3088
3246
|
return 1
|