diff --git a/.opencode/command/speckit.analyze.md b/.opencode/command/speckit.analyze.md index 7529ad8a..9d5c97e7 100644 --- a/.opencode/command/speckit.analyze.md +++ b/.opencode/command/speckit.analyze.md @@ -1,5 +1,5 @@ --- -description: Perform a read-only consistency analysis across spec.md, plan.md, tasks.md, and ADR sources for the active ss-tools feature. +description: Perform a read-only consistency analysis across spec.md, plan.md, tasks.md, contracts/modules.md, and ADR sources for the active ss-tools feature. Covers UX Contract Traceability, ATTN Rules Compliance, and decision-memory continuity. --- ## User Input @@ -10,62 +10,273 @@ $ARGUMENTS You **MUST** consider the user input before proceeding (if not empty). +## Required Skills + +MANDATORY USE `skill({name="semantics-core"})`, `skill({name="semantics-contracts"})`, `skill({name="semantics-svelte"})`. + ## Goal -Identify inconsistencies, ambiguities, coverage gaps, and decision-memory drift across the feature artifacts before implementation proceeds. +Identify inconsistencies, ambiguities, coverage gaps, decision-memory drift, UX contract gaps, and ATTN-rules violations across the feature artifacts **before implementation proceeds**. This command MUST run only after `/speckit.tasks` has produced a complete `tasks.md`. ## Operating Constraints -**STRICTLY READ-ONLY**: Do not modify files. +**STRICTLY READ-ONLY**: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up edits). -**Constitution Authority**: `.specify/memory/constitution.md` is the local constitutional baseline for this workflow. Conflicts with its must-level principles are CRITICAL. +**Constitution Authority**: `.specify/memory/constitution.md` is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks — not dilution, reinterpretation, or silent ignoring of the principle. ## Execution Steps -1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` and derive absolute paths for `spec.md`, `plan.md`, `tasks.md`, and relevant ADR sources under `docs/adr/`. - - Analyze the active feature directory under `specs//` only. +### 1. Initialize Analysis Context -2. Load minimal necessary context from: - - `spec.md` - - `plan.md` - - `tasks.md` - - `contracts/modules.md` when present - - `README.md` - - `.specify/memory/constitution.md` - - relevant `docs/adr/*.md` +Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` once from repo root and parse JSON for `FEATURE_DIR` and `AVAILABLE_DOCS`. Derive absolute paths: -3. Build internal inventories for: - - requirements - - user stories and acceptance criteria - - task coverage - - constitution principles - - ADR / decision-memory guardrails +- `SPEC` = `FEATURE_DIR/spec.md` +- `PLAN` = `FEATURE_DIR/plan.md` +- `TASKS` = `FEATURE_DIR/tasks.md` +- `CONTRACTS` = `FEATURE_DIR/contracts/modules.md` (when present) +- `ADR` = `docs/adr/*.md` (repo-global ADR sources when referenced) -4. Detect high-signal issues only: - - duplication - - ambiguity - - underspecification - - constitution conflicts - - coverage gaps - - terminology drift - - repository-structure mismatches (e.g., Rust/MCP paths in a Python/Svelte project) - - decision-memory drift and rejected-path scheduling +Abort with an error message if any required file is missing (instruct the user to run the missing prerequisite command). -5. Produce a compact Markdown report with: - - findings table - - coverage summary table - - decision-memory summary table - - constitution alignment issues - - unmapped tasks - - metrics +### 2. Load Artifacts (Progressive Disclosure) -6. Provide next actions: - - CRITICAL/HIGH issues should be resolved before `speckit.implement` - - lower-severity issues may be deferred with explicit rationale +Load only the minimal necessary context from each artifact: + +**From `spec.md`:** +- Overview / Context +- Functional Requirements +- Non-Functional Requirements +- User Stories with acceptance criteria +- Edge Cases (when present) + +**From `plan.md`:** +- Architecture / stack choices +- Data Model references +- Phases / milestones +- Technical constraints +- ADR references or emitted decisions +- Component inventory (Svelte components, Screen Models) + +**From `tasks.md`:** +- Task IDs with checkbox status +- Descriptions and exact file paths +- Phase grouping and story labels (`[USx]`) +- Parallel markers (`[P]`) +- Inlined contract constraints (`@PRE`, `@POST`, `@SIDE_EFFECT`, `@TEST_EDGE`) +- Inlined ADR guardrails (`@RATIONALE`, `@REJECTED`) +- Referenced UX states and component names + +**From `contracts/modules.md` (when present):** +- All `#region` / `[DEF:...]` contract headers +- Complexity tiers (`[C:N]`) +- Type annotations (`[TYPE ...]`) +- Domain grouping (`@defgroup`, `@ingroup`) +- `@UX_STATE`, `@UX_FEEDBACK`, `@UX_RECOVERY` annotations +- `@UX_TEST`, `@UX_REACTIVITY` annotations +- `@RATIONALE`, `@REJECTED` decision-memory entries +- `@RELATION` edges +- `@PRE`, `@POST`, `@INVARIANT`, `@DATA_CONTRACT` entries + +**From ADR sources:** +- ADR IDs and status +- `@RATIONALE` — accepted paths +- `@REJECTED` — forbidden paths +- `@RELATION DEPENDS_ON` edges to other ADRs + +**From constitution (`.specify/memory/constitution.md`):** +- All MUST-level principles (I-VIII) +- Verification gates +- Development workflow steps + +### 3. Build Semantic Models + +Create internal representations (do NOT include raw artifacts in output): + +- **Requirements inventory**: Each functional + non-functional requirement with a stable slug key (derive from imperative phrase; e.g., "User can upload file" → `user-can-upload-file`) +- **User story inventory**: Discrete user actions with acceptance criteria +- **Task coverage mapping**: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns) +- **Constitution rule set**: Extract principle names and MUST/SHOULD normative statements +- **Decision-memory inventory**: ADR ids, accepted paths, rejected paths, and the tasks/contracts expected to inherit them +- **UX contract inventory**: Per-component map of declared `@UX_STATE` names, `@UX_FEEDBACK` mechanisms, `@UX_RECOVERY` paths, and `@UX_TEST` scenarios from both `contracts/modules.md` and `tasks.md` +- **ATTN rules snapshot**: For each contract in `contracts/modules.md`, record: anchor line count (ATTN_1), ID hierarchy depth (ATTN_2), `[SEMANTICS ...]` keywords and `@ingroup` presence (ATTN_3), estimated line count (ATTN_4) + +### 4. Detection Passes (Token-Efficient Analysis) + +Focus on high-signal findings. **Limit to 50 findings total**; aggregate remainder in overflow summary. Generate stable IDs prefixed by category initial. + +--- + +#### A. Duplication Detection + +- Identify near-duplicate requirements within `spec.md` +- Flag tasks that duplicate work across different phases without explicit dependency +- Mark lower-quality phrasing for consolidation + +#### B. Ambiguity Detection + +- Flag vague adjectives lacking measurable criteria: "fast", "scalable", "secure", "intuitive", "robust", "reliable", "performant" +- Flag unresolved placeholders: `TODO`, `TKTK`, `???`, ``, `TBD`, `TBC` +- Flag acceptance criteria without a measurable outcome (e.g., "works correctly") + +#### C. Underspecification + +- Requirements with verbs but missing object or measurable outcome +- User stories missing acceptance criteria alignment +- Tasks referencing files or components not defined in `spec.md` or `plan.md` +- Tasks lacking exact file paths (violates tasks.md generation rules) + +#### D. Constitution Alignment + +- Any requirement or plan element conflicting with a MUST principle (I-VIII) +- Missing mandated sections or quality gates from constitution +- Feature that contradicts ADR-guarded architectural decisions without `` + +#### E. Coverage Gaps + +- Requirements with **zero** associated tasks +- Tasks with **no** mapped requirement or user story +- Non-functional requirements (performance, security, RBAC) not reflected in tasks + +#### F. Inconsistency + +- **Terminology drift**: same concept named differently across `spec.md`, `plan.md`, `tasks.md` (e.g., "migration plan" vs "transfer config" vs "export bundle") +- **Entity mismatches**: data entities referenced in `plan.md` but absent in `spec.md` (or vice versa) +- **Task ordering contradictions**: integration tasks scheduled before foundational setup tasks without dependency note +- **Conflicting requirements**: two requirements that cannot both be satisfied (e.g., "no database" vs "persist user preferences") +- **Rust/MCP path contamination**: task or plan references `.rs` files, `cargo`, `src/server/`, or MCP server paths in a Python/Svelte project + +#### G. Decision-Memory Drift + +- ADR exists in `docs/adr/` with a `@REJECTED` path, but `tasks.md` schedules work implementing that rejected path +- ADR exists with a `@RATIONALE`-guarded decision, but no downstream task carries a corresponding guardrail +- Task carries a `@RATIONALE` / `@REJECTED` guardrail with no upstream ADR or plan rationale +- Decision recorded in `contracts/modules.md` (`@RATIONALE` / `@REJECTED`) is not propagated to any task in `tasks.md` +- `@REJECTED` path in `plan.md` or ADR is contradicted by later spec or task language without explicit `` decision revision + +#### H. UX Contract Traceability + +Validate Svelte component UX contracts across `contracts/modules.md` and `tasks.md`. Reference `semantics-svelte` §II (UX Contracts) and §IIIa (Reactive Screen Models). + +| # | Rule | Severity | What to check | +|---|------|----------|---------------| +| **H1** | **Missing UX Triplet** | MEDIUM (display) / HIGH (interactive) | Component contract in `contracts/modules.md` has `@UX_STATE` but is **missing** `@UX_FEEDBACK` and/or `@UX_RECOVERY`. For interactive components (forms, mutations, migrations, actions): severity HIGH. For display-only (badges, status labels): MEDIUM. | +| **H2** | **State Name Drift** | HIGH | The set of state names declared in `@UX_STATE` for a component in `contracts/modules.md` **differs** from the state names referenced in that component's task in `tasks.md`. Example: contract says `loading/loaded/error`, task says `fetching/ready/failed`. | +| **H3** | **Orphan UX Test** | MEDIUM | A `@UX_TEST` scenario references a state name that is **not declared** in the corresponding `@UX_STATE` list. Example: `@UX_TEST: Saving -> ...` but `@UX_STATE` only declares `idle/loading/loaded/error`. | +| **H4** | **Untested UX State** | MEDIUM | A state declared in `@UX_STATE` has **no** corresponding `@UX_TEST` scenario. User-facing states without test coverage create blind spots for the browser Judge Agent. | +| **H5** | **Missing UX Contract for Component** | MEDIUM | A frontend task in `tasks.md` references a Svelte component (`.svelte` file) but `contracts/modules.md` has **no** UX annotations (`@UX_STATE` / `@UX_FEEDBACK` / `@UX_RECOVERY`) for that component. | +| **H6** | **Incomplete Recovery Path** | MEDIUM | `@UX_STATE` includes error-like states (`error`, `timeout`, `network_down`, `save_error`, `lookup_error`) but `@UX_RECOVERY` is **absent or empty**. Every error state MUST have a user recovery path. | +| **H7** | **Inconsistent UX Annotation Style** | LOW | Within the same `contracts/modules.md`, UX annotations use mixed formats: some in HTML comments (``), some as bare tags (`@UX_STATE: ...`). Pick one style for the entire file. | +| **H8** | **Missing Model-First Pattern** | MEDIUM | `plan.md` describes a screen with cross-widget logic (filters affecting lists, multi-step forms, pagination with search) but `contracts/modules.md` contains **no** `[TYPE Model]` contract. Complex screens MUST use the Screen Model pattern (`semantics-svelte` §IIIa). | + +#### I. ATTN Rules Compliance + +Validate that all contracts in `contracts/modules.md` comply with the Attention Architecture rules from `semantics-core` §VIII. Contracts that violate these rules become invisible to the model after context compression — causing downstream hallucination during implementation. + +| # | Rule | Severity | What to check | +|---|------|----------|---------------| +| **I1** | **ATTN_1 — Split Anchor** | HIGH | Contract opening anchor spreads across **multiple lines**. ID, `[C:N]`, `[TYPE TypeName]`, `[SEMANTICS tags]` MUST be on ONE line. CSA 4× pooling compresses multi-line anchors into separate KV records — the contract becomes invisible. Check: `#region Id [C:N] [TYPE Type] [SEMANTICS t1,t2]` is all on ONE line. | +| **I2** | **ATTN_2 — Flat ID** | HIGH (C3+) / MEDIUM (C1-C2) | Contract ID is a single word without dot-separated domain hierarchy. After HCA 128× compression, `login_handler` is noise; `Core.Auth.Login` survives. Required: at least 2 hierarchy levels (`Domain.Name`) for C3+. For C1/C2 inside a hierarchical parent, single-level may be acceptable. | +| **I3** | **ATTN_3 — Missing Semantic Grouping** | MEDIUM | Two contracts in the same domain use **different** primary keywords in `[SEMANTICS ...]`. Example: one auth contract has `[SEMANTICS login]`, another has `[SEMANTICS authentication]` — DSA Lightning Indexer cannot group them. Also check: module has `@defgroup` but children lack `@ingroup` (or vice versa). | +| **I4** | **ATTN_4 — Boundary Overrun** | MEDIUM | Estimated contract length exceeds **150 lines** or module exceeds **400 lines**. Violates INV_7 (`semantics-core` §I) and sliding window visibility (`semantics-core` §VIII ATTN_4). Flag contracts/modules that appear to be over the limit based on content density. | +| **I5** | **Missing Complexity Tag** | CRITICAL | Contract header lacks `[C:N]` complexity tier annotation. Violates INV_1: every contract MUST have a `#region`/`#endregion` with explicit complexity. Without `[C:N]`, the semantic index cannot classify the contract. | +| **I6** | **Missing Type Tag** | HIGH | Contract header lacks `[TYPE TypeName]` annotation. The type (`Module`, `Function`, `Class`, `Component`, `Model`, `ADR`, etc.) is required for the semantic index to route relations correctly. | + +### 5. Severity Assignment + +Use this heuristic to prioritize findings: + +- **CRITICAL**: Violates constitution MUST principle, missing `[C:N]` complexity tag, missing core spec artifact, ADR-rejected path scheduled as work, requirement with zero coverage that blocks baseline functionality +- **HIGH**: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion, ADR guardrail drift, ATTN_1 split anchor, ATTN_2 flat ID (C3+), UX state name drift, missing UX triplet on interactive component +- **MEDIUM**: Terminology drift, missing non-functional task coverage, underspecified edge case, incomplete decision-memory propagation, ATTN_3/ATTN_4 violations, missing UX contract, orphan UX test, missing recovery path, missing Model-first pattern +- **LOW**: Style/wording improvements, minor redundancy, inconsistent annotation formatting + +### 6. Produce Compact Analysis Report + +Output a Markdown report (no file writes) with the following structure: + +#### Specification Analysis Report + +**Findings Table:** + +| ID | Category | Severity | Location(s) | Summary | Recommendation | +|----|----------|----------|-------------|---------|----------------| +| A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version | + +**Coverage Summary Table:** + +| Requirement Key | Has Task? | Task IDs | Notes | +|-----------------|-----------|----------|-------| + +**Decision Memory Summary Table:** + +| ADR / Guardrail | Present in Plan | Propagated to Tasks | Rejected Path Protected | Notes | +|-----------------|-----------------|---------------------|-------------------------|-------| + +**UX Contract Summary Table:** + +| Component | Has @UX_STATE? | Has @UX_FEEDBACK? | Has @UX_RECOVERY? | @UX_TEST Count | Issues | +|-----------|:---:|:---:|:---:|:---:|--------| + +**ATTN Rules Compliance Table:** + +| Contract ID | C:N | ATTN_1 (anchor) | ATTN_2 (ID) | ATTN_3 (grouping) | ATTN_4 (size) | Issues | +|-------------|-----|:---:|:---:|:---:|:---:|--------| + +**Constitution Alignment Issues:** (if any) + +**Unmapped Tasks:** (if any) + +**Metrics:** +- Total Requirements: N +- Total Tasks: N +- Coverage % (requirements with >=1 task): N% +- Total Contracts in modules.md: N +- UX Contracts with Full Triplet %: N% +- ATTN Rules Compliance %: N% +- Ambiguity Count: N +- Duplication Count: N +- Critical Issues Count: N +- ADR Count: N +- Guardrail Drift Count: N + +### 7. Provide Next Actions + +At end of report, output a concise Next Actions block: + +- If **CRITICAL** issues exist: recommend resolving before `/speckit.implement` +- If only **LOW/MEDIUM**: user may proceed, but provide improvement suggestions +- Provide explicit command suggestions: e.g., "Run `/speckit.specify` with refinement", "Run `/speckit.plan` to adjust architecture", "Manually edit `tasks.md` to add coverage for 'performance-metrics'" + +### 8. Offer Remediation + +Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.) ## Analysis Rules -- Treat stale Rust/MCP assumptions in plan/tasks as real defects for this Python/Svelte repository. -- Treat missing ADR propagation as a real defect, not a documentation nit. -- Prefer repository-real expectations (`backend/src/**/*.py`, `frontend/src/**/*.svelte`, `backend/tests/`, `frontend/src/lib/**/__tests__/`). -- Do not treat `.kilo/plans/*` as feature artifacts for consistency analysis. +- Treat stale Rust/MCP assumptions in plan/tasks as **real defects** for this Python/Svelte repository. +- Treat missing ADR propagation as a **real defect**, not a documentation nit. +- Prefer repository-real paths (`backend/src/**/*.py`, `frontend/src/**/*.svelte`, `backend/tests/`, `frontend/src/lib/**/__tests__/`). +- Do NOT treat `.kilo/plans/*` as feature artifacts. + +## Operating Principles + +### Context Efficiency + +- **Minimal high-signal tokens**: focus on actionable findings, not exhaustive documentation +- **Progressive disclosure**: load artifacts incrementally; don't dump all content into analysis +- **Token-efficient output**: limit findings table to 50 rows; summarize overflow +- **Deterministic results**: rerunning without changes should produce consistent IDs and counts + +### Analysis Guidelines + +- **NEVER modify files** (this is read-only analysis) +- **NEVER hallucinate missing sections** (if absent from artifacts, report them accurately) +- **Prioritize constitution violations** (these are always CRITICAL) +- **Prioritize ATTN_1/ATTN_2** (split anchors and flat IDs cause downstream model blindness for all implementing agents) +- **Use examples over exhaustive rules** (cite specific instances from artifacts, not generic patterns) +- **Report zero issues gracefully** (emit success report with coverage statistics) +- **Treat missing UX contract annotations as real UX debt** — every untested state is a browser-verification blind spot + +## Context + +$ARGUMENTS diff --git a/.opencode/opencode.jsonc b/.opencode/opencode.jsonc index 4538531c..f922e8ab 100644 --- a/.opencode/opencode.jsonc +++ b/.opencode/opencode.jsonc @@ -13,7 +13,7 @@ "axiom": { "type": "local", "command": ["sh", "-c","/home/busya/dev/axiom-mcp-rust-port/target/release/axiom-mcp-server-rs 2>>/tmp/axiom-server.log"], - "enabled": true + "enabled": false } } } \ No newline at end of file diff --git a/backend/src/api/routes/translate/_preview_routes.py b/backend/src/api/routes/translate/_preview_routes.py index 27ed2c58..516d35ea 100644 --- a/backend/src/api/routes/translate/_preview_routes.py +++ b/backend/src/api/routes/translate/_preview_routes.py @@ -1,6 +1,6 @@ -# #region TranslatePreviewRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, translate, preview, review, api, search] +# #region TranslatePreviewRoutesModule [C:3] [TYPE Module] [SEMANTICS fastapi, translate, preview, api] # @defgroup Api Module group. -# @BRIEF Translation Preview session management routes. +# @BRIEF Translation Preview session management routes — generate preview, fetch records. # @LAYER API @@ -13,11 +13,7 @@ from ....core.logger import logger from ....dependencies import get_config_manager, get_current_user, has_permission from ....plugins.translate.preview import TranslationPreview from ....schemas.auth import User -from ....schemas.translate import ( - PreviewRequest, - PreviewRow, - PreviewRowUpdate, -) +from ....schemas.translate import PreviewRequest, PreviewRow from ._router import router # ============================================================ @@ -61,92 +57,6 @@ async def preview_translation( # #endregion preview_translation -# #region update_preview_row [C:4] [TYPE Function] -# @ingroup Api -# @BRIEF Approve, edit, or reject a preview row (optionally per language). -# @PRE User has translate.job.execute permission. -# @POST Preview row status is updated. -@router.put("/jobs/{job_id}/preview/rows/{row_key}") -async def update_preview_row( - job_id: str, - row_key: str, - payload: PreviewRowUpdate, - current_user: User = Depends(get_current_user), - _ = Depends(has_permission("translate.job", "EXECUTE")), - db: Session = Depends(get_db), - config_manager: ConfigManager = Depends(get_config_manager), -): - """Approve, edit, or reject a preview row (optionally per language).""" - logger.reason(f"update_preview_row — Job: {job_id}, Row: {row_key}, Action: {payload.action}, Lang: {payload.language_code}", extra={"src": "translate_routes"}) - try: - preview_service = TranslationPreview(db, config_manager, current_user.username) - result = preview_service.update_preview_row( - job_id=job_id, - row_id=row_key, - action=payload.action, - translation=payload.translation, - feedback=payload.feedback, - language_code=payload.language_code, - ) - return result - except ValueError as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) -# #endregion update_preview_row - - -# #region accept_preview_session [C:4] [TYPE Function] -# @ingroup Api -# @BRIEF Accept a preview session, marking it as the quality gate for full execution. -# @PRE User has translate.job.execute permission. Job has an ACTIVE preview session. -# @POST Preview session is marked as APPLIED; full execution can proceed. -@router.post("/jobs/{job_id}/preview/accept") -async def accept_preview_session( - job_id: str, - current_user: User = Depends(get_current_user), - _ = Depends(has_permission("translate.job", "EXECUTE")), - db: Session = Depends(get_db), - config_manager: ConfigManager = Depends(get_config_manager), -): - """Accept a preview session, enabling full translation execution.""" - logger.reason(f"accept_preview_session — Job: {job_id}, User: {current_user.username}", extra={"src": "translate_routes"}) - try: - preview_service = TranslationPreview(db, config_manager, current_user.username) - result = preview_service.accept_preview_session(job_id=job_id) - return result - except ValueError as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) -# #endregion accept_preview_session - - -# #region apply_preview [C:4] [TYPE Function] -# @ingroup Api -# @BRIEF Apply a preview session (alias for accept when accepting at session level). -# @PRE User has translate.job.execute permission. -# @POST Preview is applied. -@router.post("/preview/{session_id}/apply") -async def apply_preview( - session_id: str, - current_user: User = Depends(get_current_user), - _ = Depends(has_permission("translate.job", "EXECUTE")), - db: Session = Depends(get_db), - config_manager: ConfigManager = Depends(get_config_manager), -): - """Apply a preview session by session ID.""" - logger.reason(f"apply_preview — Session: {session_id}, User: {current_user.username}", extra={"src": "translate_routes"}) - # Find job_id from session - from ....models.translate import TranslationPreviewSession - session = db.query(TranslationPreviewSession).filter(TranslationPreviewSession.id == session_id).first() - if not session: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Preview session '{session_id}' not found") - try: - preview_service = TranslationPreview(db, config_manager, current_user.username) - result = preview_service.accept_preview_session(job_id=session.job_id) - return result - except ValueError as e: - raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) -# #endregion apply_preview - - # ============================================================ # Preview Records # ============================================================ @@ -156,7 +66,6 @@ async def apply_preview( # @BRIEF Get records for a preview session. # @PRE User has translate.job.view permission. # @POST Returns list of preview records. -# @COMPLEXITY 4 @router.get("/preview/{session_id}/records", response_model=list[PreviewRow]) async def get_preview_records( diff --git a/frontend/src/lib/components/assistant/MarkdownRenderer.svelte b/frontend/src/lib/components/assistant/MarkdownRenderer.svelte index 57148d5a..2cf5510f 100644 --- a/frontend/src/lib/components/assistant/MarkdownRenderer.svelte +++ b/frontend/src/lib/components/assistant/MarkdownRenderer.svelte @@ -1,12 +1,12 @@ - + - + @@ -18,7 +18,7 @@ {/if}