Core changes: - Add @defgroup/@ingroup to 1791 C2+ contracts (555 files) for HCA 128× pre-training DSA grouping - Add §0.1 Pre-Training Frequency matrix to semantics-core - Add §VIII Attention Architecture rules (ATTN_1-4) with MLA/CSA/HCA/DSA mechanics - Add @defgroup/@ingroup to canonical syntax (§II) and all contract examples Agent prompts (5 files): - Add ZERO-STATE RATIONALE with MLA/CSA/HCA/DSA compression mechanics - Add pre-training note: @RATIONALE/@REJECTED are in-context learned tags - svelte-coder: add missing #region contract, fix Svelte rule violations - python-coder/fullstack-coder: honor function contracts from speckit plan - qa-tester: add attention compliance audit (P3 ATTN_1-4 checks) Skills (6 files): - Translate all axiom_config descriptions to English - Fix doc_dirs to index .opencode/ and .specify/ - Deduplicate 5× complexity_rules → single global_tags catalog - Reduce semantics-svelte 591→485 lines (remove duplicate code blocks) - Fix semantics-testing: 'Short IDs' → 'Short hierarchical IDs' - Fix all examples: flat IDs → hierarchical Domain.Name format - Fix Svelte examples: replace raw Tailwind + <button> with semantic tokens + /ui Speckit workflow (commands + templates): - speckit.plan: add Function-Level Contracts for C3+ with @PRE/@POST/@TEST_EDGE - speckit.plan: add Attention Compliance Gate (ATTN_1-4 before contract generation) - speckit.tasks: add function contract inlining format (constraints in task description) - speckit.specify: load semantics-core for spec density rules - spec-template: add #region contract, @SEMANTICS grouping, hierarchical IDs - ux-reference-template: add #region wrapper - plan-template: add attention gate, @defgroup/@ingroup guidance - tasks-template: add attention audit + rebuild + orphan check tasks - constitution.md: translate to English, add Principle VIII (attention-optimized contracts) Reference modules rewritten (hierarchical IDs + full contracts): - Auth.Jwt: 6 child contracts with @RATIONALE/@REJECTED/@TEST_EDGE - Api.Auth: 5 endpoints with @TEST_EDGE + molecular CoT markers - Migration.Model: @defgroup Migration with 18 @ACTION + 6 @INVARIANT Scripts: - add_defgroup_ingroup.py: zero-risk additive @ingroup migration (1791 insertions) - migrate_hierarchical.py: flat→hierarchical ID dry-run analysis (792 contracts) - merge_prompts.py: merge all prompts/skills/commands into one review file Config: - axiom_config.yaml: 749→395 lines (-47%), English, doc_dirs include prompts - Fix test_datasets.py import collision (rename → test_datasets_routes.py) - Fix test_preview.py: SupersetClient→get_superset_client, AsyncMock, logger f-string
290 lines
12 KiB
Python
290 lines
12 KiB
Python
# #region AssistantDatasetReviewDispatch [C:4] [TYPE Module] [SEMANTICS assistant, dataset, review, dispatch, confirm]
|
|
# @defgroup AssistantApi Module group.
|
|
# @BRIEF Dispatch and confirmation handling for dataset-review assistant intents.
|
|
# @LAYER API
|
|
# @RELATION DEPENDS_ON -> [AssistantDatasetReview]
|
|
# @RELATION DEPENDS_ON -> [DatasetReviewOrchestrator]
|
|
# @RELATION DEPENDS_ON -> [AssistantSchemas]
|
|
# @INVARIANT Dataset review dispatch requires valid session version for write operations.
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import UTC, datetime
|
|
from typing import Any
|
|
|
|
from fastapi import HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
|
|
from src.api.routes.dataset_review import FieldSemanticUpdateRequest, _update_semantic_field_state
|
|
from src.core.config_manager import ConfigManager
|
|
from src.core.logger import belief_scope, logger
|
|
from src.models.dataset_review import (
|
|
ApprovalState,
|
|
ReadinessState,
|
|
RecommendedAction,
|
|
)
|
|
from src.schemas.auth import User
|
|
from src.services.dataset_review.orchestrator import (
|
|
DatasetReviewOrchestrator,
|
|
PreparePreviewCommand,
|
|
)
|
|
from src.services.dataset_review.repositories.session_repository import (
|
|
DatasetReviewSessionRepository,
|
|
DatasetReviewSessionVersionConflictError,
|
|
)
|
|
|
|
from ._schemas import (
|
|
AssistantAction,
|
|
)
|
|
|
|
|
|
# #region _dataset_review_conflict_http_exception [C:2] [TYPE Function]
|
|
# @BRIEF Convert dataset-review optimistic-lock conflicts into shared 409 assistant semantics.
|
|
def _dataset_review_conflict_http_exception(
|
|
exc: DatasetReviewSessionVersionConflictError,
|
|
) -> HTTPException:
|
|
return HTTPException(
|
|
status_code=status.HTTP_409_CONFLICT,
|
|
detail={
|
|
"error_code": "session_version_conflict",
|
|
"message": str(exc),
|
|
"session_id": exc.session_id,
|
|
"expected_version": exc.expected_version,
|
|
"actual_version": exc.actual_version,
|
|
},
|
|
)
|
|
|
|
|
|
# #endregion _dataset_review_conflict_http_exception
|
|
|
|
|
|
# #region _dispatch_dataset_review_intent [C:4] [TYPE Function]
|
|
# @BRIEF Route confirmed dataset-review assistant intents through existing backend dataset-review APIs and orchestration boundaries.
|
|
# @RELATION CALLS -> DatasetReviewOrchestrator
|
|
# @PRE context contains valid session data and user intent.
|
|
# @POST Returns a structured response with planned actions and confirmations.
|
|
# @SIDE_EFFECT May update session state and enqueue tasks.
|
|
async def _dispatch_dataset_review_intent(
|
|
intent: dict[str, Any],
|
|
current_user: User,
|
|
config_manager: ConfigManager,
|
|
db: Session,
|
|
) -> tuple[str, str | None, list[AssistantAction]]:
|
|
with belief_scope("_dispatch_dataset_review_intent"):
|
|
logger.reason(
|
|
"Dispatching assistant dataset-review intent",
|
|
extra={"operation": intent.get("operation")},
|
|
)
|
|
entities = intent.get("entities", {})
|
|
session_id = entities.get("dataset_review_session_id")
|
|
session_version = entities.get("session_version")
|
|
if not session_id or session_version is None:
|
|
raise HTTPException(
|
|
status_code=422,
|
|
detail="Missing dataset_review_session_id/session_version",
|
|
)
|
|
|
|
operation = str(intent.get("operation") or "")
|
|
repository = DatasetReviewSessionRepository(db)
|
|
if operation == "dataset_review_answer_context":
|
|
summary = str(entities.get("summary") or "")
|
|
logger.reflect(
|
|
"Returned assistant-safe dataset review context summary",
|
|
extra={"session_id": session_id, "operation": operation},
|
|
)
|
|
return summary, None, []
|
|
|
|
session = repository.load_session_detail(session_id, current_user.id)
|
|
if session is None or session.user_id != current_user.id:
|
|
logger.explore(
|
|
"Assistant dataset-review intent rejected because session was not found",
|
|
extra={"session_id": session_id, "user_id": current_user.id},
|
|
)
|
|
raise HTTPException(
|
|
status_code=404, detail="Dataset review session not found"
|
|
)
|
|
|
|
try:
|
|
repository.require_session_version(session, int(session_version))
|
|
except DatasetReviewSessionVersionConflictError as exc:
|
|
logger.explore(
|
|
"Assistant dataset-review intent rejected due to stale session version",
|
|
extra={
|
|
"session_id": exc.session_id,
|
|
"expected_version": exc.expected_version,
|
|
"actual_version": exc.actual_version,
|
|
"operation": operation,
|
|
},
|
|
)
|
|
raise _dataset_review_conflict_http_exception(exc) from exc
|
|
|
|
logger.reason(
|
|
"Dispatching confirmed assistant dataset-review intent",
|
|
extra={
|
|
"session_id": session_id,
|
|
"session_version": session_version,
|
|
"operation": operation,
|
|
},
|
|
)
|
|
|
|
if operation == "dataset_review_approve_mappings":
|
|
mapping_ids = list(dict.fromkeys(entities.get("mapping_ids") or []))
|
|
if not mapping_ids:
|
|
raise HTTPException(
|
|
status_code=409, detail="No pending mappings to approve"
|
|
)
|
|
updated_count = 0
|
|
for mapping in session.execution_mappings:
|
|
if mapping.mapping_id not in mapping_ids:
|
|
continue
|
|
mapping.approval_state = ApprovalState.APPROVED
|
|
mapping.approved_by_user_id = current_user.id
|
|
mapping.approved_at = datetime.now(UTC)
|
|
updated_count += 1
|
|
if updated_count == 0:
|
|
raise HTTPException(
|
|
status_code=409, detail="No matching mappings available to approve"
|
|
)
|
|
session.last_activity_at = datetime.now(UTC)
|
|
if session.readiness_state == ReadinessState.MAPPING_REVIEW_NEEDED:
|
|
session.recommended_action = RecommendedAction.GENERATE_SQL_PREVIEW
|
|
repository.bump_session_version(session)
|
|
repository.db.commit()
|
|
repository.db.refresh(session)
|
|
repository.event_logger.log_for_session(
|
|
session,
|
|
actor_user_id=current_user.id,
|
|
event_type="assistant_mapping_approval",
|
|
event_summary="Assistant-approved warning-sensitive mappings persisted",
|
|
event_details={
|
|
"mapping_ids": mapping_ids,
|
|
"count": updated_count,
|
|
"version": int(getattr(session, "version", 0) or 0),
|
|
},
|
|
)
|
|
logger.reflect(
|
|
"Assistant mapping approval persisted within optimistic-lock boundary",
|
|
extra={
|
|
"session_id": session_id,
|
|
"updated_count": updated_count,
|
|
"version": int(getattr(session, "version", 0) or 0),
|
|
},
|
|
)
|
|
return (
|
|
f"Approved {updated_count} mapping(s) for dataset review session {session_id}.",
|
|
None,
|
|
[
|
|
AssistantAction(
|
|
type="focus_target",
|
|
label="Open mapping review",
|
|
target="mapping",
|
|
)
|
|
],
|
|
)
|
|
|
|
if operation == "dataset_review_set_field_semantics":
|
|
field_id = str(entities.get("field_id") or "").strip()
|
|
if not field_id:
|
|
raise HTTPException(status_code=422, detail="Missing field_id")
|
|
field = next(
|
|
(item for item in session.semantic_fields if item.field_id == field_id),
|
|
None,
|
|
)
|
|
if field is None:
|
|
raise HTTPException(status_code=404, detail="Semantic field not found")
|
|
update_request = FieldSemanticUpdateRequest(
|
|
candidate_id=entities.get("candidate_id"),
|
|
verbose_name=entities.get("verbose_name"),
|
|
description=entities.get("description"),
|
|
display_format=entities.get("display_format"),
|
|
lock_field=bool(entities.get("lock_field", False)),
|
|
)
|
|
try:
|
|
_update_semantic_field_state(
|
|
field, update_request, changed_by="assistant"
|
|
)
|
|
except HTTPException:
|
|
raise
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
session.last_activity_at = datetime.now(UTC)
|
|
repository.bump_session_version(session)
|
|
repository.db.commit()
|
|
repository.db.refresh(session)
|
|
repository.db.refresh(field)
|
|
repository.event_logger.log_for_session(
|
|
session,
|
|
actor_user_id=current_user.id,
|
|
event_type="assistant_field_semantics_updated",
|
|
event_summary="Assistant semantic field update persisted",
|
|
event_details={
|
|
"field_id": field.field_id,
|
|
"candidate_id": entities.get("candidate_id"),
|
|
"lock_field": bool(entities.get("lock_field", False)),
|
|
"version": int(getattr(session, "version", 0) or 0),
|
|
},
|
|
)
|
|
logger.reflect(
|
|
"Assistant semantic field update committed safely",
|
|
extra={
|
|
"session_id": session_id,
|
|
"field_id": field_id,
|
|
"version": int(getattr(session, "version", 0) or 0),
|
|
},
|
|
)
|
|
return (
|
|
f"Updated semantic field {field.field_name} for dataset review session {session_id}.",
|
|
None,
|
|
[
|
|
AssistantAction(
|
|
type="focus_target",
|
|
label="Open semantic review",
|
|
target=f"field:{field.field_id}",
|
|
)
|
|
],
|
|
)
|
|
|
|
if operation == "dataset_review_generate_sql_preview":
|
|
orchestrator = DatasetReviewOrchestrator(
|
|
repository=repository,
|
|
config_manager=config_manager,
|
|
)
|
|
result = orchestrator.prepare_launch_preview(
|
|
PreparePreviewCommand(
|
|
user=current_user,
|
|
session_id=session_id,
|
|
expected_version=int(session_version),
|
|
)
|
|
)
|
|
preview_status = getattr(
|
|
result.preview.preview_status, "value", result.preview.preview_status
|
|
)
|
|
logger.reflect(
|
|
"Assistant-triggered Superset preview generation completed",
|
|
extra={
|
|
"session_id": session_id,
|
|
"preview_status": preview_status,
|
|
},
|
|
)
|
|
return (
|
|
f"SQL preview {preview_status} for dataset review session {session_id}.",
|
|
None,
|
|
[
|
|
AssistantAction(
|
|
type="focus_target",
|
|
label="Open SQL preview",
|
|
target="sql-preview",
|
|
)
|
|
],
|
|
)
|
|
|
|
raise HTTPException(
|
|
status_code=400, detail="Unsupported dataset review operation"
|
|
)
|
|
|
|
|
|
# #endregion _dispatch_dataset_review_intent
|
|
|
|
|
|
# #endregion AssistantDatasetReviewDispatch
|