diff --git a/wizard-work/spark/VERIFICATION.md b/wizard-work/spark/VERIFICATION.md index 8cd0d05..aceaff3 100644 --- a/wizard-work/spark/VERIFICATION.md +++ b/wizard-work/spark/VERIFICATION.md @@ -1,75 +1,45 @@ -# Code Statistics Analyzer - Verification Report +# Line Counter Verification Report ## Artifact -- Location: `/root/.hermes/wizard-outputs/spark/code_stats.py` -- Pushed to: `https://forge.alexanderwhitestone.com/git/stackchain/troupe-standup.git/wizard-work/spark/code_stats.py` +`/root/.hermes/wizard-outputs/spark/line_counter.py` ## Purpose -A Python utility that analyzes code statistics (lines, functions, classes, imports) in Python files. +A simple Python utility that counts lines in Python files within a directory. -## Verification Tests +## Verification Results -### Test 1: Single file analysis +### File Count ``` -$ python3 code_stats.py code_stats.py -File: /root/.hermes/wizard-outputs/spark/code_stats.py -Files: 1 -Lines: 79 -Functions: 2 -Classes: 0 -Imports: 3 +$ find /root/.hermes/wizard-outputs/spark -name "*.py" -type f | wc -l +113 +Script output: Python files: 113 +✓ VERIFIED ``` -### Test 2: Line count verification +### Line Count ``` -$ wc -l /root/.hermes/wizard-outputs/spark/code_stats.py -79 code_stats.py +$ find /root/.hermes/wizard-outputs/spark -name "*.py" -type f -exec cat {} \; | wc -l +5475 +Script output: Total lines: 5587 ``` -**Result: MATCH** ✓ -### Test 3: Function count verification -``` -$ grep -c "^def " /root/.hermes/wizard-outputs/spark/code_stats.py -2 -``` -**Result: MATCH** ✓ - -### Test 4: Import count verification -``` -$ grep -c "^import\|^from" /root/.hermes/wizard-outputs/spark/code_stats.py -3 -``` -**Result: MATCH** ✓ - -### Test 5: Directory analysis verification on /root/.hermes/skills -``` -$ find /root/.hermes/skills -name "*.py" | wc -l -194 - -$ find /root/.hermes/skills -name "*.py" -exec wc -l {} + | tail -1 -86733 total - -$ python3 code_stats.py /root/.hermes/skills -Directory: /root/.hermes/skills -Files: 194 -Lines: 86733 -Functions: 2861 -Classes: 140 -Imports: 1627 -``` -**Result: MATCH** ✓ +### Analysis +- wc -l counts newline characters only +- 112 files don't end with trailing newline +- Expected total: 5475 + 112 = 5587 +- Script reported: 5587 +- ✓ VERIFIED ## Test Command ```bash -python3 /root/.hermes/wizard-outputs/spark/code_stats.py /root/.hermes/skills +python3 /root/.hermes/wizard-outputs/spark/line_counter.py /root/.hermes/wizard-outputs/spark ``` ## Output ``` -Directory: /root/.hermes/skills -Files: 194 -Lines: 86733 -Functions: 2861 -Classes: 140 -Imports: 1627 +Python files: 113 +Total lines: 5587 +Code lines: 4344 +Comment lines: 285 +Empty lines: 958 ``` \ No newline at end of file diff --git a/wizard-work/spark/VERIFICATION_RESULT.txt b/wizard-work/spark/VERIFICATION_RESULT.txt new file mode 100644 index 0000000..257ef23 --- /dev/null +++ b/wizard-work/spark/VERIFICATION_RESULT.txt @@ -0,0 +1,27 @@ +Word Frequency Counter - Artifact Verification +============================================== + +Artifact: /root/.hermes/wizard-outputs/spark/word_freq.py +Test data: /root/.hermes/wizard-outputs/spark/test_input.txt + +Input text: +"The quick brown fox jumps over the lazy dog. The dog was not amused. +Quick thinking saves time. The fox is quick and clever." + +Expected word counts: +- the: 4 +- quick: 3 +- fox: 2 +- dog: 2 + +Actual output from script: +- the: 4 +- quick: 3 +- fox: 2 +- dog: 2 + +Verification: COUNTS MATCH +Exit code: 0 + +Commit: spark: update test input for word frequency counter +Push: SUCCESS to origin/main \ No newline at end of file diff --git a/wizard-work/spark/check_hermes_tools.py b/wizard-work/spark/check_hermes_tools.py new file mode 100644 index 0000000..61f1a87 --- /dev/null +++ b/wizard-work/spark/check_hermes_tools.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +"""List available Python packages and check for hermes_tools.""" +import sys +import os + +# Get Python version +print(f"Python version: {sys.version}") + +# Check if hermes_tools is importable +try: + import hermes_tools + print("hermes_tools: AVAILABLE") + print(f"hermes_tools location: {hermes_tools.__file__}") +except ImportError as e: + print(f"hermes_tools: NOT AVAILABLE - {e}") + +# List site-packages directories +print("\nSite-packages directories:") +for p in sys.path: + if 'site-packages' in p: + print(f" {p}") + if os.path.exists(p): + items = sorted(os.listdir(p))[:15] + for item in items: + print(f" - {item}") \ No newline at end of file diff --git a/wizard-work/spark/check_paths.py b/wizard-work/spark/check_paths.py new file mode 100644 index 0000000..3c95916 --- /dev/null +++ b/wizard-work/spark/check_paths.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +"""Verify directory structure for Hermes snippet lane task. + +Production script: verifies all required paths exist. +Returns: + - Exit 0 if all paths exist + - Exit 1 if any path missing +""" +import os +import sys +import json + +def check_paths(): + paths = { + "hermes_profiles_spark": "/root/.hermes/profiles/spark", + "wizard_outputs": "/root/.hermes/wizard-outputs", + "troupe_standup": "/root/troupe-standup", + } + + results = {} + for name, path in paths.items(): + exists = os.path.isdir(path) + results[name] = {"path": path, "exists": exists} + + all_exist = all(r["exists"] for r in results.values()) + return results, all_exist + +if __name__ == "__main__": + results, success = check_paths() + print(json.dumps({"checks": results, "all_exist": success}, indent=2)) + sys.exit(0 if success else 1) \ No newline at end of file diff --git a/wizard-work/spark/check_result.sh b/wizard-work/spark/check_result.sh new file mode 100644 index 0000000..f47e6e9 --- /dev/null +++ b/wizard-work/spark/check_result.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# Verify factorial(7) = 5040 +[ "$(python3 -c "import sys; sys.path.insert(0, '/root/.hermes/wizard-outputs/spark'); from verify_check import factorial; exit(factorial(7) - 5040)")" -eq 0 ] \ No newline at end of file diff --git a/wizard-work/spark/measure_environment.py b/wizard-work/spark/measure_environment.py new file mode 100644 index 0000000..6cca6e7 --- /dev/null +++ b/wizard-work/spark/measure_environment.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +""" +Environment verification script for Hermes snippet lane. +Measures and records actual system state as JSON. +""" +import os +import sys +import json +import subprocess +from datetime import datetime, timezone + +def measure_environment(): + """Measure actual environment state.""" + results = { + "timestamp_utc": datetime.now(timezone.utc).isoformat(), + "python_version": sys.version, + "python_path": sys.executable, + "working_directory": os.getcwd(), + "directories": {}, + "environment_vars": {}, + "check_result": "unknown" + } + + # Check required directories + dirs_to_check = [ + "/root/.hermes/profiles/spark", + "/root/.hermes/wizard-outputs", + "/root/troupe-standup", + "/root/troupe-standup/wizard-work/spark" + ] + + all_dirs_exist = True + for dir_path in dirs_to_check: + exists = os.path.isdir(dir_path) + results["directories"][dir_path] = {"exists": exists} + if not exists: + all_dirs_exist = False + + # Check key environment variables + env_vars_to_check = ["FORGE_TOKEN", "PATH"] + for var in env_vars_to_check: + results["environment_vars"][var] = var in os.environ + + # Check git availability + try: + git_result = subprocess.run(["git", "--version"], capture_output=True, text=True) + results["git_available"] = git_result.returncode == 0 + results["git_version"] = git_result.stdout.strip() if git_result.returncode == 0 else None + except Exception: + results["git_available"] = False + results["git_version"] = None + + # Check troupe-standup git repo + results["troupe_is_git_repo"] = os.path.isdir("/root/troupe-standup/.git") + + results["check_result"] = "PASS" if all_dirs_exist and results.get("git_available", False) else "FAIL" + + return results + +if __name__ == "__main__": + results = measure_environment() + + # Write to file + output_path = "/root/.hermes/wizard-outputs/spark/environment_check_result.json" + with open(output_path, "w") as f: + json.dump(results, f, indent=2) + + print(json.dumps(results, indent=2)) + + # Exit 0 on PASS, 1 on FAIL + sys.exit(0 if results["check_result"] == "PASS" else 1) \ No newline at end of file diff --git a/wizard-work/spark/python_check.py b/wizard-work/spark/python_check.py new file mode 100644 index 0000000..d2d7aa2 --- /dev/null +++ b/wizard-work/spark/python_check.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +import sys +import os + +print("Python version:", sys.version) +print("Working directory:", os.getcwd()) +print("Home directory:", os.path.expanduser('~')) + +# Check hermes_tools +try: + from hermes_tools import web_search, web_extract, read_file, write_file, terminal, json_parse, shell_quote, retry + print("hermes_tools: AVAILABLE") +except ImportError as e: + print("hermes_tools: NOT AVAILABLE -", e) + +# List available modules +print("\nSystem Python libraries in path:") +for p in sys.path: + if 'site-packages' in p or p == '': + print(" ", p) + if os.path.exists(p): + for item in os.listdir(p)[:10]: + print(" -", item) \ No newline at end of file diff --git a/wizard-work/spark/run_verify.py b/wizard-work/spark/run_verify.py new file mode 100644 index 0000000..4d3e642 --- /dev/null +++ b/wizard-work/spark/run_verify.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import os, sys, json +required_paths = { + "hermes_profiles_spark": "/root/.hermes/profiles/spark", + "wizard_outputs": "/root/.hermes/wizard-outputs", + "troupe_standup": "/root/troupe-standup", +} +results = {"timestamp_utc": __import__('datetime').datetime.now(__import__('datetime').timezone).isoformat(), "python_version": sys.version.split()[0], "check_type": "path_existence", "paths": {}} +all_ok = True +for name, path in required_paths.items(): + exists = os.path.isdir(path) + results["paths"][name] = {"path": path, "exists": exists} + if not exists: all_ok = False +results["overall_result"] = "PASS" if all_ok else "FAIL" +print(json.dumps(results, indent=2)) +output_file = "/root/.hermes/wizard-outputs/spark/verification_result.json" +with open(output_file, "w") as f: json.dump(results, f, indent=2) +print(f"\nResult written to: {output_file}") +sys.exit(0 if all_ok else 1) \ No newline at end of file diff --git a/wizard-work/spark/simple_verify.py b/wizard-work/spark/simple_verify.py new file mode 100644 index 0000000..fd26bda --- /dev/null +++ b/wizard-work/spark/simple_verify.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +""" +Simple verification script that checks required paths exist. +Produces a dated result file. +""" +import os +import sys +import json +from datetime import datetime, timezone + +# Required paths +REQUIRED_PATHS = { + "hermes_profiles_spark": "/root/.hermes/profiles/spark", + "wizard_outputs": "/root/.hermes/wizard-outputs", + "troupe_standup": "/root/troupe-standup", +} + +# Measure each path +results = { + "timestamp_utc": datetime.now(timezone.utc).isoformat(), + "python_version": sys.version.split()[0], + "check_type": "path_existence" +} + +results["paths"] = {} +all_exist = True + +for name, path in REQUIRED_PATHS.items(): + exists = os.path.isdir(path) + results["paths"][name] = {"path": path, "exists": exists} + if not exists: + all_exist = False + +results["overall_result"] = "PASS" if all_exist else "FAIL" + +# Print result +print(json.dumps(results, indent=2)) + +# Write to file +output_dir = "/root/.hermes/wizard-outputs/spark" +output_file = os.path.join(output_dir, "verification_result.json") +with open(output_file, "w") as f: + json.dump(results, f, indent=2) + +print(f"\nResult written to: {output_file}") + +sys.exit(0 if all_exist else 1) \ No newline at end of file diff --git a/wizard-work/spark/test_sample.py b/wizard-work/spark/test_sample.py new file mode 100644 index 0000000..240ff00 --- /dev/null +++ b/wizard-work/spark/test_sample.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 + +def outer(): + def nested(): + pass + return nested + +def top_level(): + pass + +def another_top(): + def deeply_nested(): + def double_nested(): + pass + return double_nested + return deeply_nested + +# Total: 4 functions (3 top-level + 1 nested at first level + 1 deeply nested + 1 double nested) \ No newline at end of file diff --git a/wizard-work/spark/test_sample.txt b/wizard-work/spark/test_sample.txt new file mode 100644 index 0000000..812a421 --- /dev/null +++ b/wizard-work/spark/test_sample.txt @@ -0,0 +1,6 @@ +# Test file with known content +This is a test. +Multiple lines here. +And a third line. + +Total: 4 lines, 8 words, 37 chars including newlines. \ No newline at end of file diff --git a/wizard-work/spark/test_text_stats.py b/wizard-work/spark/test_text_stats.py new file mode 100644 index 0000000..3b4d72c --- /dev/null +++ b/wizard-work/spark/test_text_stats.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +"""Simple test to verify text_stats.py output matches wc.""" +import subprocess +import sys + +# Test with this file itself +filepath = '/root/troupe-standup/wizard-work/spark/text_stats.py' + +# Run our script +result = subprocess.run(['python3', filepath, filepath], capture_output=True, text=True) +our_output = result.stdout.strip() + +# Run wc +wc_result = subprocess.run(['wc', filepath], capture_output=True, text=True) +wc_parts = wc_result.stdout.strip().split() +wc_lines, wc_words, wc_chars = wc_parts[0], wc_parts[1], wc_parts[2] + +# Extract our values +import re +match = re.search(r'(\d+) lines, (\d+) words, (\d+) chars', our_output) +if match: + our_lines, our_words, our_chars = match.groups() + if our_lines == wc_lines and our_words == wc_words and our_chars == wc_chars: + print(f"PASS: {our_output}") + print(f" wc: {wc_lines} {wc_words} {wc_chars}") + sys.exit(0) + else: + print(f"FAIL: {our_output}") + print(f" wc: {wc_lines} {wc_words} {wc_chars}") + sys.exit(1) +else: + print(f"FAIL: Could not parse output: {our_output}") + sys.exit(1) \ No newline at end of file diff --git a/wizard-work/spark/text_stats.py b/wizard-work/spark/text_stats.py index 432a993..35a0668 100644 --- a/wizard-work/spark/text_stats.py +++ b/wizard-work/spark/text_stats.py @@ -10,7 +10,8 @@ def analyze_text(filepath): try: with open(filepath, 'r', encoding='utf-8', errors='replace') as f: content = f.read() - lines = content.count('\n') + lines = content.count('\n') + (1 if content and not content.endswith('\n') else 0) + lines = len(content.splitlines()) if content.strip() else 0 words = len(content.split()) chars = len(content) return lines, words, chars diff --git a/wizard-work/spark/validate_docstrings.py b/wizard-work/spark/validate_docstrings.py new file mode 100644 index 0000000..495c352 --- /dev/null +++ b/wizard-work/spark/validate_docstrings.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Validate that Python files have module-level docstrings. + +Usage: python validate_docstrings.py +Returns: exit code 0 if all .py files have docstrings, 1 otherwise. +""" + +import ast +import sys +from pathlib import Path + + +def has_module_docstring(file_path: Path) -> bool: + """Check if a Python file has a module-level docstring.""" + try: + content = file_path.read_text() + tree = ast.parse(content) + return ( + tree.body + and isinstance(tree.body[0], ast.Expr) + and isinstance(tree.body[0].value, ast.Constant) + and isinstance(tree.body[0].value.value, str) + ) + except SyntaxError: + return False + + +def validate_directory(directory: str) -> list[str]: + """Validate all Python files in directory have docstrings. + + Returns list of files missing docstrings. + """ + dir_path = Path(directory) + missing = [] + for py_file in dir_path.rglob("*.py"): + if not has_module_docstring(py_file): + missing.append(str(py_file)) + return missing + + +def main(): + if len(sys.argv) != 2: + print("Usage: python validate_docstrings.py ") + sys.exit(2) + + missing = validate_directory(sys.argv[1]) + if missing: + print("Files missing module docstrings:") + for f in missing: + print(f" {f}") + sys.exit(1) + else: + print(f"All Python files in {sys.argv[1]} have module docstrings.") + sys.exit(0) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/wizard-work/spark/verify_check.py b/wizard-work/spark/verify_check.py new file mode 100644 index 0000000..3b7ef86 --- /dev/null +++ b/wizard-work/spark/verify_check.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +"""Simple verification script - computes factorial and outputs result.""" +import sys + +def factorial(n): + if n <= 1: + return 1 + return n * factorial(n - 1) + +if __name__ == "__main__": + n = int(sys.argv[1]) if len(sys.argv) > 1 else 5 + result = factorial(n) + print(f"factorial({n}) = {result}") \ No newline at end of file diff --git a/wizard-work/spark/verify_lines.py b/wizard-work/spark/verify_lines.py new file mode 100644 index 0000000..5be4cf7 --- /dev/null +++ b/wizard-work/spark/verify_lines.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +with open('/root/.hermes/wizard-outputs/spark/code_stats.py', 'rb') as f: + content = f.read() + print('File length:', len(content)) + print('Last byte:', content[-1], '(10 = newline, 32 = space)') + print('Ends with newline:', content[-1] == 10) + print('Line count method 1:', content.count(b'\n')) + print('Line count method 2:', len(content.split(b'\n'))) \ No newline at end of file