refactor(semantics): migrate TIER system to adaptive COMPLEXITY 1-5 scale

- Replaced rigid TIERs with continuous COMPLEXITY 1-5 scale in semantics.md
- Updated generate_semantic_map.py to parse and score based on Complexity
- Added backward compatibility mapping for legacy TIERs
- Migrated all .ai/shots examples to use @COMPLEXITY and updated relation syntax
- Added trivial_utility.py shot to demonstrate implicit Complexity 1 token savings
This commit is contained in:
2026-03-16 09:54:13 +03:00
parent 54e90b589b
commit 321e0eb2db
7 changed files with 236 additions and 124 deletions

View File

@@ -19,7 +19,7 @@ import json
import datetime
import fnmatch
import argparse
from enum import Enum
from enum import Enum, IntEnum
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Any, Pattern, Tuple, Set
@@ -59,13 +59,24 @@ class belief_scope:
class Tier(Enum):
# [DEF:Tier:Class]
# @TIER: TRIVIAL
# @PURPOSE: Enumeration of semantic tiers defining validation strictness.
# @PURPOSE: Legacy tier buckets retained for backward-compatible reporting.
CRITICAL = "CRITICAL"
STANDARD = "STANDARD"
TRIVIAL = "TRIVIAL"
# [/DEF:Tier:Class]
class Complexity(IntEnum):
# [DEF:Complexity:Class]
# @PURPOSE: Adaptive semantic complexity scale used for validation strictness.
ONE = 1
TWO = 2
THREE = 3
FOUR = 4
FIVE = 5
# [/DEF:Complexity:Class]
class Severity(Enum):
# [DEF:Severity:Class]
# @TIER: TRIVIAL
@@ -95,31 +106,53 @@ OUTPUT_COMPRESSED_MD = ".ai/PROJECT_MAP.md"
OUTPUT_MODULE_MAP_MD = ".ai/MODULE_MAP.md"
REPORTS_DIR = "semantics/reports"
# Tier-based mandatory tags aligned with .ai/standards/semantics.md
TIER_MANDATORY_TAGS = {
Tier.CRITICAL: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "INVARIANT", "RELATION"],
"Component": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "INVARIANT", "RELATION", "UX_STATE", "UX_FEEDBACK", "UX_RECOVERY", "UX_REACTIVITY"],
"Function": ["PURPOSE", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT", "TEST_CONTRACT", "TEST_SCENARIO", "TEST_FIXTURE", "TEST_EDGE", "TEST_INVARIANT"],
"Class": ["PURPOSE", "TIER", "INVARIANT"],
"Store": ["PURPOSE", "TIER", "INVARIANT"],
"Block": ["PURPOSE", "TIER"]
# Complexity-based mandatory tags aligned with .ai/standards/semantics.md
LEGACY_TIER_TO_COMPLEXITY = {
"TRIVIAL": Complexity.ONE,
"STANDARD": Complexity.THREE,
"CRITICAL": Complexity.FIVE,
}
COMPLEXITY_MANDATORY_TAGS = {
Complexity.ONE: {
"Module": [],
"Component": [],
"Function": [],
"Class": [],
"Store": [],
"Block": []
},
Tier.STANDARD: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "RELATION"],
"Component": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "RELATION", "UX_STATE", "UX_REACTIVITY"],
"Function": ["PURPOSE", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT"],
"Class": ["PURPOSE", "TIER"],
"Store": ["PURPOSE", "TIER"],
"Block": ["PURPOSE"]
},
Tier.TRIVIAL: {
Complexity.TWO: {
"Module": ["PURPOSE"],
"Component": ["PURPOSE"],
"Function": ["PURPOSE"],
"Class": ["PURPOSE"],
"Store": ["PURPOSE"],
"Block": ["PURPOSE"]
},
Complexity.THREE: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "RELATION"],
"Component": ["PURPOSE", "RELATION", "UX_STATE"],
"Function": ["PURPOSE", "RELATION"],
"Class": ["PURPOSE", "RELATION"],
"Store": ["PURPOSE", "RELATION"],
"Block": ["PURPOSE"]
},
Complexity.FOUR: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "RELATION", "PRE", "POST", "SIDE_EFFECT"],
"Component": ["PURPOSE", "RELATION", "UX_STATE", "UX_REACTIVITY", "SIDE_EFFECT"],
"Function": ["PURPOSE", "RELATION", "PRE", "POST", "SIDE_EFFECT"],
"Class": ["PURPOSE", "RELATION", "PRE", "POST", "SIDE_EFFECT"],
"Store": ["PURPOSE", "RELATION", "PRE", "POST", "SIDE_EFFECT"],
"Block": ["PURPOSE", "SIDE_EFFECT"]
},
Complexity.FIVE: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "RELATION", "INVARIANT", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT"],
"Component": ["PURPOSE", "RELATION", "INVARIANT", "UX_STATE", "UX_FEEDBACK", "UX_RECOVERY", "UX_REACTIVITY", "SIDE_EFFECT", "DATA_CONTRACT"],
"Function": ["PURPOSE", "RELATION", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT"],
"Class": ["PURPOSE", "RELATION", "INVARIANT", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT"],
"Store": ["PURPOSE", "RELATION", "INVARIANT", "PRE", "POST", "SIDE_EFFECT", "DATA_CONTRACT"],
"Block": ["PURPOSE", "SIDE_EFFECT"]
}
}
@@ -127,11 +160,13 @@ ALLOWED_RELATION_PREDICATES = {
"DEPENDS_ON", "CALLS", "INHERITS", "IMPLEMENTS", "DISPATCHES", "BINDS_TO"
}
# Tier-based belief state requirements
TIER_BELIEF_REQUIRED = {
Tier.CRITICAL: True,
Tier.STANDARD: True,
Tier.TRIVIAL: False
# Complexity-based belief state requirements
COMPLEXITY_BELIEF_REQUIRED = {
Complexity.ONE: False,
Complexity.TWO: False,
Complexity.THREE: False,
Complexity.FOUR: True,
Complexity.FIVE: True,
}
# [/SECTION]
@@ -157,7 +192,7 @@ class ComplianceIssue:
# [DEF:SemanticEntity:Class]
# @TIER: CRITICAL
# @PURPOSE: Represents a code entity (Module, Function, Component) found during parsing.
# @INVARIANT: start_line is always set; end_line is set upon closure; tier defaults to STANDARD.
# @INVARIANT: start_line is always set; end_line is set upon closure; complexity defaults to 1 unless explicitly raised.
class SemanticEntity:
# [DEF:__init__:Function]
# @TIER: STANDARD
@@ -187,18 +222,26 @@ class SemanticEntity:
self.has_runes: bool = False
# [/DEF:__init__:Function]
# [DEF:get_tier:Function]
# @TIER: STANDARD
# @PURPOSE: Returns the tier of the entity, defaulting to STANDARD.
# @PRE: tags dictionary is accessible.
# @POST: Returns Tier enum value.
def get_tier(self) -> Tier:
with belief_scope("get_tier"):
tier_str = self.tags.get("TIER", "STANDARD").upper()
try:
base_tier = Tier(tier_str)
except ValueError:
base_tier = Tier.STANDARD
# [DEF:has_explicit_complexity:Function]
# @PURPOSE: Returns whether the entity explicitly declares complexity metadata.
def has_explicit_complexity(self) -> bool:
return any(tag.upper() in {"COMPLEXITY", "C", "TIER"} for tag in self.tags)
# [DEF:get_complexity:Function]
# @PURPOSE: Returns effective complexity with backward compatibility for legacy tiers.
# @PRE: tags dictionary is accessible.
# @POST: Returns Complexity enum value.
def get_complexity(self) -> Complexity:
with belief_scope("get_complexity"):
complexity_value = self.tags.get("COMPLEXITY") or self.tags.get("C")
if complexity_value is not None:
try:
base_complexity = Complexity(int(str(complexity_value).strip()))
except (ValueError, TypeError):
base_complexity = Complexity.ONE
else:
legacy_tier = str(self.tags.get("TIER", "")).upper().strip()
base_complexity = LEGACY_TIER_TO_COMPLEXITY.get(legacy_tier, Complexity.ONE)
file_path_lower = self.file_path.lower()
is_test_entity = (
@@ -207,36 +250,44 @@ class SemanticEntity:
or self.name.startswith("test_")
)
# 1. Tests should never be higher than STANDARD
if is_test_entity and base_tier == Tier.CRITICAL:
return Tier.STANDARD
if is_test_entity and base_complexity > Complexity.THREE:
base_complexity = Complexity.THREE
# 2. Non-route Svelte entities should not be escalated beyond STANDARD by path heuristics.
if self.file_path.endswith(".svelte"):
is_route_level_svelte = any(
marker in self.name for marker in ["+page", "+layout", "Page", "Layout"]
)
if not is_route_level_svelte and base_tier == Tier.CRITICAL:
return Tier.STANDARD
if not is_route_level_svelte and base_complexity > Complexity.THREE:
base_complexity = Complexity.THREE
# 3. Tooling scripts should not be escalated beyond STANDARD.
if ("scripts/" in self.file_path or "_tui.py" in self.file_path) and base_tier == Tier.CRITICAL:
return Tier.STANDARD
if ("scripts/" in self.file_path or "_tui.py" in self.file_path) and base_complexity > Complexity.THREE:
base_complexity = Complexity.THREE
# 4. Promote only module-like entities in critical domains by path heuristic.
# This prevents path segments like "migration" from forcing every nested
# Block/Function/Component in a route file into CRITICAL validation.
critical_keywords = ["auth", "security", "jwt", "database", "migration", "config", "session"]
module_like_types = {"Module", "Class", "Store"}
if (
self.type in module_like_types
not self.has_explicit_complexity()
and self.type in module_like_types
and any(keyword in file_path_lower for keyword in critical_keywords)
and not is_test_entity
and base_tier != Tier.TRIVIAL
):
return Tier.CRITICAL
return Complexity.FIVE
return base_tier
return base_complexity
# [DEF:get_tier:Function]
# @TIER: STANDARD
# @PURPOSE: Returns legacy tier bucket derived from effective complexity.
# @PRE: tags dictionary is accessible.
# @POST: Returns Tier enum value.
def get_tier(self) -> Tier:
with belief_scope("get_tier"):
complexity = self.get_complexity()
if complexity >= Complexity.FIVE:
return Tier.CRITICAL
if complexity >= Complexity.THREE:
return Tier.STANDARD
return Tier.TRIVIAL
# [/DEF:get_tier:Function]
# [DEF:to_dict:Function]
@@ -249,6 +300,7 @@ class SemanticEntity:
result = {
"name": self.name,
"type": self.type,
"complexity": int(self.get_complexity()),
"tier": self.get_tier().value,
"start_line": self.start_line,
"end_line": self.end_line,
@@ -272,15 +324,16 @@ class SemanticEntity:
# [DEF:validate:Function]
# @TIER: CRITICAL
# @PURPOSE: Checks for semantic compliance based on TIER requirements.
# @PRE: Entity structure is complete; tier is determined.
# @PURPOSE: Checks for semantic compliance based on complexity requirements.
# @PRE: Entity structure is complete; complexity is determined.
# @POST: Populates self.compliance_issues with severity levels.
# @SIDE_EFFECT: Modifies self.compliance_issues list.
def validate(self):
with belief_scope("validate"):
complexity = self.get_complexity()
tier = self.get_tier()
# 1. Check Closure (required for ALL tiers)
# 1. Check Closure (required for ALL complexity levels)
if self.end_line is None:
self.compliance_issues.append(ComplianceIssue(
f"Unclosed Anchor: [DEF:{self.name}:{self.type}] started at line {self.start_line}",
@@ -288,8 +341,8 @@ class SemanticEntity:
self.start_line
))
# 2. Check Mandatory Tags based on TIER
required = TIER_MANDATORY_TAGS.get(tier, {}).get(self.type, [])
# 2. Check Mandatory Tags based on complexity
required = COMPLEXITY_MANDATORY_TAGS.get(complexity, {}).get(self.type, [])
for req_tag in required:
found = False
if req_tag == "RELATION" and len(self.relations) > 0:
@@ -300,9 +353,9 @@ class SemanticEntity:
found = True
break
if not found:
severity = Severity.ERROR if tier == Tier.CRITICAL else Severity.WARNING
severity = Severity.ERROR if complexity >= Complexity.FOUR else Severity.WARNING
self.compliance_issues.append(ComplianceIssue(
f"Missing Mandatory Tag: @{req_tag} (required for {tier.value} tier)",
f"Missing Mandatory Tag: @{req_tag} (required for complexity {int(complexity)})",
severity,
self.start_line
))
@@ -313,40 +366,39 @@ class SemanticEntity:
if rel_type and rel_type not in ALLOWED_RELATION_PREDICATES:
self.compliance_issues.append(ComplianceIssue(
f"Invalid @RELATION predicate: {rel_type}. Allowed: {', '.join(sorted(ALLOWED_RELATION_PREDICATES))}",
Severity.ERROR if tier == Tier.CRITICAL else Severity.WARNING,
Severity.ERROR if complexity >= Complexity.FOUR else Severity.WARNING,
self.start_line
))
# 4. Check for Belief State Logging based on TIER
# 4. Check for Belief State Logging based on complexity
if self.type == "Function":
belief_required = TIER_BELIEF_REQUIRED.get(tier, False)
belief_required = COMPLEXITY_BELIEF_REQUIRED.get(complexity, False)
if belief_required:
is_python = self.file_path.endswith(".py")
has_belief = self.has_belief_scope if is_python else self.has_console_log
if not has_belief:
# Check if it's a special case (logger.py or mock functions)
if "logger.py" not in self.file_path and "__" not in self.name:
severity = Severity.ERROR if tier == Tier.CRITICAL else Severity.WARNING
severity = Severity.ERROR if complexity >= Complexity.FOUR else Severity.WARNING
log_type = "belief_scope / molecular methods" if is_python else "console.log with [ID][STATE]"
self.compliance_issues.append(ComplianceIssue(
f"Missing Belief State Logging: Function should use {log_type} (required for {tier.value} tier)",
f"Missing Belief State Logging: Function should use {log_type} (required for complexity {int(complexity)})",
severity,
self.start_line
))
# 5. Check for @INVARIANT in CRITICAL tier
if tier == Tier.CRITICAL and self.type in ["Module", "Component", "Class"]:
# 5. Check for @INVARIANT in maximum complexity
if complexity == Complexity.FIVE and self.type in ["Module", "Component", "Class"]:
if "INVARIANT" not in [k.upper() for k in self.tags.keys()]:
self.compliance_issues.append(ComplianceIssue(
f"Missing @INVARIANT tag (required for CRITICAL tier)",
"Missing @INVARIANT tag (required for complexity 5)",
Severity.ERROR,
self.start_line
))
# 6. Validate modern Svelte reactivity protocol
if self.type == "Component" and self.file_path.endswith(".svelte"):
strict_severity = Severity.ERROR if tier == Tier.CRITICAL else Severity.WARNING
strict_severity = Severity.ERROR if complexity >= Complexity.FOUR else Severity.WARNING
if self.has_export_let:
self.compliance_issues.append(ComplianceIssue(
@@ -379,7 +431,7 @@ class SemanticEntity:
# [DEF:get_score:Function]
# @TIER: STANDARD
# @PURPOSE: Calculates a compliance score (0.0 to 1.0) based on tier requirements.
# @PURPOSE: Calculates a compliance score (0.0 to 1.0) based on complexity requirements.
# @PRE: validate() has been called.
# @POST: Returns a float score.
def get_score(self) -> float:
@@ -387,11 +439,11 @@ class SemanticEntity:
if self.end_line is None:
return 0.0
tier = self.get_tier()
complexity = self.get_complexity()
score = 1.0
# Dynamic penalties based on Tier
error_penalty = 0.5 if tier == Tier.CRITICAL else 0.3
# Dynamic penalties based on complexity
error_penalty = 0.5 if complexity >= Complexity.FOUR else 0.3
warning_penalty = 0.15
# Count issues by severity
@@ -403,7 +455,7 @@ class SemanticEntity:
score -= warnings * warning_penalty
# Check mandatory tags
required = TIER_MANDATORY_TAGS.get(tier, {}).get(self.type, [])
required = COMPLEXITY_MANDATORY_TAGS.get(complexity, {}).get(self.type, [])
if required:
found_count = 0
for req_tag in required:
@@ -687,7 +739,7 @@ def parse_file(full_path: str, rel_path: str, lang: str) -> Tuple[List[SemanticE
# Create orphan function entity
orphan = SemanticEntity(func_name, "Function", lineno, rel_path)
orphan.tags["PURPOSE"] = f"Auto-detected function (orphan)"
orphan.tags["TIER"] = "TRIVIAL"
orphan.tags["COMPLEXITY"] = "1"
orphan.end_line = lineno # Mark as closed immediately
orphan_functions.append(orphan)
@@ -770,7 +822,7 @@ def parse_file(full_path: str, rel_path: str, lang: str) -> Tuple[List[SemanticE
rel_path
)
synthetic_module.tags["PURPOSE"] = f"Auto-generated module for {rel_path}"
synthetic_module.tags["TIER"] = "TRIVIAL"
synthetic_module.tags["COMPLEXITY"] = "1"
synthetic_module.tags["LAYER"] = "Unknown"
synthetic_module.end_line = len(lines)