semantics

This commit is contained in:
2026-05-26 09:30:41 +03:00
parent 1e7bcecaea
commit 9ffa8af1dc
623 changed files with 28045 additions and 26557 deletions

View File

@@ -6,8 +6,8 @@
@SEMANTICS: dashboard, grid, selection, pagination
@PURPOSE: Displays a grid of dashboards with selection and pagination.
@LAYER: Component
@RELATION: USED_BY -> frontend/src/routes/migration/+page.svelte
@LAYER Component
@RELATION USED_BY -> [frontend/src/routes/migration/+page.svelte]
@INVARIANT: Selected IDs must be a subset of available dashboards.
-->

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: form, schema, dynamic, json-schema
@PURPOSE: Generates a form dynamically based on a JSON schema.
@LAYER: UI
@RELATION: BINDS_TO -> onsubmit callback
@LAYER UI
@RELATION BINDS_TO -> [onsubmit callback]
@PROPS:
- schema: Object - JSON schema for the form.

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: environment, selector, dropdown, migration
@PURPOSE: Provides a UI component for selecting source and target environments.
@LAYER: Feature
@RELATION: BINDS_TO -> environments store
@LAYER Feature
@RELATION BINDS_TO -> [environments store]
@INVARIANT: Source and target environments must be selectable from the list of configured environments.
-->

View File

@@ -5,7 +5,7 @@
<!--
@SEMANTICS: footer, layout, copyright
@PURPOSE: Displays the application footer with copyright information.
@LAYER: UI
@LAYER UI
-->
<footer class="bg-white border-t p-4 mt-8 text-center text-gray-500 text-sm">
&copy; 2025 Superset Tools. All rights reserved.

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: mapping, table, database, editor
@PURPOSE: Displays and allows editing of database mappings.
@LAYER: Feature
@RELATION: BINDS_TO -> mappings state
@LAYER Feature
@RELATION BINDS_TO -> [mappings state]
@INVARIANT: Each source database can be mapped to one target database.
-->

View File

@@ -4,9 +4,9 @@
<!--
@SEMANTICS: modal, mapping, prompt, migration
@PURPOSE: Prompts the user to provide a database mapping when one is missing during migration.
@LAYER: Feature
@RELATION: BINDS_TO -> onresolve
@RELATION: BINDS_TO -> oncancel
@LAYER Feature
@RELATION BINDS_TO -> [EXT:frontend:onresolve]
@RELATION BINDS_TO -> [EXT:frontend:oncancel]
@INVARIANT: Modal blocks migration progress until resolved or cancelled.
-->

View File

@@ -4,10 +4,10 @@
<!--
@SEMANTICS: navbar, navigation, header, layout
@PURPOSE: Main navigation bar for the application.
@LAYER: UI
@RELATION: BINDS_TO -> [authStore]
@RELATION: BINDS_TO -> [i18n]
@RELATION: DEPENDS_ON -> [LanguageSwitcher]
@LAYER UI
@RELATION BINDS_TO -> [EXT:frontend:authStore]
@RELATION BINDS_TO -> [EXT:frontend:i18n]
@RELATION DEPENDS_ON -> [LanguageSwitcher]
@UX_STATE: Idle -> Navigation links and settings menus are visible.
@UX_STATE: Authenticated -> User identity and logout action are rendered.

View File

@@ -4,10 +4,10 @@
<!--
@SEMANTICS: password, prompt, modal, input, security
@PURPOSE: A modal component to prompt the user for database passwords when a migration task is paused.
@LAYER: UI
@RELATION: USES -> frontend/src/lib/api.js (inferred)
@RELATION: BINDS_TO -> onresume
@RELATION: BINDS_TO -> oncancel
@LAYER UI
@RELATION USES -> [EXT:path:frontend/src/lib/api.js (inferred)]
@RELATION BINDS_TO -> [EXT:frontend:onresume]
@RELATION BINDS_TO -> [EXT:frontend:oncancel]
-->
<script>
let {

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: dashboard, grid, selection, pagination
@PURPOSE: Displays a grid of dashboards with selection and pagination.
@LAYER: Component
@RELATION: USED_BY -> frontend/src/routes/migration/+page.svelte
@LAYER Component
@RELATION USED_BY -> [frontend/src/routes/migration/+page.svelte]
@INVARIANT: Selected IDs must be a subset of available dashboards.
-->

View File

@@ -5,9 +5,9 @@
<script>
/**
* @PURPOSE: Blocking startup wizard for creating the first Superset environment from zero-state screens.
* @LAYER: UI
* @RELATION: CALLS -> api
* @RELATION: CALLS -> environmentContext
* @LAYER UI
* @RELATION CALLS -> api
* @RELATION CALLS -> environmentContext
* @INVARIANT: When open, wizard keeps user on an actionable setup path until the first environment exists.
*
* @UX_STATE: Intro -> Explains why dashboard screen is blocked.

View File

@@ -4,9 +4,9 @@
<!--
@SEMANTICS: task, history, list, status, monitoring
@PURPOSE: Displays a list of recent tasks with their status and allows selecting them for viewing logs.
@LAYER: UI
@RELATION: USES -> stores
@RELATION: USES -> frontend/src/lib/api.js (inferred)
@LAYER UI
@RELATION USES -> [EXT:frontend:stores]
@RELATION USES -> [EXT:path:frontend/src/lib/api.js (inferred)]
-->
<script>
import { onMount, onDestroy } from 'svelte';

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: tasks, list, status, history
@PURPOSE: Displays a list of tasks with their status and execution details.
@LAYER: Component
@RELATION: USES -> api.js
@LAYER Component
@RELATION USES -> [EXT:frontend:api.js]
-->
<script lang="ts">

View File

@@ -6,9 +6,9 @@
@SEMANTICS: task, log, viewer, inline, realtime
@PURPOSE: Displays task logs inline (in drawer) or as modal. Merges real-time WebSocket logs with polled historical logs.
@LAYER: UI
@RELATION: USES -> taskService
@RELATION: USES -> TaskLogPanel
@LAYER UI
@RELATION USES -> [EXT:frontend:taskService]
@RELATION USES -> [TaskLogPanel]
@INVARIANT: Real-time logs are always appended without duplicates.
-->
<script>

View File

@@ -6,8 +6,8 @@
@SEMANTICS: task, runner, logs, websocket
@PURPOSE: Connects to a WebSocket to display real-time logs for a running task with filtering support.
@LAYER: UI
@RELATION: DEPENDS_ON -> TaskLogPanel
@LAYER UI
@RELATION DEPENDS_ON -> [TaskLogPanel]
-->
<script>
// [SECTION: IMPORTS]
@@ -51,7 +51,7 @@
const task = get(selectedTask);
if (!task || connectionStatus === 'completed') return;
console.log(`[TaskRunner][Entry] Connecting to logs for task: ${task.id} (Attempt ${reconnectAttempts + 1}) filters: source=${selectedSource}, level=${selectedLevel}`);
console.log(`[EXT:frontend:TaskRunner][Entry] Connecting to logs for task: ${task.id} (Attempt ${reconnectAttempts + 1}) filters: source=${selectedSource}, level=${selectedLevel}`);
connectionStatus = 'connecting';
let wsUrl = getWsUrl(task.id);
@@ -69,7 +69,7 @@
ws = new WebSocket(wsUrl);
ws.onopen = () => {
console.log('[TaskRunner][Coherence:OK] WebSocket connection established');
console.log('[EXT:frontend:TaskRunner][Coherence:OK] WebSocket connection established');
connectionStatus = 'connected';
reconnectAttempts = 0;
startDataTimeout();
@@ -121,24 +121,24 @@
}
ws.onerror = (error) => {
console.error('[TaskRunner][Coherence:Failed] WebSocket error:', error);
console.error('[EXT:frontend:TaskRunner][Coherence:Failed] WebSocket error:', error);
connectionStatus = 'disconnected';
};
ws.onclose = (event) => {
console.log(`[TaskRunner][Exit] WebSocket connection closed (Code: ${event.code})`);
console.log(`[EXT:frontend:TaskRunner][Exit] WebSocket connection closed (Code: ${event.code})`);
clearTimeout(dataTimeout);
waitingForData = false;
if (connectionStatus !== 'completed' && reconnectAttempts < maxReconnectAttempts) {
const delay = Math.min(initialReconnectDelay * Math.pow(2, reconnectAttempts), maxReconnectDelay);
console.log(`[TaskRunner][Action] Reconnecting in ${delay}ms...`);
console.log(`[EXT:frontend:TaskRunner][Action] Reconnecting in ${delay}ms...`);
reconnectTimeout = setTimeout(() => {
reconnectAttempts++;
connect();
}, delay);
} else if (reconnectAttempts >= maxReconnectAttempts) {
console.error('[TaskRunner][Coherence:Failed] Max reconnect attempts reached.');
console.error('[EXT:frontend:TaskRunner][Coherence:Failed] Max reconnect attempts reached.');
addToast($t.tasks?.log_stream_failed, 'error');
}
};
@@ -158,7 +158,7 @@
selectedSource = source;
selectedLevel = level;
console.log(`[TaskRunner] Filter changed, reconnecting WebSocket: source=${source}, level=${level}`);
console.log(`[EXT:frontend:TaskRunner] Filter changed, reconnecting WebSocket: source=${source}, level=${level}`);
// Clear current logs when filter changes to avoid confusion
taskLogs.set([]);
@@ -290,14 +290,14 @@
onMount(() => {
const unsubscribe = selectedTask.subscribe(task => {
if (task) {
console.log(`[TaskRunner][Action] Task selected: ${task.id}. Initializing connection.`);
console.log(`[EXT:frontend:TaskRunner][Action] Task selected: ${task.id}. Initializing connection.`);
if (ws) ws.close();
clearTimeout(reconnectTimeout);
reconnectAttempts = 0;
connectionStatus = 'disconnected';
if (task.logs && Array.isArray(task.logs)) {
console.log(`[TaskRunner] Loaded ${task.logs.length} existing logs.`);
console.log(`[EXT:frontend:TaskRunner] Loaded ${task.logs.length} existing logs.`);
taskLogs.set(task.logs);
} else {
taskLogs.set([]);
@@ -315,7 +315,7 @@
clearTimeout(reconnectTimeout);
clearTimeout(dataTimeout);
if (ws) {
console.log("[TaskRunner][Action] Closing WebSocket connection.");
console.log("[EXT:frontend:TaskRunner][Action] Closing WebSocket connection.");
ws.close();
}
});

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: toast, notification, feedback, ui
@PURPOSE: Displays transient notifications (toasts) in the bottom-right corner.
@LAYER: UI
@RELATION: BINDS_TO -> toasts
@LAYER UI
@RELATION BINDS_TO -> [EXT:frontend:toasts]
@UX_STATE: Empty -> Toast viewport stays mounted without visible notifications.
@UX_STATE: Visible -> Active toast items render with type-specific emphasis.

View File

@@ -1,8 +1,8 @@
// #region TaskLogViewerTest:Module [TYPE Function]
// @SEMANTICS: tests, task-log, viewer, mount, components
// @PURPOSE: Unit tests for TaskLogViewer component by mounting it and observing the DOM.
// @LAYER: UI (Tests)
// @RELATION: DEPENDS_ON -> [TaskLogViewer]
// @LAYER UI (Tests)
// @RELATION DEPENDS_ON -> [TaskLogViewer]
// @INVARIANT: Duplicate logs are never appended. Polling only active for in-progress tasks.
// @TEST_CONTRACT: TaskLogViewerPropsAndLogStream -> RenderedLogTimeline
// @TEST_SCENARIO: historical_and_realtime_merge -> Historical logs render and realtime logs append without duplication.

View File

@@ -4,11 +4,11 @@
<!--
@SEMANTICS: auth, route-guard, permission, redirect, session-validation
@PURPOSE: Enforces authenticated and authorized access before protected route content is rendered.
@LAYER: UI
@RELATION: [BINDS_TO] ->[authStore]
@RELATION: [CALLS] ->[goto]
@RELATION: [DEPENDS_ON] ->[Permissions]
@RELATION: [CALLS] ->[fetchApi]
@LAYER UI
@RELATION BINDS_TO ->[EXT:frontend:authStore]
@RELATION CALLS ->[EXT:frontend:goto]
@RELATION DEPENDS_ON ->[EXT:internal:Permissions]
@RELATION CALLS ->[EXT:frontend:fetchApi]
@INVARIANT: Unauthenticated users are redirected to /login, unauthorized users are redirected to fallbackPath, and protected slot renders only when access is verified.
@UX_STATE: Idle -> Component mounted, verification not yet started.
@UX_STATE: Loading -> Spinner is rendered while auth/session/permission validation is in progress.

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: backup, list, table
@PURPOSE: Displays a list of existing backups.
@LAYER: Component
@RELATION: USED_BY -> frontend/src/components/backups/BackupManager.svelte
@LAYER Component
@RELATION USED_BY -> [frontend/src/components/backups/BackupManager.svelte]
-->
<script lang="ts">

View File

@@ -4,9 +4,9 @@
<!--
@SEMANTICS: backup, manager, orchestrator
@PURPOSE: Main container for backup management, handling creation and listing.
@LAYER: Feature
@RELATION: USES -> BackupList
@RELATION: USES -> api
@LAYER Feature
@RELATION USES -> [BackupList]
@RELATION USES -> [EXT:frontend:api]
@INVARIANT: Only one backup task can be triggered at a time from the UI.
-->
@@ -56,8 +56,8 @@
* @returns {Promise<void>}
* @side_effect Updates local state variables.
*/
// @RELATION: CALLS -> api.getEnvironmentsList
// @RELATION: CALLS -> api.requestApi
// @RELATION CALLS -> api.getEnvironmentsList
// @RELATION CALLS -> api.requestApi
function getSubpath(path: string): string {
if (!path || path === 'backups') return '';
return path.replace(/^backups\/?/, '');
@@ -70,7 +70,7 @@
}
async function loadData() {
console.log("[BackupManager][Entry] Loading data.");
console.log("[EXT:frontend:BackupManager][Entry] Loading data.");
loading = true;
try {
const subpath = getSubpath(currentPath);
@@ -94,9 +94,9 @@
is_directory: file.mime_type === 'directory',
status: 'success'
}));
console.log("[BackupManager][Action] Data loaded successfully.");
console.log("[EXT:frontend:BackupManager][Action] Data loaded successfully.");
} catch (error) {
console.error("[BackupManager][Coherence:Failed] Load failed", error);
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Load failed", error);
} finally {
loading = false;
}
@@ -113,7 +113,7 @@
* @returns {Promise<void>}
* @side_effect Dispatches a toast notification.
*/
// @RELATION: CALLS -> api.createTask
// @RELATION CALLS -> api.createTask
// #region handleUpdateSchedule:Function [TYPE Function]
/**
* @purpose Updates the backup schedule for the selected environment.
@@ -123,7 +123,7 @@
async function handleUpdateSchedule() {
if (!selectedEnvId) return;
console.log(`[BackupManager][Action] Updating schedule for env: ${selectedEnvId}`);
console.log(`[EXT:frontend:BackupManager][Action] Updating schedule for env: ${selectedEnvId}`);
savingSchedule = true;
try {
await api.updateEnvironmentSchedule(selectedEnvId, {
@@ -139,7 +139,7 @@
: e
);
} catch (error) {
console.error("[BackupManager][Coherence:Failed] Schedule update failed", error);
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Schedule update failed", error);
} finally {
savingSchedule = false;
}
@@ -152,14 +152,14 @@
return;
}
console.log(`[BackupManager][Action] Triggering backup for env: ${selectedEnvId}`);
console.log(`[EXT:frontend:BackupManager][Action] Triggering backup for env: ${selectedEnvId}`);
creating = true;
try {
await api.createTask('superset-backup', { environment_id: selectedEnvId });
addToast($t.common.success, 'success');
console.log("[BackupManager][Coherence:OK] Backup task triggered.");
console.log("[EXT:frontend:BackupManager][Coherence:OK] Backup task triggered.");
} catch (error) {
console.error("[BackupManager][Coherence:Failed] Create failed", error);
console.error("[EXT:frontend:BackupManager][Coherence:Failed] Create failed", error);
} finally {
creating = false;
}

View File

@@ -4,11 +4,11 @@
<!--
@SEMANTICS: git, branch, selection, checkout
@PURPOSE: UI для выбора и создания веток Git.
@LAYER: Component
@RELATION: CALLS -> gitService.getBranches
@RELATION: CALLS -> GitServiceBranch
@RELATION: CALLS -> gitService.createBranch
@RELATION: BINDS_TO -> onchange
@LAYER Component
@RELATION CALLS -> [gitService.getBranches]
@RELATION CALLS -> [GitServiceBranch]
@RELATION CALLS -> [gitService.createBranch]
@RELATION BINDS_TO -> [onchange]
-->
<script>
@@ -54,13 +54,13 @@
* @post branches обновлен.
*/
async function loadBranches() {
console.log(`[BranchSelector][Action] Loading branches for dashboard ${dashboardId}`);
console.log(`[EXT:frontend:BranchSelector][Action] Loading branches for dashboard ${dashboardId}`);
loading = true;
try {
branches = await gitService.getBranches(dashboardId, envId);
console.log(`[BranchSelector][Coherence:OK] Loaded ${branches.length} branches`);
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Loaded ${branches.length} branches`);
} catch (e) {
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
toast($t.git?.load_branches_failed, 'error');
} finally {
loading = false;
@@ -86,15 +86,15 @@
* @post currentBranch обновлен, родительский callback вызван.
*/
async function handleCheckout(branchName) {
console.log(`[BranchSelector][Action] Checking out branch ${branchName}`);
console.log(`[EXT:frontend:BranchSelector][Action] Checking out branch ${branchName}`);
try {
await gitService.checkoutBranch(dashboardId, branchName, envId);
currentBranch = branchName;
onchange({ branch: branchName });
toast($t.git?.switched_to?.replace('{branch}', branchName), 'success');
console.log(`[BranchSelector][Coherence:OK] Checked out ${branchName}`);
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Checked out ${branchName}`);
} catch (e) {
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
toast(e.message, 'error');
}
}
@@ -108,16 +108,16 @@
*/
async function handleCreate() {
if (!newBranchName) return;
console.log(`[BranchSelector][Action] Creating branch ${newBranchName} from ${currentBranch}`);
console.log(`[EXT:frontend:BranchSelector][Action] Creating branch ${newBranchName} from ${currentBranch}`);
try {
await gitService.createBranch(dashboardId, newBranchName, currentBranch, envId);
toast($t.git?.created_branch?.replace('{branch}', newBranchName), 'success');
showCreate = false;
newBranchName = '';
await loadBranches();
console.log(`[BranchSelector][Coherence:OK] Branch created`);
console.log(`[EXT:frontend:BranchSelector][Coherence:OK] Branch created`);
} catch (e) {
console.error(`[BranchSelector][Coherence:Failed] ${e.message}`);
console.error(`[EXT:frontend:BranchSelector][Coherence:Failed] ${e.message}`);
toast(e.message, 'error');
}
}

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: git, history, commits, audit
@PURPOSE: Displays the commit history for a specific dashboard.
@LAYER: Component
@RELATION: CALLS -> gitService.getHistory
@LAYER Component
@RELATION CALLS -> [gitService.getHistory]
-->
<script>

View File

@@ -6,8 +6,8 @@
@SEMANTICS: git, commit, modal, version_control, diff
@PURPOSE: Модальное окно для создания коммита с просмотром изменений (diff).
@LAYER: Component
@RELATION: CALLS -> [GitServiceClient]
@LAYER Component
@RELATION CALLS -> [EXT:frontend:GitServiceClient]
@UX_STATE: Ready -> Commit message, status, and diff preview are available for the selected repository.
@UX_STATE: Submitting -> Commit actions stay disabled while the commit request is in flight.
-->

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: git, conflict, resolution, merge
@PURPOSE: UI for resolving merge conflicts (Keep Mine / Keep Theirs).
@LAYER: Component
@RELATION: BINDS_TO -> onresolve
@LAYER Component
@RELATION BINDS_TO -> [EXT:frontend:onresolve]
@INVARIANT: User must resolve all conflicts before saving.
-->
@@ -40,7 +40,7 @@
*/
function resolve(file, strategy) {
console.log(
`[ConflictResolver][Action] Resolving ${file} with ${strategy}`,
`[EXT:frontend:ConflictResolver][Action] Resolving ${file} with ${strategy}`,
);
resolutions[file] = strategy;
resolutions = { ...resolutions }; // Trigger update
@@ -59,7 +59,7 @@
const unresolved = conflicts.filter((c) => !resolutions[c.file_path]);
if (unresolved.length > 0) {
console.warn(
`[ConflictResolver][Coherence:Failed] ${unresolved.length} unresolved conflicts`,
`[EXT:frontend:ConflictResolver][Coherence:Failed] ${unresolved.length} unresolved conflicts`,
);
toast(
`Please resolve all conflicts first. (${unresolved.length} remaining)`,
@@ -69,7 +69,7 @@
}
// 2. Implementation
console.log(`[ConflictResolver][Coherence:OK] All conflicts resolved`);
console.log(`[EXT:frontend:ConflictResolver][Coherence:OK] All conflicts resolved`);
onresolve(resolutions);
show = false;
}

View File

@@ -4,9 +4,9 @@
<!--
@SEMANTICS: deployment, git, environment, modal
@PURPOSE: Modal for deploying a dashboard to a target environment.
@LAYER: Component
@RELATION: CALLS -> GitService
@RELATION: DISPATCHES -> deploy
@LAYER Component
@RELATION CALLS -> [GitService]
@RELATION DISPATCHES -> [deploy]
@INVARIANT: Cannot deploy without a selected environment.
-->
@@ -82,7 +82,7 @@
* @side_effect Updates environments state.
*/
async function loadEnvironments() {
console.log(`[DeploymentModal][Action] Loading environments`);
console.log(`[EXT:frontend:DeploymentModal][Action] Loading environments`);
loading = true;
try {
environments = await api.getEnvironmentsList();
@@ -94,10 +94,10 @@
selectedEnv = (candidates[0]?.id) || "";
}
console.log(
`[DeploymentModal][Coherence:OK] Loaded ${environments.length} environments`,
`[EXT:frontend:DeploymentModal][Coherence:OK] Loaded ${environments.length} environments`,
);
} catch (e) {
console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
console.error(`[EXT:frontend:DeploymentModal][Coherence:Failed] ${e.message}`);
toast($t.migration?.loading_envs_failed, "error");
} finally {
loading = false;
@@ -122,7 +122,7 @@
return;
}
}
console.log(`[DeploymentModal][Action] Deploying to ${selectedEnv}`);
console.log(`[EXT:frontend:DeploymentModal][Action] Deploying to ${selectedEnv}`);
deploying = true;
try {
const result = await gitService.deploy(dashboardId, selectedEnv, envId);
@@ -131,9 +131,9 @@
"success",
);
show = false;
console.log(`[DeploymentModal][Coherence:OK] Deployment triggered`);
console.log(`[EXT:frontend:DeploymentModal][Coherence:OK] Deployment triggered`);
} catch (e) {
console.error(`[DeploymentModal][Coherence:Failed] ${e.message}`);
console.error(`[EXT:frontend:DeploymentModal][Coherence:Failed] ${e.message}`);
toast(e.message, "error");
} finally {
deploying = false;

View File

@@ -2,7 +2,7 @@
<!-- @BRIEF Git initialization panel: select config, create remote repo, init local repo. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
<!-- @RELATION CALLS -> [gitService] -->
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
<!-- @UX_STATE Idle -> Config selector, remote URL input, create/init buttons. -->
<!-- @UX_STATE Loading -> Buttons disabled, spinner visible. -->
<script>

View File

@@ -6,10 +6,10 @@
<!-- @RELATION USES -> [GitReleasePanel] -->
<!-- @RELATION USES -> [GitOperationsPanel] -->
<!-- @RELATION USES -> [GitMergeDialog] -->
<!-- @RELATION USES -> [BranchSelector] -->
<!-- @RELATION USES -> [DeploymentModal] -->
<!-- @RELATION USES -> [ConflictResolver] -->
<!-- @RELATION CALLS -> [gitService] -->
<!-- @RELATION USES -> [EXT:frontend:BranchSelector] -->
<!-- @RELATION USES -> [EXT:frontend:DeploymentModal] -->
<!-- @RELATION USES -> [EXT:frontend:ConflictResolver] -->
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
<!-- @RELATION DEPENDS_ON -> [UseGitManager] -->
<!-- @RATIONALE Decomposed from 1220→~370 lines by extracting sub-panels, utils, and composable handlers per INV_7. -->

View File

@@ -2,7 +2,7 @@
<!-- @BRIEF Unfinished merge recovery dialog: abort, continue, resolve conflicts. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
<!-- @RELATION CALLS -> [gitService] -->
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
<!-- @UX_STATE Open -> Dialog with merge context, status, and action buttons. -->
<!-- @UX_STATE Loading -> Recovery state loading spinner. -->
<script>

View File

@@ -2,7 +2,7 @@
<!-- @BRIEF Git release panel: promote branches via MR or direct mode. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
<!-- @RELATION CALLS -> [gitService] -->
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
<!-- @UX_STATE Idle -> Pipeline status and promote button. -->
<!-- @UX_STATE Advanced -> Expandable branch/reason settings. -->
<script>

View File

@@ -2,7 +2,7 @@
<!-- @BRIEF Git workspace panel: sync, commit message input, diff viewer, commit action. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [GitUtils] -->
<!-- @RELATION CALLS -> [gitService] -->
<!-- @RELATION CALLS -> [EXT:frontend:gitService] -->
<!-- @UX_STATE Idle -> Commit form with diff viewer. -->
<!-- @UX_STATE Loading -> GeneratingMessage spinner, workspace loading. -->
<!-- @UX_STATE Error -> Toast on failure. -->

View File

@@ -1,7 +1,7 @@
// #region GitManagerUnfinishedMergeIntegrationTest:Module [TYPE Function]
// @SEMANTICS: git-manager, unfinished-merge, dialog, integration-test
// @PURPOSE: Protect unresolved-merge dialog contract in GitManager pull flow.
// @RELATION: DEPENDS_ON -> [GitManager]
// @RELATION DEPENDS_ON -> [GitManager]
import { describe, it, expect } from 'vitest';
import fs from 'node:fs';

View File

@@ -1,6 +1,6 @@
// #region UseGitManager [C:3] [TYPE Module] [SEMANTICS git, handlers, composable, orchestration]
// @BRIEF Composable for GitManager handler functions — extracted to reduce component size per INV_7.
// @RELATION DEPENDS_ON -> [gitService]
// @RELATION DEPENDS_ON -> [EXT:frontend:gitService]
// @RELATION DEPENDS_ON -> [GitUtils]
// @RATIONALE Extracted handler logic from GitManager (1220→~350 lines) to meet INV_7 <150 line contract limit.
import { gitService } from '../../services/gitService';

View File

@@ -5,8 +5,8 @@
@UX_STATE: Loading -> Default
@PURPOSE: UI component for previewing generated dataset documentation before saving.
@LAYER: UI
@RELATION: DEPENDS_ON -> backend/src/plugins/llm_analysis/plugin.py
@LAYER UI
@RELATION DEPENDS_ON -> [EXT:path:backend/src/plugins/llm_analysis/plugin.py]
-->
<script>

View File

@@ -5,8 +5,8 @@
@UX_STATE: Loading -> Default
@PURPOSE: UI form for managing LLM provider configurations.
@LAYER: UI
@RELATION: DEPENDS_ON -> requestApi
@LAYER UI
@RELATION DEPENDS_ON -> [EXT:frontend:requestApi]
-->
<script>

View File

@@ -1,8 +1,8 @@
<!-- #region ValidationReport [C:3] [TYPE Component] [SEMANTICS llm, validation, report, issues, dashboard] -->
<!-- @BRIEF Displays the results of an LLM-based dashboard validation task with status, issues, and recommendations. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [DashboardValidationService] -->
<!-- @RELATION CALLS -> [api_module] -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:DashboardValidationService] -->
<!-- @RELATION CALLS -> [EXT:frontend:api_module] -->
<!-- @PURPOSE: Displays the results of an LLM-based dashboard validation task. -->
<script>

View File

@@ -1,6 +1,6 @@
// #region ProviderConfigIntegrationTest [C:3] [TYPE Module] [SEMANTICS llm, provider-config, integration-test, edit-flow, delete-flow]
// @PURPOSE: Protect edit, submit, test, and delete interaction contracts in LLM provider settings UI.
// @LAYER: UI Tests
// @LAYER UI (Tests)
// @RELATION DEPENDS_ON -> [ProviderConfig]
// @INVARIANT: Edit action keeps explicit click handler and opens normalized edit form.
// @INVARIANT: Masked API keys are excluded from save/test/fetch-models payloads.
@@ -15,7 +15,7 @@ const COMPONENT_PATH = path.resolve(
);
// #region provider_config_edit_contract_tests:Function [TYPE Function]
// @RELATION: BINDS_TO -> [ProviderConfigIntegrationTest]
// @RELATION BINDS_TO -> [EXT:frontend:ProviderConfigIntegrationTest]
// @PURPOSE: Validate edit and delete handler wiring plus normalized edit form state mapping.
// @PRE: ProviderConfig component source exists in expected path.
// @POST: Contract checks ensure edit click cannot degrade into no-op flow.

View File

@@ -6,8 +6,8 @@
@SEMANTICS: storage, files, list, table
@PURPOSE: Displays a table of files with metadata and actions.
@LAYER: UI
@RELATION: DEPENDS_ON -> storageService
@LAYER UI
@RELATION DEPENDS_ON -> [storageService]
@PROPS: files (Array) - List of StoredFile objects.
@EVENTS: ondelete/onnavigate callback props - Raised when a file is deleted or navigation is requested.

View File

@@ -6,8 +6,8 @@
@SEMANTICS: storage, upload, files
@PURPOSE: Provides a form for uploading files to a specific category.
@LAYER: UI
@RELATION: DEPENDS_ON -> storageService
@LAYER UI
@RELATION DEPENDS_ON -> [storageService]
@PROPS: None
@EVENTS: onuploaded callback prop - Invoked when a file is successfully uploaded.

View File

@@ -2,11 +2,11 @@
<!-- @BRIEF Component component: components/tasks/LogEntryRow.svelte -->
<!-- @LAYER UI -->
<!--
@RELATION: USES -> App
@RELATION USES -> [EXT:frontend:App]
@SEMANTICS: log, entry, row, ui
@PURPOSE: Renders a single log entry with stacked layout optimized for narrow drawer panels.
@LAYER: UI
@LAYER UI
@UX_STATE: Idle -> Displays log entry with color-coded level and source badges.
-->
<script>

View File

@@ -2,11 +2,11 @@
<!-- @BRIEF Component component: components/tasks/LogFilterBar.svelte -->
<!-- @LAYER UI -->
<!--
@RELATION: USES -> App
@RELATION USES -> [EXT:frontend:App]
@SEMANTICS: log, filter, ui
@PURPOSE: Compact filter toolbar for logs — level, source, and text search in a single dense row.
@LAYER: UI
@LAYER UI
@UX_STATE: Idle -> Shows filter controls
@UX_STATE: Active -> Filters applied, clear button visible
-->

View File

@@ -4,9 +4,9 @@
<!--
@SEMANTICS: task, log, panel, filter, list
@PURPOSE: Combines log filtering and display into a single cohesive light-themed panel.
@LAYER: UI
@RELATION: USES -> LogFilterBar
@RELATION: USES -> LogEntryRow
@LAYER UI
@RELATION USES -> [LogFilterBar]
@RELATION USES -> [LogEntryRow]
@INVARIANT: Must always display logs in chronological order and respect auto-scroll preference.
@UX_STATE: Empty -> Displays "No logs" message
@UX_STATE: Populated -> Displays list of LogEntryRow components

View File

@@ -1,7 +1,7 @@
<!-- #region TaskResultPanel [C:2] [TYPE Component] [SEMANTICS task, result, summary, status, plugin] -->
<!-- @BRIEF Displays formatted task result summary with status badges and result details. -->
<!-- @LAYER UI -->
<!-- @RELATION DEPENDS_ON -> [i18n] -->
<!-- @RELATION DEPENDS_ON -> [EXT:frontend:i18n] -->
<!-- @UX_STATE Empty -> No task selected, placeholder shown. -->
<!-- @UX_STATE Loaded -> Task result displayed with status color coding. -->
<script>

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: debug, tool, api, structure
@PURPOSE: UI component for system diagnostics and debugging API responses.
@LAYER: UI
@RELATION: USES -> frontend/src/services/toolsService.js
@LAYER UI
@RELATION USES -> [EXT:path:frontend/src/services/toolsService.js]
-->
<script>
// [SECTION: IMPORTS]

View File

@@ -4,8 +4,8 @@
<!--
@SEMANTICS: mapper, tool, dataset, sqllab, excel
@PURPOSE: UI component for mapping dataset column verbose names using Superset SQL Lab or Excel files.
@LAYER: UI
@RELATION: USES -> frontend/src/services/toolsService.js
@LAYER UI
@RELATION USES -> [EXT:path:frontend/src/services/toolsService.js]
-->
<script>
// [SECTION: IMPORTS]