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

@@ -1,10 +1,9 @@
#[DEF:BackendRouteShot:Module] #[DEF:BackendRouteShot:Module]
# @TIER: STANDARD # @COMPLEXITY: 3
# @SEMANTICS: Route, Task, API, Async # @SEMANTICS: Route, Task, API, Async
# @PURPOSE: Reference implementation of a task-based route using GRACE-Poly. # @PURPOSE: Reference implementation of a task-based route using GRACE-Poly.
# @LAYER: Interface (API) # @LAYER: Interface (API)
# @RELATION: IMPLEMENTS -> [DEF:Std:API_FastAPI] # @RELATION: [IMPLEMENTS] ->[API_FastAPI]
# @INVARIANT: TaskManager must be available in dependency graph.
from typing import Dict, Any from typing import Dict, Any
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
@@ -25,15 +24,13 @@ class CreateTaskRequest(BaseModel):
# [/DEF:CreateTaskRequest:Class] # [/DEF:CreateTaskRequest:Class]
# [DEF:create_task:Function] # [DEF:create_task:Function]
# @COMPLEXITY: 4
# @PURPOSE: Create and start a new task using TaskManager. Non-blocking. # @PURPOSE: Create and start a new task using TaskManager. Non-blocking.
# @DATA_CONTRACT: Input -> CreateTaskRequest, Output -> Task # @RELATION: [CALLS] ->[task_manager.create_task]
# @PRE: plugin_id must match a registered plugin. # @PRE: plugin_id must match a registered plugin.
# @POST: A new task is spawned; Task object returned immediately. # @POST: A new task is spawned; Task object returned immediately.
# @SIDE_EFFECT: Writes to DB, Triggers background worker. # @SIDE_EFFECT: Writes to DB, Triggers background worker.
# # @DATA_CONTRACT: Input -> CreateTaskRequest, Output -> Task
# @UX_STATE: Success -> 201 Created
# @UX_STATE: Error(Validation) -> 400 Bad Request
# @UX_STATE: Error(System) -> 500 Internal Server Error
@router.post("/tasks", response_model=Task, status_code=status.HTTP_201_CREATED) @router.post("/tasks", response_model=Task, status_code=status.HTTP_201_CREATED)
async def create_task( async def create_task(
request: CreateTaskRequest, request: CreateTaskRequest,

View File

@@ -1,9 +1,9 @@
# [DEF:TransactionCore:Module] # [DEF:TransactionCore:Module]
# @TIER: CRITICAL # @COMPLEXITY: 5
# @SEMANTICS: Finance, ACID, Transfer, Ledger # @SEMANTICS: Finance, ACID, Transfer, Ledger
# @PURPOSE: Core banking transaction processor with ACID guarantees. # @PURPOSE: Core banking transaction processor with ACID guarantees.
# @LAYER: Domain (Core) # @LAYER: Domain (Core)
# @RELATION: DEPENDS_ON -> [DEF:Infra:PostgresDB] # @RELATION: [DEPENDS_ON] ->[PostgresDB]
# #
# @INVARIANT: Total system balance must remain constant (Double-Entry Bookkeeping). # @INVARIANT: Total system balance must remain constant (Double-Entry Bookkeeping).
# @INVARIANT: Negative transfers are strictly forbidden. # @INVARIANT: Negative transfers are strictly forbidden.
@@ -33,14 +33,13 @@ class TransferResult(NamedTuple):
new_balance: Decimal new_balance: Decimal
# [DEF:execute_transfer:Function] # [DEF:execute_transfer:Function]
# @COMPLEXITY: 5
# @PURPOSE: Atomically move funds between accounts with audit trails. # @PURPOSE: Atomically move funds between accounts with audit trails.
# @DATA_CONTRACT: Input -> (sender_id: str, receiver_id: str, amount: Decimal), Output -> TransferResult # @RELATION: [CALLS] ->[atomic_transaction]
# @PRE: amount > 0; sender != receiver; sender_balance >= amount. # @PRE: amount > 0; sender != receiver; sender_balance >= amount.
# @POST: sender_balance -= amount; receiver_balance += amount; Audit Record Created. # @POST: sender_balance -= amount; receiver_balance += amount; Audit Record Created.
# @SIDE_EFFECT: Database mutation (Rows locked), Audit IO. # @SIDE_EFFECT: Database mutation (Rows locked), Audit IO.
# # @DATA_CONTRACT: Input -> (sender_id: str, receiver_id: str, amount: Decimal), Output -> TransferResult
# @UX_STATE: Success -> Returns 200 OK + Transaction Receipt.
# @UX_STATE: Error(LowBalance) -> 422 Unprocessable -> UI shows "Top-up needed" modal.
def execute_transfer(sender_id: str, receiver_id: str, amount: Decimal) -> TransferResult: def execute_transfer(sender_id: str, receiver_id: str, amount: Decimal) -> TransferResult:
# Guard: Input Validation (Вне belief_scope, так как это trivial проверка) # Guard: Input Validation (Вне belief_scope, так как это trivial проверка)
if amount <= Decimal("0.00"): if amount <= Decimal("0.00"):
@@ -54,7 +53,6 @@ def execute_transfer(sender_id: str, receiver_id: str, amount: Decimal) -> Trans
logger.reason("Initiating transfer", extra={"from": sender_id, "to": receiver_id, "amount": amount}) logger.reason("Initiating transfer", extra={"from": sender_id, "to": receiver_id, "amount": amount})
try: try:
# @RELATION: CALLS -> atomic_transaction
with atomic_transaction(): with atomic_transaction():
current_balance = get_balance(sender_id, for_update=True) current_balance = get_balance(sender_id, for_update=True)

View File

@@ -1,17 +1,26 @@
<!-- [DEF:FrontendComponentShot:Component] --> <!-- [DEF:FrontendComponentShot:Component] -->
<!-- <!--
/** /**
* @TIER: CRITICAL * @COMPLEXITY: 5
* @SEMANTICS: Task, Button, Action, UX * @SEMANTICS: Task, Button, Action, UX
* @PURPOSE: Action button to spawn a new task with full UX feedback cycle. * @PURPOSE: Action button to spawn a new task with full UX feedback cycle.
* @LAYER: UI (Presentation) * @LAYER: UI (Presentation)
* @RELATION: CALLS -> postApi * @RELATION: [CALLS] ->[postApi]
* *
* @INVARIANT: Must prevent double-submission while loading. * @INVARIANT: Must prevent double-submission while loading.
* @INVARIANT: Loading state must always terminate (no infinite spinner). * @INVARIANT: Loading state must always terminate (no infinite spinner).
* @INVARIANT: User must receive feedback on both success and failure. * @INVARIANT: User must receive feedback on both success and failure.
* *
* @SIDE_EFFECT: Sends network request and emits toast notifications.
* @DATA_CONTRACT: Input -> { plugin_id: string, params: object }, Output -> { task_id?: string }
*
* @UX_REACTIVITY: Props -> $props(), LocalState -> $state(isLoading). * @UX_REACTIVITY: Props -> $props(), LocalState -> $state(isLoading).
* @UX_STATE: Idle -> Button enabled, primary color, no spinner.
* @UX_STATE: Loading -> Button disabled, spinner visible, aria-busy=true.
* @UX_STATE: Success -> Toast success displayed.
* @UX_STATE: Error -> Toast error displayed.
* @UX_FEEDBACK: toast.success, toast.error
* @UX_RECOVERY: Error -> Keep form interactive and allow retry after failure.
* *
* @TEST_CONTRACT: ComponentState -> * @TEST_CONTRACT: ComponentState ->
* { * {
@@ -21,26 +30,13 @@
* "isLoading=true implies aria-busy=true" * "isLoading=true implies aria-busy=true"
* ] * ]
* } * }
*
* @TEST_FIXTURE: idle_state -> { isLoading: false } * @TEST_FIXTURE: idle_state -> { isLoading: false }
* @TEST_FIXTURE: successful_response -> { task_id: "task_123" } * @TEST_FIXTURE: successful_response -> { task_id: "task_123" }
*
* @TEST_EDGE: api_failure -> raises Error("Network") * @TEST_EDGE: api_failure -> raises Error("Network")
* @TEST_EDGE: empty_response -> {} * @TEST_EDGE: empty_response -> {}
* @TEST_EDGE: rapid_double_click -> special: concurrent_click * @TEST_EDGE: rapid_double_click -> special: concurrent_click
*
* @TEST_INVARIANT: prevent_double_submission -> VERIFIED_BY:[rapid_double_click] * @TEST_INVARIANT: prevent_double_submission -> VERIFIED_BY:[rapid_double_click]
* @TEST_INVARIANT: feedback_always_emitted -> VERIFIED_BY:[successful_response, api_failure] * @TEST_INVARIANT: feedback_always_emitted -> VERIFIED_BY:[successful_response, api_failure]
*
* @UX_STATE: Idle -> Button enabled, primary color, no spinner.
* @UX_STATE: Loading -> Button disabled, spinner visible, aria-busy=true.
* @UX_STATE: Success -> Toast success displayed.
* @UX_STATE: Error -> Toast error displayed.
*
* @UX_FEEDBACK: toast.success, toast.error
*
* @UX_TEST: Idle -> {click: spawnTask, expected: isLoading=true}
* @UX_TEST: Loading -> {double_click: ignored, expected: single_api_call}
*/ */
--> -->
<script> <script>

View File

@@ -1,10 +1,9 @@
# [DEF:PluginExampleShot:Module] # [DEF:PluginExampleShot:Module]
# @TIER: STANDARD # @COMPLEXITY: 3
# @SEMANTICS: Plugin, Core, Extension # @SEMANTICS: Plugin, Core, Extension
# @PURPOSE: Reference implementation of a plugin following GRACE standards. # @PURPOSE: Reference implementation of a plugin following GRACE standards.
# @LAYER: Domain (Business Logic) # @LAYER: Domain (Business Logic)
# @RELATION: INHERITS -> PluginBase # @RELATION: [INHERITS] ->[PluginBase]
# @INVARIANT: get_schema must return valid JSON Schema.
from typing import Dict, Any, Optional from typing import Dict, Any, Optional
from ..core.plugin_base import PluginBase from ..core.plugin_base import PluginBase
@@ -14,6 +13,7 @@ from ..core.logger import logger, belief_scope
# [DEF:ExamplePlugin:Class] # [DEF:ExamplePlugin:Class]
# @PURPOSE: A sample plugin to demonstrate execution context and logging. # @PURPOSE: A sample plugin to demonstrate execution context and logging.
# @RELATION: [INHERITS] ->[PluginBase]
class ExamplePlugin(PluginBase): class ExamplePlugin(PluginBase):
@property @property
def id(self) -> str: def id(self) -> str:
@@ -21,7 +21,6 @@ class ExamplePlugin(PluginBase):
#[DEF:get_schema:Function] #[DEF:get_schema:Function]
# @PURPOSE: Defines input validation schema. # @PURPOSE: Defines input validation schema.
# @DATA_CONTRACT: Input -> None, Output -> Dict (JSON Schema draft 7)
def get_schema(self) -> Dict[str, Any]: def get_schema(self) -> Dict[str, Any]:
return { return {
"type": "object", "type": "object",
@@ -36,8 +35,9 @@ class ExamplePlugin(PluginBase):
#[/DEF:get_schema:Function] #[/DEF:get_schema:Function]
# [DEF:execute:Function] # [DEF:execute:Function]
# @COMPLEXITY: 4
# @PURPOSE: Core plugin logic with structured logging and scope isolation. # @PURPOSE: Core plugin logic with structured logging and scope isolation.
# @DATA_CONTRACT: Input -> (params: Dict, context: Optional[TaskContext]), Output -> None # @RELATION: [BINDS_TO] ->[context.logger]
# @PRE: params must be validated against get_schema() before calling. # @PRE: params must be validated against get_schema() before calling.
# @POST: Plugin payload is processed; progress is reported if context exists. # @POST: Plugin payload is processed; progress is reported if context exists.
# @SIDE_EFFECT: Emits logs to centralized system and TaskContext. # @SIDE_EFFECT: Emits logs to centralized system and TaskContext.

View File

@@ -0,0 +1,40 @@
# [DEF:TrivialUtilityShot:Module]
# @COMPLEXITY: 1
# @PURPOSE: Reference implementation of a zero-overhead utility using implicit Complexity 1.
import re
from datetime import datetime, timezone
from typing import Optional
# [DEF:slugify:Function]
# @PURPOSE: Converts a string to a URL-safe slug.
def slugify(text: str) -> str:
if not text:
return ""
text = text.lower().strip()
text = re.sub(r'[^\w\s-]', '', text)
return re.sub(r'[-\s]+', '-', text)
# [/DEF:slugify:Function]
# [DEF:get_utc_now:Function]
def get_utc_now() -> datetime:
"""Returns current UTC datetime (purpose is omitted because it's obvious)."""
return datetime.now(timezone.utc)
# [/DEF:get_utc_now:Function]
# [DEF:PaginationDTO:Class]
class PaginationDTO:
# [DEF:__init__:Function]
def __init__(self, page: int = 1, size: int = 50):
self.page = max(1, page)
self.size = min(max(1, size), 1000)
# [/DEF:__init__:Function]
# [DEF:offset:Function]
@property
def offset(self) -> int:
return (self.page - 1) * self.size
# [/DEF:offset:Function]
# [/DEF:PaginationDTO:Class]
# [/DEF:TrivialUtilityShot:Module]

View File

@@ -30,7 +30,7 @@
## III. ТОПОЛОГИЯ ФАЙЛА (СТРОГИЙ ПОРЯДОК) ## III. ТОПОЛОГИЯ ФАЙЛА (СТРОГИЙ ПОРЯДОК)
1. **HEADER (Заголовок):**[DEF:filename:Module] 1. **HEADER (Заголовок):**[DEF:filename:Module]
@TIER: [CRITICAL | STANDARD | TRIVIAL] @COMPLEXITY: [1|2|3|4|5] *(алиас: `@C:`; legacy `@TIER` допустим только для обратной совместимости)*
@SEMANTICS: [keywords] @SEMANTICS: [keywords]
@PURPOSE: [Однострочная суть] @PURPOSE: [Однострочная суть]
@LAYER: [Domain | UI | Infra] @LAYER: [Domain | UI | Infra]
@@ -40,7 +40,7 @@
3. **FOOTER (Подвал):** [/DEF:filename:Module] 3. **FOOTER (Подвал):** [/DEF:filename:Module]
## IV. КОНТРАКТЫ (DESIGN BY CONTRACT & UX) ## IV. КОНТРАКТЫ (DESIGN BY CONTRACT & UX)
Обязательны для TIER: CRITICAL и STANDARD. Заменяют стандартные Docstrings. Контракты требуются адаптивно по уровню сложности, а не по жесткому tier.
**[CORE CONTRACTS]:** **[CORE CONTRACTS]:**
- `@PURPOSE:` Суть функции/компонента. - `@PURPOSE:` Суть функции/компонента.
@@ -62,11 +62,40 @@
- `@TEST_EDGE: [Название] ->[Сбой]` (Минимум 3: missing_field, invalid_type, external_fail). - `@TEST_EDGE: [Название] ->[Сбой]` (Минимум 3: missing_field, invalid_type, external_fail).
- `@TEST_INVARIANT: [Имя] -> VERIFIED_BY: [scenario_1, ...]` - `@TEST_INVARIANT: [Имя] -> VERIFIED_BY: [scenario_1, ...]`
## V. УРОВНИ СТРОГОСТИ (TIERS) ## V. ШКАЛА СЛОЖНОСТИ (COMPLEXITY 1-5)
Степень контроля задается в Header. Степень контроля задается в Header через `@COMPLEXITY` или сокращение `@C`.
- **CRITICAL** (Ядро/Деньги/Безопасность): 100% покрытие тегами GRACE. Обязательны: Граф, Инварианты, Логи `logger.reason/reflect`, все `@UX` и `@TEST` теги. Использование `belief_scope` строго обязательно. Если тег отсутствует, сущность по умолчанию считается **Complexity 1**. Это сделано специально для экономии токенов и снижения шума на очевидных утилитах.
- **STANDARD** (Бизнес-логика / Типовые формы): Базовый уровень. Обязательны: `@PURPOSE`, `@UX_STATE`, `@RELATION`, базовое логирование.
- **TRIVIAL** (Утилиты / DTO / Атомы UI): Минимальный каркас. Только якоря `[DEF]...[/DEF]` и `@PURPOSE`. - **1 — ATOMIC**
- Примеры: DTO, исключения, геттеры, простые утилиты, короткие адаптеры.
- Обязательны только якоря `[DEF]...[/DEF]`.
- `@PURPOSE` желателен, но не обязателен.
- **2 — SIMPLE**
- Примеры: простые helper-функции, небольшие мапперы, UI-атомы.
- Обязателен `@PURPOSE`.
- Остальные контракты опциональны.
- **3 — FLOW**
- Примеры: стандартная бизнес-логика, API handlers, сервисные методы, UI с загрузкой данных.
- Обязательны: `@PURPOSE`, `@RELATION`.
- Для UI дополнительно обязателен `@UX_STATE`.
- **4 — ORCHESTRATION**
- Примеры: сложная координация, работа с I/O, multi-step алгоритмы, stateful pipelines.
- Обязательны: `@PURPOSE`, `@RELATION`, `@PRE`, `@POST`, `@SIDE_EFFECT`.
- Для Python обязателен осмысленный путь логирования через `logger.reason()` / `logger.reflect()` или аналогичный belief-state механизм.
- **5 — CRITICAL**
- Примеры: auth, security, database boundaries, migration core, money-like invariants.
- Обязателен полный контракт: уровень 4 + `@DATA_CONTRACT` + `@INVARIANT`.
- Для UI требуются UX-контракты.
- Использование `belief_scope` строго обязательно.
**Legacy mapping (обратная совместимость):**
- `@TIER: TRIVIAL` -> Complexity 1
- `@TIER: STANDARD` -> Complexity 3
- `@TIER: CRITICAL` -> Complexity 5
## VI. ПРОТОКОЛ ЛОГИРОВАНИЯ (THREAD-LOCAL BELIEF STATE) ## VI. ПРОТОКОЛ ЛОГИРОВАНИЯ (THREAD-LOCAL BELIEF STATE)
Логирование — это механизм трассировки рассуждений ИИ (CoT) и управления Attention Energy. Архитектура использует Thread-local storage (`_belief_state`), поэтому `ID` прокидывается автоматически. Логирование — это механизм трассировки рассуждений ИИ (CoT) и управления Attention Energy. Архитектура использует Thread-local storage (`_belief_state`), поэтому `ID` прокидывается автоматически.
@@ -90,11 +119,11 @@
## VII. АЛГОРИТМ ИСПОЛНЕНИЯ И САМОКОРРЕКЦИИ ## VII. АЛГОРИТМ ИСПОЛНЕНИЯ И САМОКОРРЕКЦИИ
**[PHASE_1: ANALYSIS]** **[PHASE_1: ANALYSIS]**
Оцени TIER, Layer и UX-требования. При слепоте контекста -> `yield [NEED_CONTEXT: id]`. Оцени Complexity, Layer и UX-требования. При слепоте контекста -> `yield [NEED_CONTEXT: id]`.
**[PHASE_2: SYNTHESIS]** **[PHASE_2: SYNTHESIS]**
Сгенерируй каркас из `[DEF]`, Header и Контрактов. Сгенерируй каркас из `[DEF]`, Header и только тех контрактов, которые соответствуют уровню сложности.
**[PHASE_3: IMPLEMENTATION]** **[PHASE_3: IMPLEMENTATION]**
Напиши код строго по Контракту. Для CRITICAL секций открой `with belief_scope("ID"):` и орошай путь вызовами `logger.reason()` и `logger.reflect()`. Напиши код строго по Контракту. Для Complexity 5 секций открой `with belief_scope("ID"):` и орошай путь вызовами `logger.reason()` и `logger.reflect()`.
**[PHASE_4: CLOSURE]** **[PHASE_4: CLOSURE]**
Убедись, что все `[DEF]` закрыты соответствующими `[/DEF]`. Убедись, что все `[DEF]` закрыты соответствующими `[/DEF]`.

View File

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