♻️ refactor(meta): add consistent META headers across all files
- add standardized META block with name, description, version, created, modified dates - unify metadata formatting for better maintainability and traceability - introduce new meta_check standard handler for library-profile META validation - update json_structure_check to support library-profile branch detection and path rules - improve imports_check to enforce pip package import standards (no AIPASS_ROOT/sys.path hacks) - refine documentation_check to remove META block validation (now in meta_check) - clean up legacy code and comments related to META and import checks - add meta standard to aipass standards list and pack manifest
This commit is contained in:
@@ -7,6 +7,15 @@ Verifies packs are loadable, manifests are valid, and standards are consistent.
|
||||
Run: seedgo verify
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: seedgo_verify.py
|
||||
# Description: Seedgo Verify Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -7,6 +7,15 @@ Routes commands to standard packs and seedgo-level modules.
|
||||
- 'list' shows installed standard packs
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: seedgo.py
|
||||
# Description: SEEDGO - Standards Platform for AIPass
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import json
|
||||
import sys
|
||||
import importlib.util
|
||||
|
||||
@@ -1,87 +1,4 @@
|
||||
[
|
||||
{
|
||||
"timestamp": "2026-02-28T22:09:29.949149",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": "NEXUS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:09:30.920011",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:09:31.403903",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:09:40.074739",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": ".VSCODE"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:09:42.864658",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 100
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:10:35.787714",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": "API"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:10:42.291239",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 99
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:11:32.687304",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": "API"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:11:37.688147",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 99
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:11:49.227740",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": "API"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:11:55.928817",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 99
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-02-28T22:11:58.956279",
|
||||
"operation": "standards_audit_started",
|
||||
@@ -746,5 +663,87 @@
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 77
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T17:55:54.272262",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": "SEED"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T17:55:58.731226",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T17:56:03.033619",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 75
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T17:58:58.985765",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T17:58:59.312333",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:03:47.935488",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:03:51.921661",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 79
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:05:23.241099",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:05:23.617765",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 84
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:18:21.472118",
|
||||
"operation": "standards_audit_started",
|
||||
"data": {
|
||||
"specific_branch": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2026-03-05T18:18:25.431490",
|
||||
"operation": "standards_audit_completed",
|
||||
"data": {
|
||||
"branches_audited": 1,
|
||||
"average_compliance": 84
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -4,6 +4,15 @@ Branch Audit Handler
|
||||
Audits a single branch for standards compliance.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: branch_audit.py
|
||||
# Description: Branch Audit Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
@@ -34,6 +43,7 @@ from ..standards import log_visibility_check
|
||||
from ..standards import permission_flags_check
|
||||
from ..standards import readme_check
|
||||
from ..standards import diagnostics_check
|
||||
from ..standards import meta_check
|
||||
from ..config import ignore_handler
|
||||
|
||||
|
||||
@@ -95,7 +105,8 @@ def audit_branch(branch: Dict[str, str], bypass_rules: list) -> Dict:
|
||||
'log_handler': log_handler_check,
|
||||
'log_visibility': log_visibility_check,
|
||||
'permission_flags': permission_flags_check,
|
||||
'readme': readme_check
|
||||
'readme': readme_check,
|
||||
'meta': meta_check
|
||||
}
|
||||
|
||||
results = {}
|
||||
|
||||
@@ -4,6 +4,15 @@ Bypass Audit Handler
|
||||
Audits all bypassed files to see their current state.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: bypass_audit.py
|
||||
# Description: Bypass Audit Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
@@ -26,6 +35,7 @@ from ..standards import json_structure_check
|
||||
from ..standards import testing_check
|
||||
from ..standards import error_handling_check
|
||||
from ..standards import encapsulation_check
|
||||
from ..standards import meta_check
|
||||
|
||||
|
||||
# =============================================================================
|
||||
@@ -95,6 +105,8 @@ def audit_bypasses(branches: List[Dict], bypass_rules_map: Dict[str, list]) -> L
|
||||
checker = error_handling_check
|
||||
elif standard == 'encapsulation':
|
||||
checker = encapsulation_check
|
||||
elif standard == 'meta':
|
||||
checker = meta_check
|
||||
|
||||
if checker:
|
||||
try:
|
||||
|
||||
@@ -4,6 +4,15 @@ Branch Discovery Handler
|
||||
Discovers all AIPass branches from BRANCH_REGISTRY.json
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: discovery.py
|
||||
# Description: Branch Discovery Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
|
||||
@@ -4,6 +4,15 @@ Audit Display Handler
|
||||
Formats and prints audit results to console.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: display.py
|
||||
# Description: Audit Display Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
@@ -7,6 +7,15 @@ in business logic detection. Helps reduce false positives.
|
||||
Pure configuration with helper functions for pattern access and filtering.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: ignore_handler.py
|
||||
# Description: Business Logic Detection Ignore Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
# =============================================
|
||||
# IMPORTS
|
||||
# =============================================
|
||||
|
||||
@@ -4,6 +4,15 @@ Branch Discovery Handler
|
||||
Discovers all branches from the registry for diagnostics scanning.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: discovery.py
|
||||
# Description: Branch Discovery Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,15 @@ Branch Diagnostics Runner Handler
|
||||
Runs diagnostics checks on individual branches.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: runner.py
|
||||
# Description: Branch Diagnostics Runner Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides text file reading abstraction for modules.
|
||||
Keeps direct file operations in handlers, not modules.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: file_handler.py
|
||||
# Description: File Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
@@ -17,6 +17,15 @@ def _get_caller_module_name() -> str:
|
||||
Returns:
|
||||
Module name (e.g., "imports_standard" from imports_standard.py)
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: json_handler.py
|
||||
# Description: Json Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
stack = inspect.stack()
|
||||
# Skip frames: [0]=this function, [1]=log_operation, [2]=actual caller
|
||||
if len(stack) > 2:
|
||||
|
||||
@@ -6,6 +6,15 @@ Checks 3-layer pattern, handler independence, file size, domain organization.
|
||||
For entry points, also verifies entire branch structure against template baseline.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: architecture_check.py
|
||||
# Description: Architecture Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted Architecture standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: architecture_content.py
|
||||
# Description: Architecture Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_architecture_standards() -> str:
|
||||
"""Return formatted architecture standards content with Rich markup
|
||||
|
||||
@@ -5,6 +5,15 @@ Validates module compliance with AIPass CLI standards.
|
||||
Checks console.print() usage, CLI service imports, handler separation.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_check.py
|
||||
# Description: CLI Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted CLI standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_content.py
|
||||
# Description: CLI Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_cli_standards() -> str:
|
||||
"""Return formatted CLI standards content with Rich markup
|
||||
|
||||
@@ -13,6 +13,15 @@ apps/handlers/ or apps/modules/). Non-entry-point files are skipped
|
||||
with a pass.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_flags_check.py
|
||||
# Description: CLI Flags Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,6 +4,14 @@ CLI Flags Standards Content
|
||||
Provides Rich-formatted reference text for the CLI flags standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_flags_content.py
|
||||
# Description: CLI Flags Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_cli_flags_standards() -> str:
|
||||
"""Return Rich-formatted CLI flags standards text"""
|
||||
|
||||
@@ -5,6 +5,15 @@ Uses pyright to detect type errors, undefined variables, and other
|
||||
static analysis issues that would show as Pylance errors in VS Code.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: diagnostics_check.py
|
||||
# Description: Type Error Diagnostics Checker
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
+30
-196
@@ -1,28 +1,34 @@
|
||||
"""
|
||||
Documentation Standards Checker Handler
|
||||
|
||||
Validates documentation compliance with AIPass documentation standards.
|
||||
Checks shebang, META block, module docstring, function docstrings.
|
||||
Validates documentation compliance: module docstrings and function docstrings.
|
||||
META block validation is handled separately by meta_check.py.
|
||||
"""
|
||||
|
||||
import sys
|
||||
# =================== META ====================
|
||||
# Name: documentation_check.py
|
||||
# Description: Documentation Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_rules: list | None = None) -> bool:
|
||||
"""Check if a violation should be bypassed"""
|
||||
if not bypass_rules:
|
||||
return False
|
||||
for rule in bypass_rules:
|
||||
# Must match standard
|
||||
if rule.get('standard') and rule.get('standard') != standard:
|
||||
continue
|
||||
# Must match file (check if rule file path is in the full path)
|
||||
rule_file = rule.get('file', '')
|
||||
if rule_file and rule_file not in file_path:
|
||||
continue
|
||||
# Check line-specific bypass
|
||||
rule_lines = rule.get('lines', [])
|
||||
if rule_lines and line is not None:
|
||||
if line in rule_lines:
|
||||
@@ -34,29 +40,20 @@ def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_r
|
||||
|
||||
def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check if module follows documentation standards
|
||||
Check if module follows documentation standards.
|
||||
|
||||
Checks module-level docstrings and public function docstrings.
|
||||
|
||||
Args:
|
||||
module_path: Path to Python module to check
|
||||
bypass_rules: Optional bypass rules
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'passed': bool, # Overall pass/fail
|
||||
'checks': [ # Individual check results
|
||||
{
|
||||
'name': str, # Check name
|
||||
'passed': bool, # Pass/fail
|
||||
'message': str, # Details
|
||||
}
|
||||
],
|
||||
'score': int, # 0-100 percentage
|
||||
'standard': str # Standard name
|
||||
}
|
||||
dict with passed, checks, score, standard keys
|
||||
"""
|
||||
checks = []
|
||||
path = Path(module_path)
|
||||
|
||||
# Check if entire standard is bypassed for this file
|
||||
if is_bypassed(module_path, 'documentation', bypass_rules=bypass_rules):
|
||||
return {
|
||||
'passed': True,
|
||||
@@ -65,7 +62,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'DOCUMENTATION'
|
||||
}
|
||||
|
||||
# Validate file exists
|
||||
if not path.exists():
|
||||
return {
|
||||
'passed': False,
|
||||
@@ -74,7 +70,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'DOCUMENTATION'
|
||||
}
|
||||
|
||||
# Read file
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
@@ -87,7 +82,7 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'DOCUMENTATION'
|
||||
}
|
||||
|
||||
# Skip __init__.py files (different documentation standards)
|
||||
# Skip __init__.py files
|
||||
if path.name == '__init__.py':
|
||||
return {
|
||||
'passed': True,
|
||||
@@ -96,29 +91,18 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'DOCUMENTATION'
|
||||
}
|
||||
|
||||
# Check 1: Shebang line
|
||||
shebang_check = check_shebang(lines, module_path)
|
||||
checks.append(shebang_check)
|
||||
|
||||
# Check 2: META block
|
||||
meta_check = check_meta_block(content, lines)
|
||||
checks.append(meta_check)
|
||||
|
||||
# Check 3: Module-level docstring
|
||||
# Check 1: Module-level docstring
|
||||
docstring_check = check_module_docstring(lines)
|
||||
checks.append(docstring_check)
|
||||
|
||||
# Check 4: Function docstrings (for public functions)
|
||||
# Check 2: Function docstrings (for public functions)
|
||||
function_docs_check = check_function_docstrings(content, lines)
|
||||
if function_docs_check:
|
||||
checks.append(function_docs_check)
|
||||
|
||||
# Calculate score
|
||||
passed_checks = sum(1 for check in checks if check['passed'])
|
||||
total_checks = len(checks)
|
||||
score = int((passed_checks / total_checks * 100)) if total_checks > 0 else 0
|
||||
|
||||
# Overall pass if score >= 75%
|
||||
overall_passed = score >= 75
|
||||
|
||||
return {
|
||||
@@ -129,159 +113,15 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
}
|
||||
|
||||
|
||||
def check_shebang(lines: List[str], module_path: str = "") -> Dict:
|
||||
"""
|
||||
Check for correct shebang line
|
||||
|
||||
Should be: #!/home/aipass/.venv/bin/python3
|
||||
EXCEPTION: MEMORY_BANK uses #!/home/aipass/MEMORY_BANK/.venv/bin/python3
|
||||
"""
|
||||
if not lines:
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': False,
|
||||
'message': 'File is empty'
|
||||
}
|
||||
|
||||
first_line = lines[0].strip()
|
||||
|
||||
# Determine if this is a MEMORY_BANK file
|
||||
is_memory_bank = '/MEMORY_BANK/' in module_path
|
||||
|
||||
# Define valid shebangs
|
||||
standard_shebang = '#!/home/aipass/.venv/bin/python3'
|
||||
memory_bank_shebang = '#!/home/aipass/MEMORY_BANK/.venv/bin/python3'
|
||||
|
||||
# Check for correct shebang based on location
|
||||
if is_memory_bank:
|
||||
if first_line == memory_bank_shebang:
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': True,
|
||||
'message': f'Correct MEMORY_BANK shebang ({memory_bank_shebang})'
|
||||
}
|
||||
elif first_line == standard_shebang:
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': False,
|
||||
'message': f'Wrong shebang for MEMORY_BANK: {first_line} (should be {memory_bank_shebang})'
|
||||
}
|
||||
else:
|
||||
if first_line == standard_shebang:
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': True,
|
||||
'message': f'Correct shebang ({standard_shebang})'
|
||||
}
|
||||
elif first_line == memory_bank_shebang:
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': False,
|
||||
'message': f'Wrong shebang: {first_line} (should be {standard_shebang} for non-MEMORY_BANK files)'
|
||||
}
|
||||
|
||||
# Handle other shebangs
|
||||
if first_line.startswith('#!'):
|
||||
expected = memory_bank_shebang if is_memory_bank else standard_shebang
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': False,
|
||||
'message': f'Wrong shebang: {first_line} (should be {expected})'
|
||||
}
|
||||
|
||||
expected = memory_bank_shebang if is_memory_bank else standard_shebang
|
||||
return {
|
||||
'name': 'Shebang line',
|
||||
'passed': False,
|
||||
'message': f'Missing shebang line (should be {expected})'
|
||||
}
|
||||
|
||||
|
||||
def check_meta_block(content: str, lines: List[str]) -> Dict:
|
||||
"""
|
||||
Check for complete META block
|
||||
|
||||
Required fields:
|
||||
- Name: filename - Description
|
||||
- Date: YYYY-MM-DD
|
||||
- Version: X.Y.Z
|
||||
- Category: branch or branch/handlers
|
||||
- CHANGELOG: At least one entry
|
||||
- CODE STANDARDS: Reference
|
||||
"""
|
||||
# Check for META header markers
|
||||
if '# ===================AIPASS====================' not in content:
|
||||
return {
|
||||
'name': 'META block',
|
||||
'passed': False,
|
||||
'message': 'Missing META block (no AIPASS header found)'
|
||||
}
|
||||
|
||||
if '# META DATA HEADER' not in content:
|
||||
return {
|
||||
'name': 'META block',
|
||||
'passed': False,
|
||||
'message': 'Missing "# META DATA HEADER" line'
|
||||
}
|
||||
|
||||
# Check required fields
|
||||
missing_fields = []
|
||||
|
||||
if not re.search(r'# Name:\s+[\w\-]+\.py\s+-\s+', content):
|
||||
missing_fields.append('Name')
|
||||
|
||||
if not re.search(r'# Date:\s+\d{4}-\d{2}-\d{2}', content):
|
||||
missing_fields.append('Date')
|
||||
|
||||
if not re.search(r'# Version:\s+\d+\.\d+\.\d+', content):
|
||||
missing_fields.append('Version')
|
||||
|
||||
if not re.search(r'# Category:\s+\w+', content):
|
||||
missing_fields.append('Category')
|
||||
|
||||
if '# CHANGELOG' not in content:
|
||||
missing_fields.append('CHANGELOG')
|
||||
|
||||
if '# CODE STANDARDS:' not in content:
|
||||
missing_fields.append('CODE STANDARDS')
|
||||
|
||||
if missing_fields:
|
||||
return {
|
||||
'name': 'META block',
|
||||
'passed': False,
|
||||
'message': f'Incomplete META block - missing: {", ".join(missing_fields)}'
|
||||
}
|
||||
|
||||
return {
|
||||
'name': 'META block',
|
||||
'passed': True,
|
||||
'message': 'Complete META block with all required fields'
|
||||
}
|
||||
|
||||
|
||||
def check_module_docstring(lines: List[str]) -> Dict:
|
||||
"""
|
||||
Check for module-level docstring after META block
|
||||
Check for module-level docstring.
|
||||
|
||||
Should be triple-quoted string explaining module purpose
|
||||
Looks for a triple-quoted string near the top of the file,
|
||||
allowing for META block, comments, or blank lines before it.
|
||||
"""
|
||||
# Find the end of META block
|
||||
meta_end = -1
|
||||
for i, line in enumerate(lines):
|
||||
if '# =============================================' in line and i > 0:
|
||||
meta_end = i
|
||||
break
|
||||
|
||||
if meta_end == -1:
|
||||
return {
|
||||
'name': 'Module docstring',
|
||||
'passed': False,
|
||||
'message': 'Cannot find end of META block'
|
||||
}
|
||||
|
||||
# Look for docstring within next 10 lines after META block
|
||||
for i in range(meta_end + 1, min(meta_end + 11, len(lines))):
|
||||
stripped = lines[i].strip()
|
||||
for line in lines[:30]:
|
||||
stripped = line.strip()
|
||||
if stripped.startswith('"""') or stripped.startswith("'''"):
|
||||
return {
|
||||
'name': 'Module docstring',
|
||||
@@ -292,35 +132,30 @@ def check_module_docstring(lines: List[str]) -> Dict:
|
||||
return {
|
||||
'name': 'Module docstring',
|
||||
'passed': False,
|
||||
'message': 'Missing module-level docstring after META block'
|
||||
'message': 'Missing module-level docstring (expected within first 30 lines)'
|
||||
}
|
||||
|
||||
|
||||
def check_function_docstrings(content: str, lines: List[str]) -> Optional[Dict]:
|
||||
def check_function_docstrings(content: str, lines: List[str]) -> Dict | None: # noqa: ARG001
|
||||
"""
|
||||
Check that public functions have docstrings
|
||||
Check that public functions have docstrings.
|
||||
|
||||
Public functions (not starting with _) should have docstrings
|
||||
Public functions (not starting with _) should have docstrings.
|
||||
"""
|
||||
# Find all public function definitions
|
||||
public_functions = []
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
if stripped.startswith('def ') and not stripped.startswith('def _'):
|
||||
# Extract function name
|
||||
match = re.match(r'def\s+(\w+)\s*\(', stripped)
|
||||
if match:
|
||||
func_name = match.group(1)
|
||||
public_functions.append((func_name, i))
|
||||
|
||||
if not public_functions:
|
||||
# No public functions, check passes
|
||||
return None
|
||||
|
||||
# Check each function for docstring
|
||||
undocumented = []
|
||||
for func_name, line_num in public_functions:
|
||||
# Look for docstring in next few lines
|
||||
has_docstring = False
|
||||
for check_line in range(line_num, min(line_num + 5, len(lines) + 1)):
|
||||
if check_line - 1 < len(lines):
|
||||
@@ -328,7 +163,6 @@ def check_function_docstrings(content: str, lines: List[str]) -> Optional[Dict]:
|
||||
if check_stripped.startswith('"""') or check_stripped.startswith("'''"):
|
||||
has_docstring = True
|
||||
break
|
||||
|
||||
if not has_docstring:
|
||||
undocumented.append(f'{func_name} (line {line_num})')
|
||||
|
||||
|
||||
@@ -5,6 +5,14 @@ Condensed documentation standards verified against actual codebase.
|
||||
Truth-checked 2025-11-13 against cortex and seed production code.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: documentation_content.py
|
||||
# Description: Documentation Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_documentation_standards() -> str:
|
||||
"""Return formatted documentation standards content with Rich markup
|
||||
|
||||
@@ -7,6 +7,15 @@ Validates that handlers are properly encapsulated:
|
||||
- Handlers should be accessed through module entry points, not directly
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: encapsulation_check.py
|
||||
# Description: Handler Encapsulation Standards Checker
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,15 @@ Validates module compliance with AIPass 3-tier logging standards.
|
||||
Checks Prax imports in modules/handlers, logger calls in handlers.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: error_handling_check.py
|
||||
# Description: Error Handling Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted error handling standards content (3-tier architecture).
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: error_handling_content.py
|
||||
# Description: Error Handling Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_error_handling_standards() -> str:
|
||||
"""Return formatted error handling standards content with Rich markup
|
||||
|
||||
@@ -5,6 +5,15 @@ Validates handler compliance with AIPass handler standards.
|
||||
Checks handler independence, auto-detection pattern, no orchestration.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: handlers_check.py
|
||||
# Description: Handlers Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -8,6 +8,14 @@ Provides formatted handlers standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: handlers_content.py
|
||||
# Description: Handlers Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_handlers_standards() -> str:
|
||||
"""Return formatted handlers standards content with Rich markup
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
"""
|
||||
Imports Standards Checker Handler
|
||||
|
||||
Validates module compliance with AIPass import standards.
|
||||
Checks AIPASS_ROOT pattern, import order, Prax logger, sys.path setup.
|
||||
|
||||
Fixed bugs:
|
||||
- Filters docstrings before checking imports (prevents false negatives from import examples)
|
||||
- Only checks import section (not comments/docstrings)
|
||||
- Detects handler-to-module import violations
|
||||
- Makes Prax logger conditional (not required for small files)
|
||||
Validates module compliance with AIPass import standards for pip packages.
|
||||
Checks for clean pip-style imports: no AIPASS_ROOT, no sys.path hacking,
|
||||
proper aipass.* namespace usage, correct import order.
|
||||
"""
|
||||
|
||||
import sys
|
||||
# =================== META ====================
|
||||
# Name: imports_check.py
|
||||
# Description: Imports Standards Checker Handler
|
||||
# Version: 2.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
|
||||
def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_rules: list | None = None) -> bool:
|
||||
"""Check if a violation should be bypassed"""
|
||||
if not bypass_rules:
|
||||
return False
|
||||
for rule in bypass_rules:
|
||||
# Must match standard
|
||||
if rule.get('standard') and rule.get('standard') != standard:
|
||||
continue
|
||||
# Must match file (check if rule file path is in the full path)
|
||||
rule_file = rule.get('file', '')
|
||||
if rule_file and rule_file not in file_path:
|
||||
continue
|
||||
# Check line-specific bypass
|
||||
rule_lines = rule.get('lines', [])
|
||||
if rule_lines and line is not None:
|
||||
if line in rule_lines:
|
||||
@@ -39,30 +41,18 @@ def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_r
|
||||
|
||||
def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check if module follows import standards
|
||||
Check if module follows import standards for pip packages.
|
||||
|
||||
Args:
|
||||
module_path: Path to Python module to check
|
||||
bypass_rules: Optional list of bypass rules to skip certain violations
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'passed': bool, # Overall pass/fail
|
||||
'checks': [ # Individual check results
|
||||
{
|
||||
'name': str, # Check name
|
||||
'passed': bool, # Pass/fail
|
||||
'message': str, # Details (line number, etc.)
|
||||
}
|
||||
],
|
||||
'score': int, # 0-100 percentage
|
||||
'standard': str # Standard name
|
||||
}
|
||||
Checks:
|
||||
1. No AIPASS_ROOT usage (pip packages don't need it)
|
||||
2. No sys.path hacking (pip packages resolve via installed paths)
|
||||
3. Prax logger via aipass.prax namespace (if applicable)
|
||||
4. Handler independence (no parent module imports)
|
||||
5. Import order (stdlib -> third-party -> aipass.*)
|
||||
"""
|
||||
checks = []
|
||||
path = Path(module_path)
|
||||
|
||||
# Check if entire standard is bypassed for this file
|
||||
if is_bypassed(module_path, 'imports', bypass_rules=bypass_rules):
|
||||
return {
|
||||
'passed': True,
|
||||
@@ -71,7 +61,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'IMPORTS'
|
||||
}
|
||||
|
||||
# Validate file exists
|
||||
if not path.exists():
|
||||
return {
|
||||
'passed': False,
|
||||
@@ -80,7 +69,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'IMPORTS'
|
||||
}
|
||||
|
||||
# Read file
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
@@ -93,53 +81,42 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'IMPORTS'
|
||||
}
|
||||
|
||||
# Filter out docstrings to prevent false positives from import examples
|
||||
filtered_lines = filter_docstrings(lines)
|
||||
|
||||
# Find import section boundaries
|
||||
import_section_end = find_import_section_end(filtered_lines)
|
||||
import_lines = filtered_lines[:import_section_end]
|
||||
|
||||
# Determine file type
|
||||
is_handler = '/handlers/' in module_path
|
||||
is_init_file = path.name == '__init__.py'
|
||||
is_small_file = len([l for l in lines if l.strip() and not l.strip().startswith('#')]) < 20
|
||||
|
||||
# Check 1: AIPASS_ROOT pattern (required for modules, optional for handlers)
|
||||
# Check 1: No AIPASS_ROOT (pip packages must not use it)
|
||||
if not is_init_file:
|
||||
aipass_root_check = check_aipass_root(import_lines, module_path, bypass_rules)
|
||||
checks.append(aipass_root_check)
|
||||
checks.append(check_no_aipass_root(import_lines, module_path, bypass_rules))
|
||||
|
||||
# Check 2: sys.path setup (required if AIPASS_ROOT exists)
|
||||
# Check 2: No sys.path hacking (pip packages resolve via installed paths)
|
||||
if not is_init_file:
|
||||
sys_path_check = check_sys_path(import_lines, module_path, bypass_rules)
|
||||
checks.append(sys_path_check)
|
||||
checks.append(check_no_sys_path(import_lines, module_path, bypass_rules))
|
||||
|
||||
# Check 3: Prax logger import (conditional - not required for small files/__init__/handlers)
|
||||
# Handlers MUST NOT import Prax (error_handling standard) - skip this recommendation for them
|
||||
# Check 3: Prax logger via aipass.prax (not for handlers, small files, or __init__)
|
||||
if not is_init_file and not is_small_file and not is_handler:
|
||||
prax_logger_check = check_prax_logger(import_lines, module_path, bypass_rules)
|
||||
# Make it informational for small files
|
||||
if prax_logger_check:
|
||||
checks.append(prax_logger_check)
|
||||
prax_check = check_prax_logger(import_lines, module_path, bypass_rules)
|
||||
if prax_check:
|
||||
checks.append(prax_check)
|
||||
|
||||
# Check 4: Handler independence (handlers must not import parent modules)
|
||||
if is_handler:
|
||||
handler_independence_check = check_handler_independence(import_lines, module_path, bypass_rules)
|
||||
if handler_independence_check:
|
||||
checks.append(handler_independence_check)
|
||||
handler_check = check_handler_independence(import_lines, module_path, bypass_rules)
|
||||
if handler_check:
|
||||
checks.append(handler_check)
|
||||
|
||||
# Check 5: Import order (only if file has imports)
|
||||
import_order_check = check_import_order(import_lines, module_path, bypass_rules)
|
||||
if import_order_check:
|
||||
checks.append(import_order_check)
|
||||
# Check 5: Import order (stdlib -> third-party -> aipass.*)
|
||||
order_check = check_import_order(import_lines, module_path, bypass_rules)
|
||||
if order_check:
|
||||
checks.append(order_check)
|
||||
|
||||
# Calculate score
|
||||
passed_checks = sum(1 for check in checks if check['passed'])
|
||||
total_checks = len(checks)
|
||||
score = int((passed_checks / total_checks * 100)) if total_checks > 0 else 0
|
||||
|
||||
# Overall pass if score >= 75%
|
||||
overall_passed = score >= 75
|
||||
|
||||
return {
|
||||
@@ -151,15 +128,7 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
|
||||
|
||||
def filter_docstrings(lines: List[str]) -> List[str]:
|
||||
"""
|
||||
Filter out docstrings from lines to prevent false positives.
|
||||
|
||||
This prevents import examples in module docstrings from being
|
||||
detected as actual imports.
|
||||
|
||||
Returns:
|
||||
List of lines with docstrings removed
|
||||
"""
|
||||
"""Filter out docstrings from lines to prevent false positives."""
|
||||
filtered_lines = []
|
||||
in_docstring = False
|
||||
docstring_marker = None
|
||||
@@ -167,263 +136,165 @@ def filter_docstrings(lines: List[str]) -> List[str]:
|
||||
for line in lines:
|
||||
stripped = line.strip()
|
||||
|
||||
# Check for docstring start/end
|
||||
if '"""' in stripped or "'''" in stripped:
|
||||
# Determine which marker we're looking for
|
||||
if '"""' in stripped:
|
||||
marker = '"""'
|
||||
else:
|
||||
marker = "'''"
|
||||
|
||||
# Count occurrences of the marker
|
||||
marker = '"""' if '"""' in stripped else "'''"
|
||||
marker_count = stripped.count(marker)
|
||||
|
||||
if not in_docstring:
|
||||
# Starting a docstring
|
||||
if marker_count == 2:
|
||||
# Single-line docstring - skip this line entirely
|
||||
if marker_count >= 2:
|
||||
continue
|
||||
elif marker_count == 1:
|
||||
# Multi-line docstring starting
|
||||
in_docstring = True
|
||||
docstring_marker = marker
|
||||
continue
|
||||
else:
|
||||
# Potentially ending a docstring
|
||||
if marker == docstring_marker and marker_count >= 1:
|
||||
# Multi-line docstring ending
|
||||
in_docstring = False
|
||||
docstring_marker = None
|
||||
continue
|
||||
|
||||
# Skip lines inside docstrings
|
||||
if in_docstring:
|
||||
continue
|
||||
|
||||
# Keep non-docstring lines
|
||||
filtered_lines.append(line)
|
||||
|
||||
return filtered_lines
|
||||
|
||||
|
||||
def find_import_section_end(lines: List[str]) -> int:
|
||||
"""
|
||||
Find the line number where the import section ends (first def/class).
|
||||
|
||||
This prevents false positives from matching patterns in docstrings,
|
||||
comments, or code examples.
|
||||
|
||||
Returns:
|
||||
Line number where imports end (0-indexed)
|
||||
"""
|
||||
"""Find where import section ends (first def/class)."""
|
||||
for i, line in enumerate(lines):
|
||||
stripped = line.strip()
|
||||
# Import section ends at first function or class definition
|
||||
if stripped.startswith('def ') or stripped.startswith('class ') or stripped.startswith('async def '):
|
||||
return i
|
||||
return len(lines)
|
||||
|
||||
|
||||
def check_aipass_root(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Dict:
|
||||
def check_no_aipass_root(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check for AIPASS_ROOT = Path.home() / "aipass_core" pattern
|
||||
|
||||
Only checks actual code lines (not comments)
|
||||
Check that file does NOT use AIPASS_ROOT.
|
||||
Pip packages resolve paths via installed package paths, not AIPASS_ROOT.
|
||||
"""
|
||||
# Check if entire standard is bypassed
|
||||
if is_bypassed(file_path, 'imports', None, bypass_rules):
|
||||
return {
|
||||
'name': 'AIPASS_ROOT pattern',
|
||||
'passed': True,
|
||||
'message': 'Bypassed by bypass rules'
|
||||
}
|
||||
return {'name': 'No AIPASS_ROOT', 'passed': True, 'message': 'Bypassed by bypass rules'}
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip comments and empty lines
|
||||
if not stripped or stripped.startswith('#'):
|
||||
continue
|
||||
|
||||
# Look for AIPASS_ROOT assignment (actual code, not in string)
|
||||
if 'AIPASS_ROOT' in line and '=' in line and 'Path.home()' in line:
|
||||
# Verify it's not in a comment at end of line
|
||||
if '#' in line:
|
||||
code_part = line.split('#')[0]
|
||||
if 'AIPASS_ROOT' in code_part and 'Path.home()' in code_part:
|
||||
return {
|
||||
'name': 'AIPASS_ROOT pattern',
|
||||
'passed': True,
|
||||
'message': f'Found on line {i}'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'name': 'AIPASS_ROOT pattern',
|
||||
'passed': True,
|
||||
'message': f'Found on line {i}'
|
||||
}
|
||||
code_part = line.split('#')[0] if '#' in line else line
|
||||
if 'AIPASS_ROOT' in code_part:
|
||||
return {
|
||||
'name': 'No AIPASS_ROOT',
|
||||
'passed': False,
|
||||
'message': f'AIPASS_ROOT found on line {i} (pip packages must not use AIPASS_ROOT)'
|
||||
}
|
||||
|
||||
return {
|
||||
'name': 'AIPASS_ROOT pattern',
|
||||
'passed': False,
|
||||
'message': 'AIPASS_ROOT = Path.home() / "aipass_core" not found in import section'
|
||||
'name': 'No AIPASS_ROOT',
|
||||
'passed': True,
|
||||
'message': 'No AIPASS_ROOT usage (correct for pip packages)'
|
||||
}
|
||||
|
||||
|
||||
def check_sys_path(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Dict:
|
||||
def check_no_sys_path(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check for sys.path.insert(0, str(AIPASS_ROOT)) pattern
|
||||
|
||||
Only checks actual code lines (not comments)
|
||||
Check that file does NOT hack sys.path.
|
||||
Pip packages resolve imports via installed package paths.
|
||||
"""
|
||||
# Check if entire standard is bypassed
|
||||
if is_bypassed(file_path, 'imports', None, bypass_rules):
|
||||
return {
|
||||
'name': 'sys.path setup',
|
||||
'passed': True,
|
||||
'message': 'Bypassed by bypass rules'
|
||||
}
|
||||
return {'name': 'No sys.path hacking', 'passed': True, 'message': 'Bypassed by bypass rules'}
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip comments and empty lines
|
||||
if not stripped or stripped.startswith('#'):
|
||||
continue
|
||||
|
||||
# Look for sys.path.insert with AIPASS_ROOT
|
||||
if 'sys.path.insert' in line and 'AIPASS_ROOT' in line:
|
||||
# Verify it's not in a comment
|
||||
if '#' in line:
|
||||
code_part = line.split('#')[0]
|
||||
if 'sys.path.insert' in code_part and 'AIPASS_ROOT' in code_part:
|
||||
return {
|
||||
'name': 'sys.path setup',
|
||||
'passed': True,
|
||||
'message': f'Found on line {i}'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'name': 'sys.path setup',
|
||||
'passed': True,
|
||||
'message': f'Found on line {i}'
|
||||
}
|
||||
code_part = line.split('#')[0] if '#' in line else line
|
||||
if re.search(r'sys\.path\.(insert|append)\s*\(', code_part):
|
||||
return {
|
||||
'name': 'No sys.path hacking',
|
||||
'passed': False,
|
||||
'message': f'sys.path manipulation found on line {i} (pip packages must not hack sys.path)'
|
||||
}
|
||||
|
||||
return {
|
||||
'name': 'sys.path setup',
|
||||
'passed': False,
|
||||
'message': 'sys.path.insert(0, str(AIPASS_ROOT)) not found in import section'
|
||||
'name': 'No sys.path hacking',
|
||||
'passed': True,
|
||||
'message': 'No sys.path manipulation (correct for pip packages)'
|
||||
}
|
||||
|
||||
|
||||
def check_prax_logger(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Optional[Dict]:
|
||||
"""
|
||||
Check for Prax logger import
|
||||
|
||||
Note: "Nearly always" not "always" - conditional check
|
||||
Check for Prax logger import via aipass.prax namespace.
|
||||
Pattern: from aipass.prax import logger
|
||||
"""
|
||||
# Check if entire standard is bypassed
|
||||
if is_bypassed(file_path, 'imports', None, bypass_rules):
|
||||
return {
|
||||
'name': 'Prax logger import',
|
||||
'passed': True,
|
||||
'message': 'Bypassed by bypass rules'
|
||||
}
|
||||
return {'name': 'Prax logger import', 'passed': True, 'message': 'Bypassed by bypass rules'}
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip comments and empty lines
|
||||
if not stripped or stripped.startswith('#'):
|
||||
continue
|
||||
|
||||
# Look for prax logger import
|
||||
if 'from prax.apps.modules.logger import' in line and 'system_logger' in line:
|
||||
if 'from aipass.prax' in line and 'logger' in line:
|
||||
return {
|
||||
'name': 'Prax logger import',
|
||||
'passed': True,
|
||||
'message': f'Found on line {i}'
|
||||
}
|
||||
|
||||
# Return informational failure (not critical)
|
||||
return {
|
||||
'name': 'Prax logger import (recommended)',
|
||||
'passed': False,
|
||||
'message': 'Prax logger import not found (recommended: from prax.apps.modules.logger import system_logger)'
|
||||
'message': 'Prax logger import not found (recommended: from aipass.prax import logger)'
|
||||
}
|
||||
|
||||
|
||||
def check_handler_independence(lines: List[str], module_path: str = "", bypass_rules: list | None = None) -> Optional[Dict]:
|
||||
"""
|
||||
Check that handlers don't import from parent branch modules.
|
||||
|
||||
Handlers must be independent and transportable.
|
||||
Forbidden: from <parent_branch>.apps.modules import ...
|
||||
Allowed: from prax.apps.modules.logger import ... (service imports)
|
||||
Allowed: from cli.apps.modules import ... (service imports)
|
||||
|
||||
Args:
|
||||
lines: Lines to check
|
||||
module_path: Full path to module (to detect parent branch)
|
||||
bypass_rules: Optional list of bypass rules to skip certain violations
|
||||
|
||||
Returns check result or None if not applicable
|
||||
Allowed: from aipass.prax import ... (infrastructure)
|
||||
Allowed: from aipass.cli import ... (infrastructure)
|
||||
Forbidden: from <parent>.apps.modules import ...
|
||||
"""
|
||||
# Check if entire standard is bypassed
|
||||
if is_bypassed(module_path, 'imports', None, bypass_rules):
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
'passed': True,
|
||||
'message': 'Bypassed by bypass rules'
|
||||
}
|
||||
return {'name': 'Handler independence', 'passed': True, 'message': 'Bypassed by bypass rules'}
|
||||
|
||||
# Detect parent branch from module path
|
||||
# e.g., /home/aipass/seed/apps/handlers/... -> parent is 'seed'
|
||||
# e.g., /home/aipass/aipass_core/api/apps/handlers/... -> parent is 'api'
|
||||
parent_branch = None
|
||||
if module_path:
|
||||
path_parts = Path(module_path).parts
|
||||
# Find 'apps' in path and get the directory before it
|
||||
for i, part in enumerate(path_parts):
|
||||
if part == 'apps' and i > 0:
|
||||
parent_branch = path_parts[i-1]
|
||||
parent_branch = path_parts[i - 1]
|
||||
break
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip comments and empty lines
|
||||
if not stripped or stripped.startswith('#'):
|
||||
continue
|
||||
|
||||
# Check for forbidden module imports
|
||||
if '.apps.modules' in line and ('from ' in line or 'import ' in line):
|
||||
# Extract the import statement
|
||||
if '#' in line:
|
||||
code_part = line.split('#')[0]
|
||||
else:
|
||||
code_part = line
|
||||
code_part = line.split('#')[0] if '#' in line else line
|
||||
if '.apps.modules' not in code_part:
|
||||
continue
|
||||
|
||||
if '.apps.modules' in code_part:
|
||||
# Allowed service imports (prax, cli are infrastructure)
|
||||
if 'prax.apps.modules' in code_part or 'cli.apps.modules' in code_part:
|
||||
continue
|
||||
# Allowed: aipass.prax, aipass.cli (infrastructure services)
|
||||
if 'aipass.prax' in code_part or 'aipass.cli' in code_part:
|
||||
continue
|
||||
|
||||
# If we detected parent branch, check if importing from it
|
||||
if parent_branch and f'{parent_branch}.apps.modules' in code_part:
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
'passed': False,
|
||||
'message': f'Handler importing from parent module on line {i} (violates independence rule)'
|
||||
}
|
||||
if parent_branch and f'{parent_branch}.apps.modules' in code_part:
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
'passed': False,
|
||||
'message': f'Handler importing from parent module on line {i} (violates independence rule)'
|
||||
}
|
||||
|
||||
# Generic check if no parent branch detected
|
||||
if not parent_branch:
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
'passed': False,
|
||||
'message': f'Handler importing from branch module on line {i} (violates independence rule)'
|
||||
}
|
||||
if not parent_branch:
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
'passed': False,
|
||||
'message': f'Handler importing from branch module on line {i} (violates independence rule)'
|
||||
}
|
||||
|
||||
return {
|
||||
'name': 'Handler independence',
|
||||
@@ -434,79 +305,58 @@ def check_handler_independence(lines: List[str], module_path: str = "", bypass_r
|
||||
|
||||
def check_import_order(lines: List[str], file_path: str = "", bypass_rules: list | None = None) -> Optional[Dict]:
|
||||
"""
|
||||
Check import order: infrastructure → Prax → services → internal
|
||||
Check import order: stdlib -> third-party -> aipass.*
|
||||
|
||||
Returns check result or None if no imports found
|
||||
For pip packages, the order should be:
|
||||
1. Standard library (import os, from pathlib, etc.)
|
||||
2. Third-party packages (import rich, etc.)
|
||||
3. aipass.* namespace imports (from aipass.prax, from aipass.cli, etc.)
|
||||
"""
|
||||
# Check if entire standard is bypassed
|
||||
if is_bypassed(file_path, 'imports', None, bypass_rules):
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': True,
|
||||
'message': 'Bypassed by bypass rules'
|
||||
}
|
||||
return {'name': 'Import order', 'passed': True, 'message': 'Bypassed by bypass rules'}
|
||||
|
||||
# Find all import lines with their line numbers
|
||||
imports = []
|
||||
prax_line = None
|
||||
|
||||
for i, line in enumerate(lines, 1):
|
||||
stripped = line.strip()
|
||||
|
||||
# Skip comments and empty lines
|
||||
if not stripped or stripped.startswith('#'):
|
||||
continue
|
||||
|
||||
# Check for import statements
|
||||
if stripped.startswith('import ') or stripped.startswith('from '):
|
||||
# Track Prax logger specifically
|
||||
if 'prax.apps.modules.logger' in stripped:
|
||||
prax_line = i
|
||||
imports.append((i, stripped))
|
||||
|
||||
# Track other imports (not infrastructure setup)
|
||||
if 'import sys' not in stripped and 'from pathlib' not in stripped:
|
||||
imports.append((i, stripped))
|
||||
|
||||
# If no imports found, skip this check
|
||||
if not imports:
|
||||
return None
|
||||
|
||||
# Simple check: if Prax is imported, it should be early (before internal imports)
|
||||
if prax_line:
|
||||
# Find first internal import (seed.apps, cli.apps, etc.)
|
||||
first_internal_line = None
|
||||
for line_num, import_stmt in imports:
|
||||
# Check for any .apps. pattern (internal imports)
|
||||
if '.apps.' in import_stmt:
|
||||
# Skip if it's the Prax logger itself
|
||||
if 'prax.apps.modules.logger' not in import_stmt:
|
||||
first_internal_line = line_num
|
||||
break
|
||||
# Track where aipass.* imports appear vs stdlib
|
||||
last_stdlib_line = 0
|
||||
first_aipass_line = None
|
||||
|
||||
# If we have internal imports, Prax should come before them
|
||||
if first_internal_line and prax_line < first_internal_line:
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': True,
|
||||
'message': f'Prax logger before internal imports (line {prax_line} < {first_internal_line})'
|
||||
}
|
||||
elif first_internal_line:
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': False,
|
||||
'message': f'Prax logger should be before internal imports (line {prax_line} > {first_internal_line})'
|
||||
}
|
||||
else:
|
||||
# No internal imports, Prax is fine
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': True,
|
||||
'message': 'Prax logger imported (no internal imports to check)'
|
||||
}
|
||||
# Common stdlib modules
|
||||
stdlib_prefixes = (
|
||||
'import os', 'import sys', 'import re', 'import json', 'import time',
|
||||
'import logging', 'import subprocess', 'import shutil', 'import copy',
|
||||
'import hashlib', 'import datetime', 'import tempfile', 'import ast',
|
||||
'import argparse', 'import importlib', 'import inspect', 'import unittest',
|
||||
'from pathlib', 'from typing', 'from datetime', 'from collections',
|
||||
'from functools', 'from dataclasses', 'from enum', 'from abc',
|
||||
'from io', 'from os', 'from contextlib',
|
||||
)
|
||||
|
||||
for line_num, import_stmt in imports:
|
||||
if any(import_stmt.startswith(p) for p in stdlib_prefixes):
|
||||
last_stdlib_line = line_num
|
||||
elif 'from aipass.' in import_stmt or import_stmt.startswith('import aipass'):
|
||||
if first_aipass_line is None:
|
||||
first_aipass_line = line_num
|
||||
|
||||
if first_aipass_line and last_stdlib_line and first_aipass_line < last_stdlib_line:
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': False,
|
||||
'message': f'aipass.* import (line {first_aipass_line}) before stdlib import (line {last_stdlib_line})'
|
||||
}
|
||||
|
||||
# If no Prax logger, we already failed that check, so import order is N/A
|
||||
return {
|
||||
'name': 'Import order',
|
||||
'passed': True,
|
||||
'message': 'No specific order issues detected'
|
||||
'message': 'Import order correct (stdlib before aipass.*)'
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted import standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: imports_content.py
|
||||
# Description: Import Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_imports_standards() -> str:
|
||||
"""Return formatted import standards content with Rich markup
|
||||
|
||||
+199
-316
@@ -1,39 +1,38 @@
|
||||
"""
|
||||
JSON Structure Standards Checker Handler
|
||||
|
||||
Validates three-JSON pattern implementation:
|
||||
- Handler configuration (correct paths)
|
||||
- JSON file existence for modules
|
||||
- Naming patterns
|
||||
- Directory structure
|
||||
|
||||
This checker catches:
|
||||
- Misconfigured json_handler.py (wrong BRANCH_ROOT paths)
|
||||
- Missing JSON files for modules
|
||||
- Non-standard naming patterns
|
||||
- Orphaned JSON files
|
||||
Validates JSON handling patterns for pip packages:
|
||||
- json_handler.py uses relative paths (not hardcoded absolute)
|
||||
- Modules use json_handler for JSON operations (not direct json.load/dump)
|
||||
- Branch detection via AIPASS_REGISTRY.json and BRANCH_REGISTRY.json
|
||||
"""
|
||||
|
||||
import sys
|
||||
# =================== META ====================
|
||||
# Name: json_structure_check.py
|
||||
# Description: JSON Structure Standards Checker Handler
|
||||
# Version: 2.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
import ast
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
|
||||
def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_rules: list | None = None) -> bool:
|
||||
"""Check if a violation should be bypassed"""
|
||||
if not bypass_rules:
|
||||
return False
|
||||
for rule in bypass_rules:
|
||||
# Must match standard
|
||||
if rule.get('standard') and rule.get('standard') != standard:
|
||||
continue
|
||||
# Must match file (check if rule file path is in the full path)
|
||||
rule_file = rule.get('file', '')
|
||||
if rule_file and rule_file not in file_path:
|
||||
continue
|
||||
# Check line-specific bypass
|
||||
rule_lines = rule.get('lines', [])
|
||||
if rule_lines and line is not None:
|
||||
if line in rule_lines:
|
||||
@@ -45,29 +44,16 @@ def is_bypassed(file_path: str, standard: str, line: int | None = None, bypass_r
|
||||
|
||||
def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check if module follows JSON structure standards
|
||||
Check if module follows JSON structure standards.
|
||||
|
||||
Validates:
|
||||
1. json_handler.py files: Configuration correctness
|
||||
2. Modules using json_handler: JSON files exist
|
||||
3. Direct JSON operations: Should use json_handler
|
||||
|
||||
Args:
|
||||
module_path: Path to Python module to check
|
||||
bypass_rules: Optional list of bypass rules to skip specific violations
|
||||
|
||||
Returns:
|
||||
dict: {
|
||||
'passed': bool,
|
||||
'checks': [{'name': str, 'passed': bool, 'message': str}],
|
||||
'score': int,
|
||||
'standard': str
|
||||
}
|
||||
For pip packages, validates:
|
||||
1. json_handler.py uses relative paths (Path(__file__).resolve().parent)
|
||||
2. json_handler.py does NOT use hardcoded absolute paths (BRANCH_ROOT, Path.home())
|
||||
3. Modules use json_handler instead of direct json.load/dump
|
||||
"""
|
||||
checks = []
|
||||
path = Path(module_path)
|
||||
|
||||
# Validate file exists
|
||||
if not path.exists():
|
||||
return {
|
||||
'passed': False,
|
||||
@@ -76,7 +62,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'JSON STRUCTURE'
|
||||
}
|
||||
|
||||
# Read file
|
||||
try:
|
||||
with open(path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
@@ -88,20 +73,11 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'JSON STRUCTURE'
|
||||
}
|
||||
|
||||
# Determine what type of file this is
|
||||
if 'json_handler' in path.name and path.parent.name == 'json':
|
||||
# This is a json_handler.py file - check configuration
|
||||
checks = check_json_handler_config(path, content, bypass_rules)
|
||||
elif 'apps/modules' in str(path):
|
||||
# This is a module - check if it has JSON files (if it uses json_handler)
|
||||
checks = check_module_json_files(path, content, bypass_rules)
|
||||
else:
|
||||
# Other files - check for direct JSON operations
|
||||
json_check = check_json_handler_usage(content, module_path, bypass_rules)
|
||||
if json_check:
|
||||
checks.append(json_check)
|
||||
|
||||
# If no checks, skip (not applicable)
|
||||
if not checks:
|
||||
return {
|
||||
'passed': True,
|
||||
@@ -110,7 +86,6 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
'standard': 'JSON STRUCTURE'
|
||||
}
|
||||
|
||||
# Calculate score
|
||||
passed_checks = sum(1 for check in checks if check['passed'])
|
||||
total_checks = len(checks)
|
||||
score = int((passed_checks / total_checks * 100)) if total_checks > 0 else 0
|
||||
@@ -124,279 +99,22 @@ def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
}
|
||||
|
||||
|
||||
def get_branch_path(branch_name: str) -> Optional[str]:
|
||||
"""Get actual branch path from BRANCH_REGISTRY.json"""
|
||||
registry_path = Path.home() / "BRANCH_REGISTRY.json"
|
||||
if registry_path.exists():
|
||||
try:
|
||||
with open(registry_path, 'r', encoding='utf-8') as f:
|
||||
registry = json.load(f)
|
||||
for branch in registry.get('branches', []):
|
||||
if branch.get('name', '').lower() == branch_name.lower():
|
||||
return branch.get('path', '')
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def check_json_handler_config(handler_path: Path, content: str, bypass_rules: list | None = None) -> List[Dict]:
|
||||
"""
|
||||
Check if json_handler.py is configured correctly for its branch
|
||||
|
||||
Critical checks:
|
||||
- BRANCH_ROOT points to correct branch (not SEED)
|
||||
- JSON_DIR points to {branch}_json/
|
||||
- TEMPLATES_DIR points to branch's templates
|
||||
"""
|
||||
checks = []
|
||||
branch_name = detect_branch(handler_path)
|
||||
|
||||
if not branch_name:
|
||||
checks.append({
|
||||
'name': 'Branch detection',
|
||||
'passed': False,
|
||||
'message': f'Cannot detect branch from path: {handler_path}'
|
||||
})
|
||||
return checks
|
||||
|
||||
# Get actual branch path from registry
|
||||
actual_branch_path = get_branch_path(branch_name)
|
||||
if actual_branch_path:
|
||||
# Convert path to relative from home for display
|
||||
home = str(Path.home())
|
||||
relative_path = actual_branch_path.replace(home + '/', '')
|
||||
else:
|
||||
relative_path = f'aipass_core/{branch_name}' # Fallback assumption
|
||||
|
||||
# Check 1: BRANCH_ROOT configuration
|
||||
# Pattern matches: BRANCH_ROOT = Path.home() / "path" or BRANCH_ROOT = Path.home() / 'path'
|
||||
root_var_pattern = r"(\w+)_ROOT\s*=\s*Path\.home\(\)\s*/\s*['\"]([^'\"]+)['\"]"
|
||||
root_matches = re.findall(root_var_pattern, content)
|
||||
|
||||
var_prefix = branch_name.upper()
|
||||
|
||||
root_check_passed = False
|
||||
root_message = ''
|
||||
|
||||
# Filter to only check the branch-specific ROOT constant (ignore AIPASS_ROOT which is infrastructure)
|
||||
branch_specific_matches = [(var_name, path_value) for var_name, path_value in root_matches if var_name != 'AIPASS']
|
||||
|
||||
for var_name, path_value in branch_specific_matches:
|
||||
# var_name is already just the prefix (e.g., "SEED" from "SEED_ROOT")
|
||||
# Check if pointing to correct location
|
||||
if branch_name == 'seed' and path_value == 'seed':
|
||||
root_check_passed = True
|
||||
root_message = f'{var_name}_ROOT correctly points to /home/aipass/seed'
|
||||
elif branch_name != 'seed':
|
||||
# For other branches, check if handler path matches actual branch path
|
||||
if actual_branch_path and actual_branch_path in str(handler_path):
|
||||
# Handler is in correct branch - check if ROOT constant points to same location
|
||||
# Build expected path pattern from relative_path
|
||||
path_parts = relative_path.split('/')
|
||||
expected_pattern = '" / "'.join(path_parts)
|
||||
if expected_pattern in content or expected_pattern.replace('" / "', "' / '") in content:
|
||||
root_check_passed = True
|
||||
root_message = f'{var_name}_ROOT correctly points to {actual_branch_path}'
|
||||
elif 'seed' in path_value.lower():
|
||||
root_check_passed = False
|
||||
root_message = f'{var_name}_ROOT points to SEED paths - should point to {actual_branch_path}'
|
||||
break
|
||||
elif 'seed' in path_value.lower():
|
||||
root_check_passed = False
|
||||
root_message = f'{var_name}_ROOT points to SEED paths - should point to {actual_branch_path or relative_path}'
|
||||
break
|
||||
|
||||
if not root_matches:
|
||||
checks.append({
|
||||
'name': 'BRANCH_ROOT configuration',
|
||||
'passed': False,
|
||||
'message': 'No BRANCH_ROOT constant found in handler'
|
||||
})
|
||||
elif not branch_specific_matches:
|
||||
checks.append({
|
||||
'name': 'BRANCH_ROOT configuration',
|
||||
'passed': False,
|
||||
'message': f'No {branch_name.upper()}_ROOT constant found (only AIPASS_ROOT infrastructure)'
|
||||
})
|
||||
else:
|
||||
if not root_message:
|
||||
root_message = f'Unable to validate {branch_name.upper()}_ROOT configuration'
|
||||
checks.append({
|
||||
'name': 'BRANCH_ROOT configuration',
|
||||
'passed': root_check_passed,
|
||||
'message': root_message
|
||||
})
|
||||
|
||||
# Check 2: JSON_DIR configuration
|
||||
json_dir_pattern = r"(\w+)_JSON_DIR\s*="
|
||||
json_dir_matches = re.findall(json_dir_pattern, content)
|
||||
|
||||
if json_dir_matches:
|
||||
expected_json_dir = f'{branch_name}_json'
|
||||
json_dir_correct = any(expected_json_dir in content for expected_json_dir in [f'"{branch_name}_json"', f"'{branch_name}_json'", f'/ "{branch_name}_json"', f"/ '{branch_name}_json'"])
|
||||
|
||||
checks.append({
|
||||
'name': 'JSON_DIR configuration',
|
||||
'passed': json_dir_correct,
|
||||
'message': f'JSON_DIR {"correctly" if json_dir_correct else "incorrectly"} configured (should point to {branch_name}_json/)'
|
||||
})
|
||||
|
||||
# Check 3: TEMPLATES_DIR configuration
|
||||
templates_pattern = r"TEMPLATES_DIR\s*="
|
||||
if re.search(templates_pattern, content):
|
||||
# Should reference branch's own templates, not SEED's
|
||||
if branch_name != 'seed' and 'seed' in content.lower() and 'json_templates' in content:
|
||||
# Check if it's using SEED's templates
|
||||
seed_template_check = '"seed"' in content and 'json_templates' in content
|
||||
checks.append({
|
||||
'name': 'TEMPLATES_DIR configuration',
|
||||
'passed': not seed_template_check,
|
||||
'message': 'TEMPLATES_DIR points to SEED - should use branch templates' if seed_template_check else 'TEMPLATES_DIR correctly configured'
|
||||
})
|
||||
|
||||
return checks
|
||||
|
||||
|
||||
def check_module_json_files(module_path: Path, content: str, bypass_rules: list | None = None) -> List[Dict]:
|
||||
"""
|
||||
Check if module has its three JSON files (if it uses json_handler)
|
||||
|
||||
Checks:
|
||||
- If module imports json_handler, it should have config/data/log files
|
||||
- Files should be in correct directory
|
||||
- Naming should follow pattern
|
||||
"""
|
||||
checks = []
|
||||
|
||||
# Check if module uses json_handler
|
||||
uses_json_handler = 'from' in content and 'json_handler import' in content
|
||||
|
||||
if not uses_json_handler:
|
||||
# Module doesn't use json_handler - check if it should
|
||||
has_json_ops = check_json_handler_usage(content, str(module_path), bypass_rules)
|
||||
if has_json_ops:
|
||||
checks.append(has_json_ops)
|
||||
return checks
|
||||
|
||||
# Module uses json_handler - verify JSON files exist
|
||||
branch_name = detect_branch(module_path)
|
||||
module_name = module_path.stem
|
||||
|
||||
if not branch_name:
|
||||
checks.append({
|
||||
'name': 'Branch detection',
|
||||
'passed': False,
|
||||
'message': f'Cannot detect branch from path: {module_path}'
|
||||
})
|
||||
return checks
|
||||
|
||||
if branch_name == 'seed':
|
||||
json_dir = Path.home() / 'seed' / 'seed_json'
|
||||
else:
|
||||
json_dir = Path.home() / 'aipass_core' / branch_name / f'{branch_name}_json'
|
||||
|
||||
# Check if directory exists
|
||||
if not json_dir.exists():
|
||||
checks.append({
|
||||
'name': 'JSON directory exists',
|
||||
'passed': False,
|
||||
'message': f'JSON directory not found: {json_dir}'
|
||||
})
|
||||
return checks
|
||||
|
||||
# Check for three JSON files
|
||||
config_file = json_dir / f'{module_name}_config.json'
|
||||
data_file = json_dir / f'{module_name}_data.json'
|
||||
log_file = json_dir / f'{module_name}_log.json'
|
||||
|
||||
files_status = []
|
||||
all_exist = True
|
||||
|
||||
for json_type, json_file in [('config', config_file), ('data', data_file), ('log', log_file)]:
|
||||
if json_file.exists():
|
||||
files_status.append(f'{json_type}✓')
|
||||
else:
|
||||
files_status.append(f'{json_type}✗')
|
||||
all_exist = False
|
||||
|
||||
checks.append({
|
||||
'name': 'Module JSON files',
|
||||
'passed': all_exist,
|
||||
'message': f'Module JSON files: {", ".join(files_status)} in {json_dir.name}/' if all_exist else f'Missing JSON files: {", ".join(files_status)} - should exist in {json_dir.name}/'
|
||||
})
|
||||
|
||||
return checks
|
||||
|
||||
|
||||
def check_json_handler_usage(content: str, file_path: str, bypass_rules: list | None = None) -> Optional[Dict]:
|
||||
"""
|
||||
Check that modules use json_handler for JSON operations (not direct json.load/dump)
|
||||
"""
|
||||
try:
|
||||
tree = ast.parse(content)
|
||||
except SyntaxError:
|
||||
return None
|
||||
|
||||
has_json_import = False
|
||||
has_json_operations = False
|
||||
has_json_handler_import = False
|
||||
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
if alias.name == 'json':
|
||||
has_json_import = True
|
||||
|
||||
if isinstance(node, ast.ImportFrom):
|
||||
if node.module == 'json':
|
||||
has_json_import = True
|
||||
if node.module and 'json_handler' in node.module:
|
||||
has_json_handler_import = True
|
||||
|
||||
if isinstance(node, ast.Call):
|
||||
if isinstance(node.func, ast.Attribute):
|
||||
if (isinstance(node.func.value, ast.Name) and
|
||||
node.func.value.id == 'json' and
|
||||
node.func.attr in ['dump', 'load']):
|
||||
has_json_operations = True
|
||||
|
||||
# No JSON operations detected
|
||||
if not has_json_import and not has_json_operations:
|
||||
return None
|
||||
|
||||
# Has JSON operations but not using json_handler
|
||||
if has_json_operations and not has_json_handler_import:
|
||||
# Check if bypassed
|
||||
if is_bypassed(file_path, 'json_structure', bypass_rules=bypass_rules):
|
||||
return None
|
||||
|
||||
return {
|
||||
'name': 'json_handler usage',
|
||||
'passed': False,
|
||||
'message': 'Direct JSON operations detected (use json_handler for three-JSON pattern)'
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def detect_branch(file_path: Path) -> Optional[str]:
|
||||
"""
|
||||
Detect which branch a file belongs to from its path
|
||||
Detect which branch a file belongs to from its path.
|
||||
|
||||
Uses BRANCH_REGISTRY.json as source of truth for all branch paths.
|
||||
Falls back to path heuristics if registry unavailable.
|
||||
|
||||
Returns branch name (lowercase) or None if cannot detect
|
||||
Checks both AIPASS_REGISTRY.json (pip/library) and
|
||||
BRANCH_REGISTRY.json (Dev-Pass) as sources of truth.
|
||||
Falls back to path heuristics if neither available.
|
||||
"""
|
||||
file_path_str = str(file_path)
|
||||
|
||||
# Try BRANCH_REGISTRY.json first (source of truth)
|
||||
registry_path = Path.home() / "BRANCH_REGISTRY.json"
|
||||
if registry_path.exists():
|
||||
# Try AIPASS_REGISTRY.json first (library profile)
|
||||
aipass_registry = Path(__file__).parents[8] / "AIPASS_REGISTRY.json"
|
||||
if aipass_registry.exists():
|
||||
try:
|
||||
with open(registry_path, 'r', encoding='utf-8') as f:
|
||||
with open(aipass_registry, 'r', encoding='utf-8') as f:
|
||||
registry = json.load(f)
|
||||
# Sort by path length (longest first) to match most specific path
|
||||
branches = sorted(
|
||||
registry.get('branches', []),
|
||||
key=lambda b: len(b.get('path', '')),
|
||||
@@ -407,19 +125,184 @@ def detect_branch(file_path: Path) -> Optional[str]:
|
||||
if branch_path and file_path_str.startswith(branch_path):
|
||||
return branch.get('name', '').lower()
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass # Fall through to heuristics
|
||||
pass
|
||||
|
||||
# Fallback: path-based heuristics
|
||||
# Try BRANCH_REGISTRY.json (Dev-Pass)
|
||||
branch_registry = Path.home() / "BRANCH_REGISTRY.json"
|
||||
if branch_registry.exists():
|
||||
try:
|
||||
with open(branch_registry, 'r', encoding='utf-8') as f:
|
||||
registry = json.load(f)
|
||||
branches = sorted(
|
||||
registry.get('branches', []),
|
||||
key=lambda b: len(b.get('path', '')),
|
||||
reverse=True
|
||||
)
|
||||
for branch in branches:
|
||||
branch_path = branch.get('path', '')
|
||||
if branch_path and file_path_str.startswith(branch_path):
|
||||
return branch.get('name', '').lower()
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass
|
||||
|
||||
# Fallback: path heuristics
|
||||
path_parts = file_path.parts
|
||||
|
||||
# Check if in seed
|
||||
if 'seed' in path_parts:
|
||||
return 'seed'
|
||||
|
||||
# Check if in aipass_core/{branch}
|
||||
if 'seedgo' in path_parts:
|
||||
return 'seedgo'
|
||||
if 'aipass_core' in path_parts:
|
||||
idx = path_parts.index('aipass_core')
|
||||
if idx + 1 < len(path_parts):
|
||||
return path_parts[idx + 1]
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_branch_path(branch_name: str) -> Optional[str]:
|
||||
"""Get actual branch path from registries."""
|
||||
# Try AIPASS_REGISTRY.json first
|
||||
aipass_registry = Path(__file__).parents[8] / "AIPASS_REGISTRY.json"
|
||||
if aipass_registry.exists():
|
||||
try:
|
||||
with open(aipass_registry, 'r', encoding='utf-8') as f:
|
||||
registry = json.load(f)
|
||||
for branch in registry.get('branches', []):
|
||||
if branch.get('name', '').lower() == branch_name.lower():
|
||||
return branch.get('path', '')
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass
|
||||
|
||||
# Fall back to BRANCH_REGISTRY.json
|
||||
branch_registry = Path.home() / "BRANCH_REGISTRY.json"
|
||||
if branch_registry.exists():
|
||||
try:
|
||||
with open(branch_registry, 'r', encoding='utf-8') as f:
|
||||
registry = json.load(f)
|
||||
for branch in registry.get('branches', []):
|
||||
if branch.get('name', '').lower() == branch_name.lower():
|
||||
return branch.get('path', '')
|
||||
except (json.JSONDecodeError, IOError):
|
||||
pass
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def check_json_handler_config(handler_path: Path, content: str, bypass_rules: list | None = None) -> List[Dict]: # noqa: ARG001
|
||||
"""
|
||||
Check json_handler.py for library profile.
|
||||
|
||||
For pip packages:
|
||||
- PASS if using relative paths (Path(__file__).resolve().parent, etc.)
|
||||
- FAIL if using hardcoded absolute paths (Path.home(), BRANCH_ROOT, etc.)
|
||||
"""
|
||||
checks = []
|
||||
|
||||
# Check 1: No hardcoded absolute paths
|
||||
has_path_home = bool(re.search(r'Path\.home\(\)', content))
|
||||
# Only flag _ROOT constants that use Path.home() (Dev-Pass pattern)
|
||||
# Allow _ROOT = Path(__file__).resolve()... (relative, pip-safe)
|
||||
has_branch_root = False
|
||||
for line in content.split('\n'):
|
||||
stripped = line.strip()
|
||||
if stripped.startswith('#'):
|
||||
continue
|
||||
if re.search(r'\w+_ROOT\s*=', stripped) and 'Path.home()' in stripped:
|
||||
has_branch_root = True
|
||||
break
|
||||
|
||||
if has_path_home or has_branch_root:
|
||||
issues = []
|
||||
if has_path_home:
|
||||
issues.append('Path.home()')
|
||||
if has_branch_root:
|
||||
issues.append('hardcoded _ROOT constant')
|
||||
checks.append({
|
||||
'name': 'No absolute paths',
|
||||
'passed': False,
|
||||
'message': f'Found {", ".join(issues)} — pip packages should use relative paths'
|
||||
})
|
||||
else:
|
||||
checks.append({
|
||||
'name': 'No absolute paths',
|
||||
'passed': True,
|
||||
'message': 'No hardcoded absolute paths (correct for pip packages)'
|
||||
})
|
||||
|
||||
# Check 2: Uses relative path resolution
|
||||
has_relative = bool(re.search(r'Path\(__file__\)', content) or
|
||||
re.search(r'\.resolve\(\)', content) or
|
||||
re.search(r'\.parent', content))
|
||||
|
||||
checks.append({
|
||||
'name': 'Relative path resolution',
|
||||
'passed': has_relative,
|
||||
'message': 'Uses relative path resolution (Path(__file__).parent)' if has_relative
|
||||
else 'Missing relative path resolution — should use Path(__file__).resolve().parent'
|
||||
})
|
||||
|
||||
return checks
|
||||
|
||||
|
||||
def check_module_json_files(module_path: Path, content: str, bypass_rules: list | None = None) -> List[Dict]:
|
||||
"""
|
||||
Check if module uses json_handler for JSON operations.
|
||||
For library profile, just validates json_handler usage pattern.
|
||||
"""
|
||||
checks = []
|
||||
|
||||
uses_json_handler = 'json_handler' in content and ('from' in content or 'import' in content)
|
||||
|
||||
if not uses_json_handler:
|
||||
json_check = check_json_handler_usage(content, str(module_path), bypass_rules)
|
||||
if json_check:
|
||||
checks.append(json_check)
|
||||
return checks
|
||||
|
||||
# Module uses json_handler — that's correct
|
||||
checks.append({
|
||||
'name': 'json_handler usage',
|
||||
'passed': True,
|
||||
'message': 'Module uses json_handler for JSON operations'
|
||||
})
|
||||
|
||||
return checks
|
||||
|
||||
|
||||
def check_json_handler_usage(content: str, file_path: str, bypass_rules: list | None = None) -> Optional[Dict]:
|
||||
"""
|
||||
Check that modules use json_handler for JSON operations (not direct json.load/dump).
|
||||
"""
|
||||
try:
|
||||
tree = ast.parse(content)
|
||||
except SyntaxError:
|
||||
return None
|
||||
|
||||
has_json_operations = False
|
||||
has_json_handler_import = False
|
||||
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.ImportFrom):
|
||||
if node.module and 'json_handler' in node.module:
|
||||
has_json_handler_import = True
|
||||
|
||||
if isinstance(node, ast.Call):
|
||||
if isinstance(node.func, ast.Attribute):
|
||||
if (isinstance(node.func.value, ast.Name) and
|
||||
node.func.value.id == 'json' and
|
||||
node.func.attr in ['dump', 'load']):
|
||||
has_json_operations = True
|
||||
|
||||
if not has_json_operations:
|
||||
return None
|
||||
|
||||
if has_json_operations and not has_json_handler_import:
|
||||
if is_bypassed(file_path, 'json_structure', bypass_rules=bypass_rules):
|
||||
return None
|
||||
return {
|
||||
'name': 'json_handler usage',
|
||||
'passed': False,
|
||||
'message': 'Direct JSON operations detected (use json_handler for structured JSON management)'
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted JSON structure standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: json_structure_content.py
|
||||
# Description: JSON Structure Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_json_structure_standards() -> str:
|
||||
"""Return formatted JSON structure standards content with Rich markup
|
||||
|
||||
@@ -12,6 +12,15 @@ THE STANDARD:
|
||||
- Prax's own logging infrastructure is exempt (it IS the implementation)
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_handler_check.py
|
||||
# Description: Log Handler Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,6 +4,14 @@ Log Handler Standards Content
|
||||
Provides Rich-formatted reference text for the log handler rotation standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_handler_content.py
|
||||
# Description: Log Handler Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_log_handler_standards() -> str:
|
||||
"""Return Rich-formatted log handler standards text"""
|
||||
|
||||
@@ -12,6 +12,15 @@ THE STANDARD:
|
||||
- INFO = Normal operations, successful completions, discoveries
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_level_check.py
|
||||
# Description: Log Level Hygiene Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,6 +4,14 @@ Log Level Hygiene Standards Content
|
||||
Provides Rich-formatted reference text for the log level hygiene standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_level_content.py
|
||||
# Description: Log Level Hygiene Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_log_level_standards() -> str:
|
||||
"""Return Rich-formatted log level hygiene standards text"""
|
||||
|
||||
@@ -12,6 +12,15 @@ TWO CHECKS:
|
||||
Prax logging infrastructure and test files are exempt from both checks.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_visibility_check.py
|
||||
# Description: Log Visibility Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,6 +4,15 @@ Log Visibility Standards Content
|
||||
Provides Rich-formatted reference text for the log visibility standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_visibility_content.py
|
||||
# Description: Log Visibility Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
"""
|
||||
META Block Standards Checker Handler
|
||||
|
||||
Validates library-profile META blocks in Python files.
|
||||
Library META is lighter than Dev-Pass META - focuses on identity
|
||||
and traceability without branch-specific fields.
|
||||
|
||||
Required META format:
|
||||
# =================== META ====================
|
||||
# Name: filename.py
|
||||
# Description: Brief description of the file
|
||||
# Version: X.Y.Z
|
||||
# Created: YYYY-MM-DD
|
||||
# Modified: YYYY-MM-DD
|
||||
# =============================================
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: meta_check.py
|
||||
# Description: META Block Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
# Header/footer markers for library META
|
||||
META_HEADER = "# =================== META ===================="
|
||||
META_FOOTER = "# ============================================="
|
||||
|
||||
# Required fields with validation patterns
|
||||
REQUIRED_FIELDS = {
|
||||
"Name": r"# Name:\s+\S+\.py",
|
||||
"Description": r"# Description:\s+\S+",
|
||||
"Version": r"# Version:\s+\d+\.\d+\.\d+",
|
||||
"Created": r"# Created:\s+\d{4}-\d{2}-\d{2}",
|
||||
"Modified": r"# Modified:\s+\d{4}-\d{2}-\d{2}",
|
||||
}
|
||||
|
||||
|
||||
def is_bypassed(file_path: str, standard: str, bypass_rules: list | None = None) -> bool:
|
||||
"""Check if a violation should be bypassed"""
|
||||
if not bypass_rules:
|
||||
return False
|
||||
for rule in bypass_rules:
|
||||
if rule.get('standard') and rule.get('standard') != standard:
|
||||
continue
|
||||
rule_file = rule.get('file', '')
|
||||
if rule_file and rule_file not in file_path:
|
||||
continue
|
||||
rule_lines = rule.get('lines', [])
|
||||
if not rule_lines:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def check_module(module_path: str, bypass_rules: list | None = None) -> Dict:
|
||||
"""
|
||||
Check if module has a valid library-profile META block.
|
||||
|
||||
Args:
|
||||
module_path: Path to Python module to check
|
||||
bypass_rules: Optional bypass rules
|
||||
|
||||
Returns:
|
||||
dict with passed, checks, score, standard keys
|
||||
"""
|
||||
path = Path(module_path)
|
||||
|
||||
if is_bypassed(module_path, 'meta', bypass_rules=bypass_rules):
|
||||
return {
|
||||
'passed': True,
|
||||
'checks': [{'name': 'Bypassed', 'passed': True, 'message': 'Standard bypassed via .seed/bypass.json'}],
|
||||
'score': 100,
|
||||
'standard': 'META'
|
||||
}
|
||||
|
||||
if not path.exists():
|
||||
return {
|
||||
'passed': False,
|
||||
'checks': [{'name': 'File exists', 'passed': False, 'message': f'File not found: {module_path}'}],
|
||||
'score': 0,
|
||||
'standard': 'META'
|
||||
}
|
||||
|
||||
# Skip __init__.py files
|
||||
if path.name == '__init__.py':
|
||||
return {
|
||||
'passed': True,
|
||||
'checks': [{'name': 'META check', 'passed': True, 'message': '__init__.py file (skipped)'}],
|
||||
'score': 100,
|
||||
'standard': 'META'
|
||||
}
|
||||
|
||||
try:
|
||||
content = path.read_text(encoding='utf-8')
|
||||
except Exception as e:
|
||||
return {
|
||||
'passed': False,
|
||||
'checks': [{'name': 'File readable', 'passed': False, 'message': f'Error reading file: {e}'}],
|
||||
'score': 0,
|
||||
'standard': 'META'
|
||||
}
|
||||
|
||||
checks = []
|
||||
|
||||
# Check 1: META block presence
|
||||
presence = check_meta_presence(content)
|
||||
checks.append(presence)
|
||||
|
||||
# Check 2: Required fields (only if block exists)
|
||||
if presence['passed']:
|
||||
fields = check_required_fields(content, path.name)
|
||||
checks.extend(fields)
|
||||
|
||||
passed_checks = sum(1 for c in checks if c['passed'])
|
||||
total_checks = len(checks)
|
||||
score = int((passed_checks / total_checks * 100)) if total_checks > 0 else 0
|
||||
overall_passed = score >= 75
|
||||
|
||||
return {
|
||||
'passed': overall_passed,
|
||||
'checks': checks,
|
||||
'score': score,
|
||||
'standard': 'META'
|
||||
}
|
||||
|
||||
|
||||
def check_meta_presence(content: str) -> Dict:
|
||||
"""Check that META block header and footer markers exist"""
|
||||
has_header = META_HEADER in content
|
||||
has_footer = META_FOOTER in content
|
||||
|
||||
if has_header and has_footer:
|
||||
return {
|
||||
'name': 'META block present',
|
||||
'passed': True,
|
||||
'message': 'META block with header and footer markers found'
|
||||
}
|
||||
|
||||
missing = []
|
||||
if not has_header:
|
||||
missing.append('header')
|
||||
if not has_footer:
|
||||
missing.append('footer')
|
||||
|
||||
return {
|
||||
'name': 'META block present',
|
||||
'passed': False,
|
||||
'message': f'Missing META block ({", ".join(missing)} marker not found)'
|
||||
}
|
||||
|
||||
|
||||
def check_required_fields(content: str, filename: str) -> List[Dict]:
|
||||
"""Check all required fields are present and valid"""
|
||||
results = []
|
||||
|
||||
for field_name, pattern in REQUIRED_FIELDS.items():
|
||||
match = re.search(pattern, content)
|
||||
|
||||
if field_name == "Name" and match:
|
||||
# Extra validation: Name field should reference the actual filename
|
||||
name_match = re.search(r"# Name:\s+(\S+\.py)", content)
|
||||
if name_match and name_match.group(1) != filename:
|
||||
results.append({
|
||||
'name': f'META {field_name}',
|
||||
'passed': False,
|
||||
'message': f'Name field says "{name_match.group(1)}" but file is "{filename}"'
|
||||
})
|
||||
continue
|
||||
|
||||
if match:
|
||||
results.append({
|
||||
'name': f'META {field_name}',
|
||||
'passed': True,
|
||||
'message': f'{field_name} field present and valid'
|
||||
})
|
||||
else:
|
||||
results.append({
|
||||
'name': f'META {field_name}',
|
||||
'passed': False,
|
||||
'message': f'Missing or invalid {field_name} field'
|
||||
})
|
||||
|
||||
return results
|
||||
@@ -5,6 +5,15 @@ Validates module compliance with AIPass module standards.
|
||||
Checks handle_command pattern, thin orchestration, file size guidelines.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: modules_check.py
|
||||
# Description: Modules Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
import ast
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted module standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: modules_content.py
|
||||
# Description: Modules Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_modules_standards() -> str:
|
||||
"""Return formatted module standards content with Rich markup
|
||||
|
||||
@@ -5,6 +5,15 @@ Validates module compliance with AIPass naming standards.
|
||||
Checks file naming, function naming, variable naming, constant naming.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: naming_check.py
|
||||
# Description: Naming Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,14 @@ Provides formatted naming standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: naming_content.py
|
||||
# Description: Naming Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_naming_standards() -> str:
|
||||
"""Return formatted naming standards content with Rich markup
|
||||
|
||||
@@ -13,6 +13,15 @@ THE STANDARD:
|
||||
- Documentation files that mention these flags for reference are exempt
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: permission_flags_check.py
|
||||
# Description: Permission Flags Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,6 +4,14 @@ Permission Flags Standards Content
|
||||
Provides Rich-formatted reference text for the permission flags standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: permission_flags_content.py
|
||||
# Description: Permission Flags Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
def get_permission_flags_standards() -> str:
|
||||
"""Return Rich-formatted permission flags standards text"""
|
||||
|
||||
@@ -12,6 +12,15 @@ Checks:
|
||||
6. Command list presence (commands/usage section is not empty)
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: readme_check.py
|
||||
# Description: README Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
@@ -4,6 +4,15 @@ README Standards Content
|
||||
Provides Rich-formatted reference text for the README standard.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: readme_content.py
|
||||
# Description: README Standards Content
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -13,6 +13,15 @@ Sections generated:
|
||||
- Last Updated timestamp
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: readme_generator.py
|
||||
# Description: README Section Auto-Generator
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
||||
@@ -6,6 +6,15 @@ generator loading, and target resolution. Returns data structures for the
|
||||
module to display.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: readme_ops.py
|
||||
# Description: README Update Operations Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
import importlib.util
|
||||
|
||||
@@ -5,6 +5,15 @@ Scans Cortex template directory and generates baseline structure.
|
||||
Respects .registry_ignore.json patterns.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: template_scanner.py
|
||||
# Description: Template Scanner - Automatically scan template to discover structure
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -6,6 +6,15 @@ Checks for test functions, error handling patterns.
|
||||
Note: Manual testing is acceptable in current rapid iteration phase.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: testing_check.py
|
||||
# Description: Testing Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@@ -15,6 +15,15 @@ Valid bypass categories for .seed/bypass.json:
|
||||
- utility: Helper called by event-firing function
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: trigger_check.py
|
||||
# Description: Trigger Standards Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides formatted Trigger event bus standards content.
|
||||
Module orchestrates, handler implements.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: trigger_content.py
|
||||
# Description: Trigger Standards Content Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@@ -5,6 +5,15 @@ Verifies that checker implementations match their documentation.
|
||||
Catches drift between trigger_check.py patterns and trigger_content.py docs.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: checker_sync.py
|
||||
# Description: Checker Documentation Sync Check
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,15 @@ Checks if new commands/flags are documented everywhere they should be.
|
||||
Validates documentation completeness for command flags.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: command_check.py
|
||||
# Description: Command Consistency Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
@@ -5,6 +5,15 @@ Checks if documentation is up-to-date with recent code changes.
|
||||
Validates modification times of key files.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: freshness_check.py
|
||||
# Description: File Freshness Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict
|
||||
|
||||
@@ -5,6 +5,15 @@ Checks that seed.py help text doesn't mention removed flags.
|
||||
Validates help documentation accuracy.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: help_check.py
|
||||
# Description: Help Consistency Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
@@ -5,6 +5,15 @@ Runs all verification checks and formats display output.
|
||||
Called by standards_verify module.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: orchestrator.py
|
||||
# Description: Verification Orchestrator Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
@@ -5,6 +5,15 @@ Checks for deprecated patterns in the seed codebase.
|
||||
Returns violations found during grep search.
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: stale_check.py
|
||||
# Description: Stale Patterns Checker Handler
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed architecture standards for AIPass branches.
|
||||
Run directly or via: drone @seed architecture
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: architecture_standard.py
|
||||
# Description: Architecture Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed CLI flags standards for AIPass branches.
|
||||
Run directly or via: drone @seed cli_flags
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_flags_standard.py
|
||||
# Description: CLI Flags Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed CLI standards for AIPass branches.
|
||||
Run directly or via: drone @seed cli
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: cli_standard.py
|
||||
# Description: CLI Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -9,6 +9,15 @@ Usage:
|
||||
drone @seed diagnostics flow # Specific branch
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: diagnostics_audit.py
|
||||
# Description: System-wide Type Error Diagnostics
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed documentation standards for AIPass branches.
|
||||
Run directly or via: drone @seed documentation
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: documentation_standard.py
|
||||
# Description: Documentation Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed error handling standards for AIPass branches.
|
||||
Run directly or via: drone @seed error_handling
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: error_handling_standard.py
|
||||
# Description: Error Handling Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed handler standards for AIPass branches.
|
||||
Run directly or via: drone @seed handlers
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: handlers_standard.py
|
||||
# Description: Handlers Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed import standards for AIPass branches.
|
||||
Run directly or via: drone @seed imports
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: imports_standard.py
|
||||
# Description: Import Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed JSON structure standards for AIPass branches.
|
||||
Run directly or via: drone @seed json
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: json_structure_standard.py
|
||||
# Description: JSON Structure Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed log handler rotation standards for AIPass branches.
|
||||
Run directly or via: drone @seed log_handler
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_handler_standard.py
|
||||
# Description: Log Handler Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed log level hygiene standards for AIPass branches.
|
||||
Run directly or via: drone @seed log_level
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_level_standard.py
|
||||
# Description: Log Level Hygiene Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed log visibility standards for AIPass branches.
|
||||
Run directly or via: drone @seed log_visibility
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: log_visibility_standard.py
|
||||
# Description: Log Visibility Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed module standards for AIPass branches.
|
||||
Run directly or via: drone @seed modules
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: modules_standard.py
|
||||
# Description: Modules Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed naming standards for AIPass branches.
|
||||
Run directly or via: drone @seed naming
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: naming_standard.py
|
||||
# Description: Naming Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed permission flags standards for AIPass branches.
|
||||
Run directly or via: drone @seed permission_flags
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: permission_flags_standard.py
|
||||
# Description: Permission Flags Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -8,6 +8,15 @@ Uses readme_generator handler to produce content for sections marked with
|
||||
Run: python3 seed.py readme update @branch
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: readme_update.py
|
||||
# Description: README Auto-Update Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -7,6 +7,15 @@ Shows per-branch scores, system-wide metrics, and top issues.
|
||||
Run: python3 seed.py audit
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: standards_audit.py
|
||||
# Description: Standards Audit Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -5,6 +5,15 @@ Validates modules against AIPass code standards.
|
||||
Run directly or via: drone @seed checklist
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: standards_checklist.py
|
||||
# Description: Standards Checklist Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,6 +5,15 @@ Provides condensed trigger event bus standards for AIPass branches.
|
||||
Run directly or via: drone @seed trigger
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: trigger_standard.py
|
||||
# Description: Trigger Standards Module
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"description": "AIPass framework standards for multi-agent Python projects",
|
||||
"author": "AIPass",
|
||||
"file_types": ["*.py"],
|
||||
"standards_count": 19,
|
||||
"standards_count": 20,
|
||||
"standards": [
|
||||
"architecture",
|
||||
"cli",
|
||||
@@ -19,6 +19,7 @@
|
||||
"log_handler",
|
||||
"log_level",
|
||||
"log_visibility",
|
||||
"meta",
|
||||
"modules",
|
||||
"naming",
|
||||
"permission_flags",
|
||||
|
||||
@@ -7,6 +7,15 @@ Auto-discovery architecture:
|
||||
- No manual imports or routing needed
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: pack_entry.py
|
||||
# Description: AIPass Standards Pack - Entry Point
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import importlib.util
|
||||
from pathlib import Path
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
# =============================================
|
||||
|
||||
"""Shared pytest fixtures for cortex tests"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: conftest.py
|
||||
# Description: Shared pytest fixtures for cortex tests
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
import pytest
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
@@ -24,6 +24,15 @@ Compares template directory with created branch to identify:
|
||||
- Renamed files
|
||||
"""
|
||||
|
||||
# =================== META ====================
|
||||
# Name: verify_branch.py
|
||||
# Description: Branch Template Verification Tool
|
||||
# Version: 1.0.0
|
||||
# Created: 2026-03-05
|
||||
# Modified: 2026-03-05
|
||||
# =============================================
|
||||
|
||||
|
||||
import sys
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
Reference in New Issue
Block a user