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:
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
40
.ai/shots/trivial_utility.py
Normal file
40
.ai/shots/trivial_utility.py
Normal 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]
|
||||||
@@ -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]`.
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
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.
|
# @PRE: tags dictionary is accessible.
|
||||||
# @POST: Returns Tier enum value.
|
# @POST: Returns Complexity enum value.
|
||||||
def get_tier(self) -> Tier:
|
def get_complexity(self) -> Complexity:
|
||||||
with belief_scope("get_tier"):
|
with belief_scope("get_complexity"):
|
||||||
tier_str = self.tags.get("TIER", "STANDARD").upper()
|
complexity_value = self.tags.get("COMPLEXITY") or self.tags.get("C")
|
||||||
|
if complexity_value is not None:
|
||||||
try:
|
try:
|
||||||
base_tier = Tier(tier_str)
|
base_complexity = Complexity(int(str(complexity_value).strip()))
|
||||||
except ValueError:
|
except (ValueError, TypeError):
|
||||||
base_tier = Tier.STANDARD
|
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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user