код написан

This commit is contained in:
2026-03-10 12:00:18 +03:00
parent a127aa07df
commit 0078c1ae05
57 changed files with 53951 additions and 4909 deletions

View File

@@ -97,25 +97,28 @@ 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"],
"Component": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "INVARIANT", "UX_STATE", "UX_FEEDBACK", "UX_RECOVERY", "UX_REATIVITY"],
"Function": ["PURPOSE", "PRE", "POST", "TEST_CONTRACT", "TEST_FIXTURE", "TEST_EDGE", "TEST_INVARIANT"],
"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"]
"Store": ["PURPOSE", "TIER", "INVARIANT"],
"Block": ["PURPOSE", "TIER"]
},
Tier.STANDARD: {
"Module": ["PURPOSE", "LAYER", "SEMANTICS", "TIER"],
"Component": ["PURPOSE", "LAYER", "SEMANTICS", "TIER", "UX_STATE"],
"Function": ["PURPOSE", "PRE", "POST"],
"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"]
"Store": ["PURPOSE", "TIER"],
"Block": ["PURPOSE"]
},
Tier.TRIVIAL: {
"Module": ["PURPOSE"],
"Component": ["PURPOSE"],
"Function": ["PURPOSE"],
"Class": ["PURPOSE"],
"Store": ["PURPOSE"]
"Store": ["PURPOSE"],
"Block": ["PURPOSE"]
}
}
@@ -178,6 +181,9 @@ class SemanticEntity:
self.props: List[Dict[str, Any]] = []
self.events: List[str] = []
self.data_flow: List[Dict[str, str]] = []
self.has_export_let: bool = False
self.has_reactive_label: bool = False
self.has_runes: bool = False
# [/DEF:__init__:Function]
# [DEF:get_tier:Function]
@@ -274,10 +280,13 @@ class SemanticEntity:
required = TIER_MANDATORY_TAGS.get(tier, {}).get(self.type, [])
for req_tag in required:
found = False
for existing_tag in self.tags:
if existing_tag.upper() == req_tag:
found = True
break
if req_tag == "RELATION" and len(self.relations) > 0:
found = True
else:
for existing_tag in self.tags:
if existing_tag.upper() == req_tag:
found = True
break
if not found:
severity = Severity.ERROR if tier == Tier.CRITICAL else Severity.WARNING
self.compliance_issues.append(ComplianceIssue(
@@ -323,6 +332,34 @@ class SemanticEntity:
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
if self.has_export_let:
self.compliance_issues.append(ComplianceIssue(
"Svelte protocol violation: `export let` is forbidden; use `$props()`",
strict_severity,
self.start_line
))
if self.has_reactive_label:
self.compliance_issues.append(ComplianceIssue(
"Svelte protocol violation: `$:` reactive label is forbidden; use runes `$state/$derived/$effect`",
strict_severity,
self.start_line
))
# 7. Validate module length limit
if self.type == "Module" and self.end_line is not None:
module_length = self.end_line - self.start_line + 1
if module_length >= 300:
self.compliance_issues.append(ComplianceIssue(
f"Fractal limit warning: Module length is {module_length} lines (must be < 300)",
Severity.WARNING,
self.start_line
))
# Recursive validation
for child in self.children:
child.validate()
@@ -358,10 +395,15 @@ class SemanticEntity:
if required:
found_count = 0
for req_tag in required:
for existing_tag in self.tags:
if existing_tag.upper() == req_tag:
found_count += 1
break
found = False
if req_tag == "RELATION" and len(self.relations) > 0:
found = True
else:
for existing_tag in self.tags:
if existing_tag.upper() == req_tag:
found_count += 1
found = True
break
if found_count < len(required):
missing_ratio = 1 - (found_count / len(required))
score -= 0.3 * missing_ratio
@@ -381,27 +423,29 @@ def get_patterns(lang: str) -> Dict[str, Pattern]:
with belief_scope("get_patterns"):
if lang == "python":
return {
"anchor_start": re.compile(r"#\s*\[DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]"),
"anchor_end": re.compile(r"#\s*\[/DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]"),
"anchor_start": re.compile(r"#\s*\[DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]"),
"anchor_end": re.compile(r"#\s*\[/DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]"),
"tag": re.compile(r"#\s*@(?P<tag>[A-Z_]+):\s*(?P<value>.*)"),
"relation": re.compile(r"#\s*@RELATION:\s*(?P<type>\w+)\s*->\s*(?P<target>.*)"),
"relation": re.compile(r"#\s*@RELATION:\s*\[?(?P<type>\w+)\]?\s*->\s*\[?(?P<target>[^\]]+)\]?"),
"func_def": re.compile(r"^\s*(async\s+)?def\s+(?P<name>\w+)"),
"belief_scope": re.compile(r"with\s+(\w+\.)?belief_scope\(|@believed\("),
"molecular_log": re.compile(r"logger\.(explore|reason|reflect)\("),
}
else:
return {
"html_anchor_start": re.compile(r"<!--\s*\[DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]\s*-->"),
"html_anchor_end": re.compile(r"<!--\s*\[/DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]\s*-->"),
"js_anchor_start": re.compile(r"//\s*\[DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]"),
"js_anchor_end": re.compile(r"//\s*\[/DEF:(?P<name>[\w\.]+):(?P<type>\w+)\]"),
"html_anchor_start": re.compile(r"<!--\s*\[DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]\s*-->"),
"html_anchor_end": re.compile(r"<!--\s*\[/DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]\s*-->"),
"js_anchor_start": re.compile(r"//\s*\[DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]"),
"js_anchor_end": re.compile(r"//\s*\[/DEF:(?P<name>[-\w\.]+):(?P<type>\w+)\]"),
"html_tag": re.compile(r"@(?P<tag>[A-Z_]+):\s*(?P<value>.*)"),
"jsdoc_tag": re.compile(r"\*\s*@(?P<tag>[A-Za-z_]+)\s*:?\s*(?P<value>.*)"),
"relation": re.compile(r"//\s*@RELATION:\s*(?P<type>\w+)\s*->\s*(?P<target>.*)"),
"relation": re.compile(r"//\s*@RELATION:\s*\[?(?P<type>\w+)\]?\s*->\s*\[?(?P<target>[^\]]+)\]?"),
"func_def": re.compile(r"^\s*(export\s+)?(async\s+)?function\s+(?P<name>\w+)"),
"console_log": re.compile(r"console\.log\s*\(\s*['\"`]\[[\w_]+\]\[[A-Za-z0-9_:]+\]"),
"console_log": re.compile(r"console\.(info|warn|debug)\s*\(\s*['\"`]\[[\w\.-]+\]\[(EXPLORE|REASON|REFLECT|[A-Za-z0-9_:]+)\]"),
# Svelte-specific patterns
"export_let": re.compile(r"export\s+let\s+(?P<name>\w+)(?:\s*:\s*(?P<type>[\w\[\]|<>]+))?(?:\s*=\s*(?P<default>[^;]+))?"),
"reactive_label": re.compile(r"^\s*\$:\s*"),
"runes_usage": re.compile(r"\$(state|derived|effect|props)\s*\("),
"create_event_dispatcher": re.compile(r"createEventDispatcher\s*<\s*\{\s*(?P<events>[^}]+)\s*\}\s*\>"),
"dispatch_call": re.compile(r"dispatch\s*\(\s*['\"](?P<event>\w+)['\"]"),
"store_subscription": re.compile(r"\$(?P<store>\w+)"),
@@ -667,10 +711,16 @@ def parse_file(full_path: str, rel_path: str, lang: str) -> Tuple[List[SemanticE
elif "molecular_log" in patterns and patterns["molecular_log"].search(line):
current.has_belief_scope = True
# Check for console.log belief state in Svelte
if lang == "svelte_js" and "console_log" in patterns:
if patterns["console_log"].search(line):
# Check for console logging + forbidden/required Svelte reactivity signals
if lang == "svelte_js":
if "console_log" in patterns and patterns["console_log"].search(line):
current.has_console_log = True
if "export_let" in patterns and patterns["export_let"].search(line):
current.has_export_let = True
if "reactive_label" in patterns and patterns["reactive_label"].search(line):
current.has_reactive_label = True
if "runes_usage" in patterns and patterns["runes_usage"].search(line):
current.has_runes = True
# End of file check
if stack:
@@ -1036,6 +1086,7 @@ class SemanticMapGenerator:
elif entity.type == "Function": icon = "ƒ"
elif entity.type == "Class": icon = ""
elif entity.type == "Store": icon = "🗄️"
elif entity.type == "Block": icon = ""
tier_badge = ""
tier = entity.get_tier()