Commit Graph

766 Commits

Author SHA1 Message Date
9f9ac07cac fix(agent): copy src/core/logger.py and ws_log_handler.py into agent image
run.py imports from src.core.logger which requires logger.py and its
dependency ws_log_handler.py. Previously only cot_logger.py was copied.
2026-07-06 11:35:12 +03:00
628805503b refactor(docker): split requirements by role, slim enterprise bundle by default
Split requirements.txt into role-specific files:
  - requirements-backend.txt — FastAPI API runtime
  - requirements-agent.txt — Gradio/LangGraph agent (no embeddings)
  - requirements-embeddings.txt — opt-in sentence-transformers

Default enterprise bundle (./build.sh bundle) builds slim agent without
sentence-transformers/torch (~500 MB saved). Embeddings opt-in via
./build.sh bundle:embeddings <tag>. Embedding router degrades gracefully
when package is absent (ImportError catch in _embedding_router.py).

Updated Dockerfiles:
  - backend.Dockerfile → requirements-backend.txt
  - Dockerfile.agent → requirements-agent.txt + WITH_EMBEDDINGS build arg
  - all-in-one.Dockerfile → requirements-backend.txt

Added embeddings variant to build.sh with full manifest/digest output.
Hardened .dockerignore (cache, report, model, archive patterns).

Other branch work: align git route mocks with async services, remove
legacy agent test files superseded by contract tests.
2026-07-06 10:06:07 +03:00
1586c31d9b chore: причесать .env.example — удалить дубликаты и мёртвые vars
- backend/.env.enterprise-clean.example — удалён (точная копия root)
- .env.enterprise-clean.example — очищен от мёртвых OPENAI_API_KEY,
  ANTHROPIC_API_KEY, добавлен пример Fernet-ключа
- docker/.env.agent.example — переписан под новую архитектуру:
  убраны LLM_*, JWT_SECRET (больше не читаются агентом),
  добавлен AUTH_SECRET_KEY
2026-07-06 08:55:11 +03:00
57b7ee05e0 test(git): align route mocks with async services 2026-07-06 01:23:20 +03:00
1e56416c9f test(backend): update legacy agent and auth expectations 2026-07-06 01:23:09 +03:00
28cd141e76 feat(reports): add task status settings and tests 2026-07-06 01:22:39 +03:00
99bbdb4398 docs(agent-chat): update 035 verification traceability 2026-07-06 01:22:07 +03:00
082d6af3ab test(agent-chat): audit guardrail and error handling 2026-07-06 01:20:12 +03:00
49e4ac0fe2 refactor(frontend): integrate compact filters into reports page
- Rename page title "Отчеты задач" → "Центр статусов"
- Remove standalone quick-status filter block (moved to FilterBar)
- Remove inline filter/sort/time-range HTML (replaced by FilterBar)
- Replace statusTotal() with  quickStatusCounts
- Pass quickStatusCounts and onQuickStatusToggle to FilterBar
- Error recovery button text "Повторить" → "Повторить загрузку"
2026-07-05 15:50:51 +03:00
86ac209615 feat(frontend): compact FilterBar with disclosure toggle and quick pills
- Quick status pills (Упавшие/В работе/Успешные) always visible
- Search input with flex spacer in same row
- Explicit "Фильтры" disclosure button with filter icon, badge count, chevron
- aria-expanded / aria-controls for accessibility
- Expandable panel: type, status, time range, sort controls
- Remove bottom status bar ("Показано X из Y", "Активно фильтров")
- Update tests for expanded state and quick pill interactions
2026-07-05 15:50:46 +03:00
95308273b3 refactor(frontend): replace raw buttons with /ui/Button in SummaryPanel
- Replace raw <button> with <Button variant="ghost">
- Dim zero-count badges with opacity-50
- Add transition-colors duration-300 to count numbers
- Replace inline reconnect link with themed <Button>
2026-07-05 15:50:41 +03:00
c75017f1e4 fix(frontend): prevent TaskList horizontal overflow
- Add min-w-0 overflow-hidden to TaskList shell container
- Add filtered_empty UX state to contract
- Update layout contract test to verify TaskList source directly
- Add transition-colors to status badges
2026-07-05 15:50:36 +03:00
147d711657 feat(agent-chat): complete context guardrail event coverage 2026-07-05 14:14:42 +03:00
45e781fb74 chore: commit remaining working changes
Backend:
- agent: confirmation, persistence, app, langgraph_setup updates
- routes: agent_superset_explore, environments, git helpers/operations
- services: git sync refactoring
- tests: git_status_route expanded

Frontend:
- Navbar: minor cleanup
- Profile: i18n (en/ru), page enhancements, integration tests
- New: _llm_params.py
2026-07-05 09:24:45 +03:00
b773a06d52 refactor(frontend): extract BulkReplaceModal.Model — state + FSM + API
- BulkReplaceModalModel.svelte.ts (170 LOC): 13 state atoms,
  7-state FSM (closed→configuring→previewing→confirming→applying→applied),
  3 API actions (handlePreview, handleApply, loadDictionaries),
  1 derived (isLargeChange), @RATIONALE/@REJECTED
- BulkReplaceModal.svelte: 461→~310 LOC (INV_7 compliance),
  delegates all state/FSM/API to model, retains modal chrome + previewAfter()
- Follows TopNavbar/TranslationRunResult pattern
2026-07-05 09:21:49 +03:00
a91023d83e fix(frontend): fix Svelte prop shorthand in TranslationRunResult
{model.targetLanguages} is invalid shorthand — Svelte only supports
bare identifiers, not property access. Changed to explicit
targetLanguages={model.targetLanguages}
2026-07-05 09:17:33 +03:00
97660cb71f refactor(frontend): extract TranslationRunResult.Model — state + API logic
- TranslationRunResultModel.svelte.ts (200 LOC): 16 $state atoms,
  3 $derived projections, 5 API actions (loadData, handleRetry,
  handleRetryInsert, loadMoreRecords, loadBatches), @RATIONALE/@REJECTED
- TranslationRunResult.svelte: 623→456 LOC (167 lines saved, -27%),
  delegates all state/API to model, retains template markup and
  DOM helpers (copyToClipboard)
- INV_1: 0 naked functions (all logic in model)
- Follows TopNavbar pattern — dense anchor, hierarchical ID,
  BINDS_TO -> [TranslationRunResult.Model]
2026-07-05 09:16:32 +03:00
669d8185f3 refactor(frontend): add @RATIONALE/@REJECTED to 5 C:4 contracts
- ConfigTabForm: rationale for single-tab vs wizard; rejected multi-step
- ValidationTaskForm: rationale for multi-step wizard; rejected flat form,
  tabs, dynamic schema generation
- GitWorkspacePanel: rationale for IntersectionObserver lazy diff chunking;
  rejected virtual scroll, server pagination, Web Worker
- Git.ManagerModel: rationale for model-first (cross-operation invariants,
  L1 testability); existing @REJECTED preserved
- AgentChat.Component: rationale for reusable component vs inline;
  rejected Web Component, iframe
2026-07-05 09:00:08 +03:00
deed06fada refactor(frontend): remove @PURPOSE duplicates, merge into @BRIEF (INV_4)
- ProviderConfig: remove duplicate @LAYER/@PURPOSE/@UX_STATE block
- SemanticLayerReview: generic @BRIEF → detailed @PURPOSE text,
  remove duplicate @LAYER/@SEMANTICS
- ExecutionMappingReview: same — generic @BRIEF → @PURPOSE detail
- TaskRunner: remove duplicate @SEMANTICS/@PURPOSE/@LAYER block
- ValidationFindingsPanel: generic @BRIEF → @PURPOSE detail,
  remove duplicate @LAYER/@SEMANTICS

All: INV_4 compliance — single source of truth for contract metadata
in #region HTML comment, no scattered duplicates
2026-07-05 08:54:38 +03:00
008a8a92a5 refactor(frontend): clean metadata on AssistantChatPanel + TaskDrawer
- AssistantChatPanel: C:3→C:4 (33 side-effecting functions), remove JSDoc
  duplicates (INV_4), add @PRE/@POST/@SIDE_EFFECT/@DATA_CONTRACT/@RATIONALE/@REJECTED
- TaskDrawer: remove JSDoc duplicates (INV_4), replace 4x @PURPOSE
  JSDoc blocks with @BRIEF/@PRE/@POST in function contracts (INV_4),
  add @RATIONALE/@REJECTED
- Both: consolidate all metadata in HTML comment #region, remove
  scattered JSDoc in <script>
2026-07-05 08:53:17 +03:00
bc3e288d0b refactor(frontend): extract TopNavbar.Model — search logic, semantic compliance
- Extract TopNavbarModel.svelte.ts (303 LOC) — search state, debounce,
  API aggregation, drawer preference hydration
- TopNavbar.svelte: 605→389 LOC (INV_7 compliance)
- Remove duplicate JSDoc metadata (INV_4)
- Add @RATIONALE, @REJECTED, @PRE, @POST, @SIDE_EFFECT, @DATA_CONTRACT
- Replace raw Tailwind (from-sky-500/via-cyan-500/to-indigo-600 →
  from-brand-gradient-from/via-brand-gradient-via/to-brand-gradient-to)
- Replace raw Tailwind focus:ring-sky-200 → focus:ring-primary-ring-light
- Fix hardcoded i18n 'Ассистент' → $t.assistant.assistant
- Add primary.ring-light token to tailwind.config.js
- Replace any types with concrete interfaces (DashboardSearchResult, etc.)
- 16 naked functions → 0 (INV_1)
2026-07-05 08:50:43 +03:00
ff60865183 feat(agent-chat): 035-agent-chat-context — контекст, guardrails, tools, database discovery
== User stories ==
US1: Контекст с дашборда/датасета → /agent с URL params
US2: Guardrails card — env badge, 7 risk tones, countdown, permission_denied
US3: Tools optimization — retry, timeout, summarise, RBAC + context affinity

== Backend ==
- _context.py (NEW): UIContext validation (7 checks)
- _tool_filter.py (NEW): RBAC + context affinity pipeline
- _confirmation.py: build_confirmation_contract_v2, permission_denied_payload
- tools.py: superset_list_databases, retry/summarise/timeout wrappers
- app.py: _inject_uicontext, _inject_env_id_into_tools, database
  prefetch в runtime context
- _persistence.py: prefetch_databases()
- agent_superset_explore.py: GET /databases endpoint
- _llm_async_http.py, _persistence.py: fix double /v1 в LLM URL
  (LM Studio Unexpected endpoint)

== Frontend ==
- AgentChatModel.svelte.ts: 5 atoms, 3 actions, countdown, context
- AgentChat.svelte: production banner, process steps, debug panel
- ConfirmationCard.svelte: 7 risk tones, permission_denied, countdown
- ToolCallCard.svelte: retrying/timeout/cancelled states
- StreamProcessor.svelte.ts: tool_retry, timeout, permission_denied
- TopNavbar: sparkles icon + Ассистент
- sidebarNavigation: AI section
- DashboardHeader, datasets/+page: contextual AI buttons
- Icon: sparkles, brain, cpu icons
- tailwind: assistant category colors
- i18n: en/ru nav keys

== Tests ==
- 159 backend agent tests (+16 US3: retry, timeout, summarise, contracts)
- 2544 frontend tests (+11 model + component tests)
- 15 JSON fixtures (10 API + 5 model)

== Specs ==
- specs/035-agent-chat-context/: spec, UX, plan, tasks, research,
  data-model, contracts, quickstart, traceability, fixtures, checklists

Closes #035
2026-07-04 22:47:17 +03:00
4c5fde8b5c chore(kilo): sync OpenCode config into Kilo format 2026-07-04 22:43:17 +03:00
1f502c9785 docs(readme): add SSL/TLS configuration section with passphrase and PKCS#12 options 2026-07-04 17:10:04 +03:00
1c6b3d6e8a feat(ssl): add passphrase-protected key and PKCS#12 support in nginx entrypoint
- docker/frontend.entrypoint.sh: add 3 new functions:
  - extract_p12_if_needed — openssl pkcs12 extraction to .crt+.key
  - resolve_ssl_passphrase — read SSL_KEY_PASSPHRASE env var
  - decrypt_key_if_needed — openssl rsa decryption before nginx start
- Pipeline: install CA -> extract p12 -> get passphrase -> select config -> decrypt key -> start nginx
- Crash-early: encrypted key without SSL_KEY_PASSPHRASE exits entrypoint
- docker-compose.enterprise-clean.yml: add SSL_KEY_PASSPHRASE to frontend env
- .env.enterprise-clean.example: document SSL_KEY_PASSPHRASE usage
- build.sh: add SSL_KEY_PASSPHRASE to generated deploy compose
2026-07-04 17:05:51 +03:00
047aff41d9 Task Status Center: save progress 2026-07-04 15:34:02 +03:00
61f3e6db75 feat: Git manager UI — панель управления Git + HelpTooltip + ReviewToggle
- GitManager: переработан в GitWorkspacePanel с вкладками
- Добавлен GitLifecycleHeader с быстрыми действиями
- RepositoryDashboardGrid: поддержка ReviewToggle, badges, env filter
- HelpTooltip: универсальный компонент подсказок с тестами
- GitManagerModel: доработаны экшены, добавлен isReady, loadDefaultBranch
- Локализация en/ru для Git UI
- tailwind: добавлен animation-delay-200
- ConfirmDialog: a11y-атрибуты для кнопок
2026-07-04 15:01:45 +03:00
0237e2f7e8 chore: добавить пример Fernet-ключа в .env.example
- Сгенерированный пример ENCRYPTION_KEY с командой для генерации
- Пометка 'сгенерируйте свой для прода'
2026-07-04 15:01:23 +03:00
b78493aeb7 chore: добавить примеры значений в .env.example
- backend/.env.example — пример DATABASE_URL с комментарием
- root/.env.example — заполнены примеры для всех переменных
  (AUTH_SECRET_KEY, DATABASE_URL, INITIAL_ADMIN_PASSWORD, POSTGRES_PASSWORD)
2026-07-04 14:59:39 +03:00
ec9bc76a37 cleanup: убрать мёртвые env-переменные, консолидировать чтение в agent/_config.py
Удалены из кода:
- JWT_SECRET — мёртвая (decode_token использует AUTH_SECRET_KEY)
- SESSION_SECRET_KEY — заменён на прямой AUTH_SECRET_KEY
- POSTGRES_URL — deprecated fallback, удалён из database.py и reencrypt.py

Консолидировано чтение env-переменных agent-модуля:
- Создан agent/_config.py — единый модуль для FASTAPI_URL,
  SERVICE_JWT, GRADIO_*, STORAGE_ROOT, AGENT_* (9 констант)
- Все agent/*.py импортируют из _config вместо разрозненных os.getenv

Удалены or-дефолты (безопасность):
- agent/langgraph_setup.py — удалён hardcoded DB URL postgres:postgres
- agent/langgraph_setup.py — удалены fallback API URL и model name
- scripts/reencrypt.py — удалён hardcoded DB URL postgres:postgres
- plugins/llm_analysis/service.py — удалены or-дефолты URL/app name

.env.example — минимализация:
- backend/.env.example: только 4 обязательные переменные
- root/.env.example: обязательные + docker + SSO/админ

Обновлены тесты (139 passed)
2026-07-04 14:58:43 +03:00
a99c1d6d01 Improve agent UX and spec sync 2026-07-03 16:47:10 +03:00
500491c281 test(tls): add encrypted (passphrase-protected) private key integration tests
- ca_chain fixture: add server_key_encrypted (BestAvailableEncryption) +
  server_key_passphrase to returned dict; existing fields unchanged
- TestEncryptedPrivateKey: 6 new tests covering
  - ssl.SSLContext.load_cert_chain() with correct/wrong/missing passphrase
  - asyncio SSL server end-to-end with encrypted key + full chain trust
  - openssl rsa -check with wrong/missing passphrase (CLI validation)
- All 6 tests pass; 14/14 in test_superset_tls_custom_ca.py
2026-07-03 16:46:12 +03:00
89b340c64f fix(agent): debug panel copyDebugInfo — full state snapshot (was 9 fields, now all model atoms)
Previously copyDebugInfo() only exported 9 hand-picked fields
(conversation_id, thread_id, connection/streaming state, user, env,
message count, truncated tool calls, error). The debug panel was
missing LLM health (status, retry, banner), confirmation/HITL state
(pending_tool, args, risk), queue position, message previews, full
tool call objects, and UI flags (sidebar, debug panel, cancelled).

Now:
- Full model  snapshot with all fields
- active_tool_calls_full — complete ToolCall objects
- last_message_preview — first 200 chars of last message
- LLM status, banner dismiss, retry countdown
- HITL confirmation state (pending_tool_name, args, risk, level)
- Conversations count, queue position, user_cancelled flag
- Visual debug panel grid: 5-column layout with new rows for
  LLM health, confirmation, queue, sidebar, convs_count
2026-07-03 15:35:22 +03:00
53eb2b1cca Improve reports UI and task drawer UX 2026-07-03 14:50:05 +03:00
33ee976c48 feat(reports): Task Status Center — unified /reports dashboard
Страница /reports трансформирована в Центр статусов задач:

Backend:
- GET /api/reports/summary — агрегированные счётчики тип×статус (5 корзин)
- GET/PUT /api/settings/reports — глобальные настройки отчётов
- _filter_tasks_by_rbac() — row-level фильтрация по роли
- normalize_task_report: LLM-валидация с ошибками → FAILED/PARTIAL
- get_summary(): 5 корзин pending/running/awaiting_input/success/failed

Frontend:
- TaskCenterModel.svelte.ts (400 строк) — Screen Model
- SummaryPanel — сводная панель с цветовым кодированием и active filter
- ReportCard — humanized labels, duration, task_id, failed border
- FilterBar — search + sort + time range с label'ами
- Pagination — showingText, уникальные id для select
- Quick views: «Упавшие», «В работе», «Успешные»
- TaskDrawer: scroll-to-error, footer скрыт для terminal, «Н/Д» fix

Тесты: 48 backend + 38 frontend (2521 всего)
Build:   Console errors: 0
2026-07-02 18:53:58 +03:00
8c10632494 feat(semantic): curator-driven protocol hardening — decision memory + relation repair
- Add @RATIONALE/@REJECTED to 103+ C4/C5 contracts across backend core, services, API routes, and frontend models
- Fix 109 unresolved @RELATION edges (Auth.*, SupersetClient.*, AgentChat.*, ADR cross-refs)
- Add 13 @ingroup tags for DSA/HCA attention grouping
- Repair 29 stale graph edges via index rebuild
- Update .kilo agent prompts and skills for GRACE-Poly v2.6 compliance
- Git integration: merge routes, branch lifecycle, remote providers, UX components
- 0 broken anchor pairs, index rebuilt with 0 parse warnings
2026-07-02 08:53:19 +03:00
64564da988 fix(git): fix 17 missing async/await bugs + UX overhaul
Backend:
- fix 17 missing 'await' in git route handlers causing silent no-ops
  (branches, diff, history, commit, push, pull, merge, promote, sync)
- fix async coroutine passed to run_blocking in git_plugin.py

Frontend:
- add collapsible 'How it works' onboarding (GitHelpPanel)
- add status legend with color-coded repository statuses
- i18n: add 50+ missing keys, replace hardcoded strings
- add Refresh button in modal header
- add PROD deploy confirmation dialog (replaces browser prompt())
- add CommitHistory to workspace tab with timeline nodes
- add post-commit success banner with next-step guidance
- increase success toast duration to 8s
- group local/remote branches in selector (optgroup)
- format last_modified dates timezone-aware
- change PROD badge from red to neutral indigo
- extract shared resolveGitStatusToken to git-utils.ts
- fix 'slug' label regression
- remove dead init_repo_button key

UI/UX audit fixes:
- add descriptions to Create/Init buttons in init panel
- add actionable CTA to server mismatch warning
- improve checkbox text phrasing
2026-07-01 20:47:25 +03:00
7613ad37ae fix(agent): minimal safety net, zero-config router, LLM provider status UI
- Remove deterministic intent matching (keyword lists, infer_tool,
  fast_confirmation, negation guard, classification sets)
- Embedding descriptions auto-generated from tool docstrings
- LLM provider health endpoint GET /api/agent/llm-status
- 3 error codes: LLM_PROVIDER_UNAVAILABLE, LLM_TIMEOUT, LLM_AUTH_ERROR
- Frontend banner with auto-retry 30s + input disable
- i18n for LLM status messages (assistant.json ru/en)
- 138 passing backend tests
2026-07-01 16:47:21 +03:00
12118ac4ec fix(security): resolve Critical+High findings from module audit — agent, translate, superset_client
P0 — CRITICAL (CWE-798): JWT_SECRET crash-early
  Replace hardcoded super-secret-key fallback with os.environ["JWT_SECRET"]
  and ${JWT_SECRET:?} syntax in app.py + docker-compose files

P1 — HIGH: Frontend dependency CVEs
  Upgrade svelte 5.43.8 → 5.56.4 — resolves devalue DoS (GHSA-g2pg-6438-jwpf)
  and svelte XSS (GHSA-crpf-4hrx-3jrp, GHSA-m56q-vw4c-c2cp, GHSA-rcqx-6q8c-2c42)

P2 — MEDIUM: Logging hygiene + contract gaps + tool resolver refactor
  Apply _redact_sensitive_fields() in middleware + event streaming
  Truncate LLM error body to 100 chars
  Add @RATIONALE/@REJECTED to HandleResume + SaveConversation
  Refactor deterministic intent matching → LLM-driven tool resolution

P3 — LOW: Translate logging hardening
  Move _sanitize_url() to _utils.py (shared, no circular imports)
  Sanitize base_url before logging in _llm_call.py and _llm_async_http.py
  Emit EXPLORE warning when LLM_SSL_VERIFY=false disables TLS

superset_client module: passed clean — no changes needed
2026-07-01 13:17:29 +03:00
1e24452b1a chore(opencode): remove closure-gate agent; swarm-master emits summary itself
Eliminates closure-gate as a separate subagent. Swarm-master now
performs the closure audit and emits the user-facing summary
directly per a new SELF-CLOSURE CONTRACT (§VIIa):

- audit_contracts to verify no broken contracts post-implementation
- audit_belief_protocol to verify C5 contracts have @RATIONALE/@REJECTED
- read_events to check for runtime errors
- Noise reduction (raw dumps, browser transcripts suppressed)
- One closure summary: Applied | Verified | Remaining | Decision
  Memory | Next Action

Also fixes pre-existing anchor corruption in swarm-master.md
(duplicate #endregion at file tail) per semantics-contracts §VIII.

Files changed:
- Deleted: .opencode/agents/closure-gate.md
- Deleted: .agents/agents/closure-gate.md
- Modified: .opencode/agents/swarm-master.md
- Modified: .agents/agents/swarm-master.md
2026-07-01 12:37:28 +03:00
e174c11d4a tasks 033 updated 2026-06-30 19:05:17 +03:00
f1810090b6 feat(opencode): add security-auditor agent + /security.audit command
Read-only security audit tooling aligned with GRACE-Poly v2.6 and
axiom MCP scan capabilities. Combines code+secrets (S1–S3),
supply-chain (S4), and runtime/config (S5–S7) projections into a
single severity-ranked report with OWASP/CWE references.

Agent: .opencode/agents/security-auditor.md
- mode: all, edit: deny (hard read-only contract)
- 7 orthogonal projections with pattern catalogs for secrets, Python
  SAST, Svelte/TS SAST, dependency audit, config/runtime, contract
  coverage, and logging hygiene
- Maps findings to CVSS v3.1 severity bands, CWE, and OWASP Top 10
- Mirrors qa-tester P1–P7 anti-loop protocol for [ATTEMPT: N] ladder
- Anti-corruption §VIII: tooling absence is reported as Info finding,
  never silently dropped

Command: .opencode/command/security.audit.md
- Dispatches security-auditor subagent via axiom MCP scan
- Supports --floor, --profile, --ci (exit code 0/1/2 for CI gates)
- PCAM worker packet contract; severity floor + suppression footer

Mirrored to .agents/agents/ and .agents/commands/ per repo convention.
2026-06-30 18:44:52 +03:00
e40724a0fe fix: timezone handling across fullstack — UTC parsing + display in configured TZ
Root cause: backend returned naive ISO datetimes (no Z/offset) → JS parsed them as
browser local time → 3h drift for MSK users → '3ч' instead of 'только что'.

Backend:
- schemas/agent.py: add field_serializer('Z' suffix) for ConversationItem.updated_at
  and MessageItem.created_at — naive datetimes serialized as UTC
- routes/agent_conversations.py: datetime.utcnow() → datetime.now(timezone.utc) (3x)

Frontend:
- New: stores/timezone.svelte.ts — global reactive appTimezone store
- dateFormat.ts: add parseDateUTC() (appends 'Z' to naive ISO), all format*()
  functions now use parseDateUTC + { timeZone: appTimezone.current }
- ~25 files: replace new Date(apiString) → parseDateUTC(apiString),
  add timeZone: appTimezone.current to toLocaleString()/toLocaleDateString()
- SystemSettings.svelte + HealthCenterModel sync appTimezone to global store
- ConversationList.svelte: fix relativeTime() and date grouping (the '3ч' bug)

Verified: backend schema test, frontend 2501 tests pass, build succeeds,
browser validation on /agent and /settings.
2026-06-30 18:11:42 +03:00
60674c8639 fix(logging): defensive trace_id seed + falsy error/payload in CotJsonFormatter
log_requests middleware (BaseHTTPMiddleware) showed no-trace
because anyio.create_task_group() in Starlette 0.50.0 does not
always propagate ContextVar from raw ASGI TraceContextMiddleware.

Fix 1: defensive get_trace_id() check at log_requests entry —
        if empty, seed_trace_id() to ensure every request has one.

Fix 2: CotJsonFormatter used 'if error:' and 'if payload:' which
        silently drop empty strings (str(e)='') and empty dicts.
        Changed to 'is not None' checks — preserves all data.

Root cause: 12 EXPLORE-without-error entries from belief_scope's
exception handler where Exception() has empty message.
2026-06-30 17:41:13 +03:00
2f238dee13 fix(agent): seed trace_id for agent process lifecycle
Agent logs had trace_id='no-trace' because the Gradio process
never called seed_trace_id(). The CotJsonFormatter reads trace_id
from ContextVar — without seeding, it defaults to empty string
displayed as 'no-trace'.

Fix:
- app.py: seed_trace_id() on every agent_handler invocation
- run.py: seed_trace_id() on agent startup (for LLM config fetch)

Each Gradio submit gets a fresh trace_id, making agent logs
correlatable with downstream FastAPI calls.
2026-06-30 17:33:21 +03:00
79d0f8f678 feat(agent-superset): extend SupersetClient with agent-critical methods + DDL/DML guard + tests (126 passed)
Ported from mcp-superset research module, integrated into existing async SupersetClient:

New mixins (4 files):
- safety.py: DDL/DML guard (13 keywords), comment/string stripping, viz_type validation
- _sql_lab.py: execute_sql, format_sql, results, estimate, CSV export, query history
- _saved_queries.py: saved queries CRUD (5 methods)
- _audit.py: permissions audit matrix (user × dashboard × dataset × RLS)

Extended mixins (4 files):
- _dashboards_write.py: +create, +update (general), +copy, +publish, +unpublish
- _dashboards_crud.py: +standalone get_dashboard_charts/datasets, +get_dashboard
- _datasets.py: +create, +delete, +duplicate, +refresh_schema, +get_or_create, +export/import
- _databases.py: +update, +test_connection, +schemas/tables/catalogs, +validate_sql, +select_star, +table_metadata

FastAPI proxy (2 files):
- agent_superset.py (284L): SQL Lab + Dashboards/Datasets write endpoints
- agent_superset_explore.py (240L): DB explore + Audit + Saved Queries endpoints

Agent tools (2 files):
- tools.py: +7 LangChain @tools (24 total), intent-routing keywords
- _tool_resolver.py: updated SAFE/GUARDED/FAST_CONFIRM classification sets

Tests (3 files, 126 tests):
- test_superset_safety.py (51): DDL/DML bypass/legitimate/safe scenarios
- test_superset_extended.py (42): all mixin methods with mock AsyncAPIClient
- test_superset_tools.py (33): agent tool registration, intent matching, @tool .ainvoke()
2026-06-30 17:26:51 +03:00
a0619ca049 fix(agent): unify logging API + add molecular-cot coverage to agent module
Phase 1 — API unification:
- Replace direct log() from cot_logger with canonical logger.reason/reflect/explore
  across _confirmation.py, _persistence.py, _tool_resolver.py, app.py

Phase 2 — Gap filling:
- tools.py: add REASON/REFLECT/EXPLORE to 17 C3 tool functions (was 0 logs)
- app.py agent_handler (C4): add lifecycle REASON on entry, REFLECT on exit,
  EXPLORE on OutputParserException + general exception
- langgraph_setup.py create_agent (C4): add REASON with model/config_source,
  EXPLORE on env-var/InMemorySaver fallback, REFLECT on graph compilation
- _tool_resolver.py infer_tool_from_text (C3, 13 branches): REASON on inference
- _persistence.py: REFLECT on save_conversation success, EXPLORE on prefetch

Phase 3 — Plain log migration:
- middleware.py: plain logger.info() -> logger.reason()
- run.py: 7 plain logger.info/warning/error -> molecular REASON/EXPLORE

Phase 4 — Cleanup:
- cot_logger.py: deprecate MarkerLogger (@DEPRECATED + @REPLACED_BY)
- molecular-cot-logging SKILL.md: remove cot_span Section IV (never implemented),
  renumber sections V-VII -> IV-VI, add cot_span rejection rationale

Verification: pytest 27/27, axiom rebuild 5844/2993/0 warnings
2026-06-30 15:48:46 +03:00
131c7cdfa4 chore: remaining pre-existing changes (storage, stream processor, tests, run.sh) 2026-06-30 15:21:15 +03:00
3b4ac807a5 feat(agent+ui): fullstack agent module refactoring + UI/UX improvements
## Backend: agent module GRACE-Poly compliance
- Split app.py (749→~280 lines) into _tool_resolver, _confirmation, _persistence
- All 18 naked functions wrapped in #region/#endregion contracts
- Fixed @DEFGROUP→@defgroup typos; added @DATA_CONTRACT, @SIDE_EFFECT, CoT logs
- Conversation list API: added last_role, has_tool_calls, has_error, risk_level fields
- Message state detection: Russian/English error patterns (недоступен, unavailable)
- State field preserved in save_conversation messages
- HITL titles: descriptive tool names instead of generic "HITL resume"

## Backend: conversation title generation (two-layer)
- Layer 1: clean_title() — rule-based, strips file markers, pre-fetch blocks, JSON/CSV,
  URLs, code; truncates at 80 chars word boundary (25 unit tests, all edge cases)
- Layer 2: generate_llm_title() — async best-effort LLM titling via /v1/chat/completions
  with per-conversation lock, graceful degradation on failure

## Frontend: conversation list indicators (orthogonal system)
- Status dot (green/yellow/red/blue) per conversation state
- Icon column: tool activity, errors, waiting, completed
- Risk stripe (left border accent) + message count badge + relative time
- Fixed group labels: "Сегодня"/"Вчера" instead of "3 ч"/"5 ч"
- Hide "Окружение: —" when env is empty

## Frontend: guardrails card verification + fixes
- Confirmed all interaction modes: Enter/click confirm, Escape/click deny
- Auto-populate envId from environmentContextStore in DashboardDetailModel
- Better error message: missing_context_hint with recovery guidance

## Design system: semantic tokens
- Added category-* gradient tokens to tailwind.config.js
- Sidebar + Breadcrumbs use semantic tokens (10 categories)
- Raw Tailwind reduced from ~50 to 6 occurrences
- Added skip-to-content link in root layout (+layout.svelte)
- Added aria-label on DashboardDataGrid row checkboxes

## Protocol: INV_7 pragmatic exception
- Modules may exceed 400 lines when contract-dense (every function has #region)
- Recorded in semantics-core SKILL.md with rationale

Total: 5841+ contracts, 2993+ edges, backend 41/41, frontend 2501/2501
2026-06-30 15:21:05 +03:00
e8d6d7d0db fix(agent): critical agent chat bugs — backend startup & frontend streaming state
Backend (tools.py):
- Add Python docstrings to all 17 @tool functions (LangChain ValueError)
- Add @INVARIANT ADR: docstring requirement documented in module header
- Fix 2 f-string escaped-quote syntax errors (Python 3.13)

Frontend — compile errors (+page.svelte):
- Fix mismatched <button>/</Button> tags
- Fix missing Button import for mobile sidebar close

Frontend — streaming state loss on conversation switch (AgentChatModel):
- Add _commitStreamingPartial() helper — saves in-progress text before cancelling
- selectConversation() commits partial text to OLD conversation before switching
- createConversation() commits partial text before clearing state
- loadHistory() sets _userCancelled=true to suppress fallback messages

Frontend — ConnectionManager:
- Pass error reason through onDisconnectedPermanent callback → model.error

Frontend — null safety:
- Guard _client.submit() calls against null _client in _sendNow and resumeConfirm
2026-06-30 13:25:28 +03:00