Skip to content

Latest commit

 

History

History
71 lines (61 loc) · 22.8 KB

File metadata and controls

71 lines (61 loc) · 22.8 KB

Backlog — Registro de débitos resolvidos (histórico)

Histórico cronológico das dívidas técnicas eliminadas. Detalhes condensados — git log + commits + CHANGELOG têm a história completa. Separado do BACKLOG.md (que mantém só aberto + won't-fix + permanente) pra reduzir overhead em sessões LLM. Este arquivo não precisa ser lido por agentes salvo quando a pergunta for "já resolvemos X?" ou similar. Última atualização: 2026-05-12.

Pareamento com ROADMAP-HISTORY.md (2026-05-13):

  • BACKLOG-HISTORY.md (este) = one-liners cronológicos de débitos resolvidos, por mês. Granular pra dívida específica (data + raiz + commit). Pergunta típica: "esse bug já foi resolvido? quando?"
  • ROADMAP-HISTORY.md = arqueologia narrativa de decisões/slices/design docs. Pergunta típica: "qual era a discussão Ângulo A vs B antes do framework unificado?"
  • CHANGELOG.md = mudanças por release, público externo. Pergunta típica: "o que mudou na release 0.7.0?"
  • Os 3 são complementares, não sobrepostos.

2026-05 (parquet-lazy + smart codes + tabular virtual cols + hardening pré-submissão)

  • Smart Codes — leaf textContains + cache invalidation via vault.on('modify') (2026-05-12, noite) — 11º leaf do predicate AST (filtra markers cujo texto pesquisável contém substring, case-insensitive default + opt-in caseSensitive). Resolve item gated "Smart Code cache hash-based invalidation" sem precisar de hash: invalidação file-level via SmartCodeCache.invalidateForFileText(fileId) wired no vault.on('modify') existente (que já era usado pra sourceHashRegistry.recompute + markerTextCache). dependencyExtractor ganha flag needsText. Helper getMarkerSearchableText em markerResolvers resolve texto por engine (markdown/pdf via marker.text, csv via markerText, image via shapeLabel, audio/video via markerLabel). QDPX/Tabular transparente (predicateSerializer é JSON-genérico). Markdown in-Obsidian já era coberto via applyMarkerMutationvault.on('modify') é rede de segurança pra mudança de texto que não passe por marker mutation (edição externa, futuras engines). +13 testes (3456 → 3469). Smoke real verde via scripts/seed-smoke-text-contains.mjs. Lição arquitetural: hash-based invalidation era over-engineering pro caso real — primitiva mais leve resolve quando a edição passa pelo vault. Hash permanece justificado pra outros consumers (cross-vault remap, rename detection, dedup) onde a primitiva foi entregue em Slice 2.
  • LazyTextFilter active indicator restaurado (2026-05-12) — dot/badge roxo do tema Quartz no header da coluna filtrada não aparecia desde 0.4.2 (regressão do LazyTextFilter custom em src/csv/duckdb/lazyTextFilter.ts). Causa-raiz: built-in filter chama params.filterChangedCallback() que internamente roda setColFilterActive(col, isActive, ...) no FilterManager — esse método dispatcha 2 eventos na column (filterActiveChanged + filterChanged) que header cell e filter button escutam respectivamente. Custom filter pula esse path (justamente pra não disparar purgeInfiniteCache que causa flash branco — razão de existir do filter), então flags column.filterActive e classes .ag-header-cell-filtered/.ag-filter-active (esta última traz o ::after com o dot) nunca atualizavam. Fix: novo método privado syncColumnFilterActive() seta column.filterActive direto + dispatcha só os eventos da column (dispatchColEvent, escopo local — não vaza pro eventSvc global, então InfiniteRowModel não reseta). Wired em applyFilter() (após currentModel = newModel) + setModel() (caminho programático). Smoke real verde em parquet 2.4M rows: dot aparece/some, multi-coluna independente, sem flash branco
  • ICR Compare Coders polish — drill-down filters + spatial pair feedback + modal disabled state (2026-05-12, commits 7063146 + fb7c02b + cc56379 + 23c275e) — 3 frentes B1/B2/B3 do polish "Compare Coders" entregues. B1 drill-downs Cards/Workflow filtram por currentSelection da overview via filterRegionsBySelection puro em regionDerivation; banner inline + clear button nos 2 drilldowns; não toca scope do extract (§46 verificado — visibleCoderIds NUNCA no scope). B2 drill-down P1 spatial responde a cliques diferentes — collectRelevantFiles aplica intersection pra {kind:'pair'} (era union, no synth corpus union dava lanes parecidas) + restringe engine pra {kind:'codeEngine'}; header indica seleção atual. Tests recalibrados pra refletir intersection. B3 modal "ver lado a lado" toggle "par único" — constructor força state='all-pairs' quando options.pair === undefined; chip par único ganha is-disabled + tooltip ("Selecione um par primeiro"). Smoke real verde via scripts/seed-smoke-icr.mjs. Spec original: obsidian-qualia-coding/plugin-docs/archive/claude_sources/specs/20260509-icr-compare-coders-design.md
  • ICR bbox aggregate weighting via perPair inputs (2026-05-11) — reportPairwise ganhou param perPairInputs?: Map<pairKey, EngineKappaInput[]> pra inputs já-per-pair (bbox κ via Hungarian é per pair). Matrix Mode A monta perPairBbox map só pra Cohen e passa ao reporter — bbox naturalmente entra no aggregate weighted por markers.length (mesma regra que já existia entre text-likes). Eliminou avg 50/50 que era trade documentado em E5b. Cache: cacheKey ganha suffix ::bbox quando perPair não-vazio — preserva reuso entre re-renders no mesmo scope, invalidação via bumpReportCache ao mutar markers. WeakMap identity cache bypassed quando perPair set (identity sozinha não diferencia extras)
  • ICR Compare Coders Slice E2 — Modes B/C + Modal + bbox + polish E1 (2026-05-10) — entrega completa do overview da Compare Coders View. Coefficient picker (5 chips Cohen/Fleiss/α/α-binary/cu-α com disabled state aplicabilidade-aware) — Mode A matriz lê state.primaryCoefficient (não mais Cohen hardcoded). Engine filter chips (markdown/pdf/csv-seg/csv-row/audio/video toggle ad-hoc) preenchem gap até Saved Comparisons no E4. Bbox pathwaycomputeBboxKappaForPair wrap bboxAdapter.buildKappaInput per-pair em modes unified (1 coluna spatial-bbox virtual) ou split (pdfShape | image separados); integrado na matriz Mode A via avg 50/50 com text-likes (weighting proper via #events fica em backlog). Mode B overviewTable — 1 row por código × 5 coeficientes, sort default por pior κ ascendente, Cohen aparece pra N=2 / Fleiss pra N≥3. Mode C overviewHeatmap — codes × engines visíveis + spatial-bbox; bbox como avg de C(N,2) Cohen pareados pra N>2. Polish E1 (κ=0 vacuous) — filter includeCodersWithoutMarkers (default false) esconde coders com 0 markers; chip do coder sem markers ganha is-empty (cinza claro + tooltip). Filter hideAgreementTotal funcional — fade opacity 0.25 em cells/linhas com κ > 0.8 nos 3 modes. Modal "ver lado a lado" (CompareCoderCoefficientsModal) — 2 estados toggle (single-pair com per-engine breakdown / all-pairs); diagnóstico narrativo (narrativeDiagnostic) com 3 padrões reconhecíveis (boundary OK + código diverge / boundary disagreement / cu-α << κ); export markdown via clipboard. Setting opt-out general.showNarrativeDiagnosis (default true). ~75 testes novos (3075 → 3150 verde). Tag post-icr-slice-e2-checkpoint. Smoke real verde em todos 7 chunks. Spec: docs/superpowers/specs/2026-05-09-icr-compare-coders-design.md §3.2/§3.3/§6. Plan: docs/superpowers/plans/2026-05-10-icr-slice-e2-modes-bc-modal.md
  • Image engine — 8 itens registrados no BACKLOG pra sessão dedicada (2026-05-09, commit 1810758) — levantamento de hardening 2026-05-08 deixou 8 itens só no chat (regionLabels viewport math, menu rebuild debounce, colorOverride wiring, suppressModelHover sync, multi-select menu UX, label refresh perf, visibility toggle ghost, threshold rect/ellipse assimétrico). Formalizados em BACKLOG.md > Polish curto > Image engine com classificação por tipo (mecânico / mecânico-c-risco / refactor / decisão UX / decisão visual / debug runtime / decisão B deferida) pra futura sessão dedicada saber o que atacar primeiro
  • Cosmético atacável fora image (2026-05-09, commit 731e251) — 5 (e as any).entity vestigiais removidos de auditLog.ts (AuditEntry.entity já existe no tipo); 3 as any em dataManager.deepMerge viram Record<string, unknown> casts + generic constraint T extends object; 12 inline styles repetidos viram 2 CSS classes (.qc-hidden-input em 2 hidden color pickers + .qc-scroll-container em 3 scroll containers); BACKLOG seção Permanente atualizada com números reais (era 6 → na verdade 18 as any justificados, 5 ts-ignore/ts-expect-error, 68 !important AG Grid defensive)
  • Cross-cutting hardening — 4 frentes (2026-05-09, commit fef4d81) — Settings size warnings com bounds 1-10000 MB + Notice + revert via blur event (não onChange — evita spam); CI workflow roda e2e suite completa (19 specs/66 testes) em vez de só smoke; χ² tautológico via walk recursivo no PredicateNode (AND/OR/NOT + 10 leaf kinds + smartCode nesting com cycle protection) detecta SCs cujo predicate referencia variável plotada — flag tautologicalForVariable? em CodeMetadataResult.codes; renderer marca canvas label com prefix + tooltip ganha linha amarela explicativa; Dendrogram cluster count preview no slider title (Cut: 0.50 → 5 clusters) post-render via novo lastDendrogramClusterCount? em AnalyticsViewContext. 2 frentes deferidas: !important AG Grid audit (defensive, exige runtime) + cooccurrence reorder async (refactor invasivo ModeEntry.render em 25 modes)
  • Polish mecânico pré-ICR (2026-05-08, commit e09cf4e) — varredura de strings/CSS/types pré-submissão Community Plugins. Strings/i18n: pt-br residual removido (codeVisibilityPopover header/empty + baseCodeExplorerView hydrator status); empty states com CTA (Marker not found / No segments yet / No codes yet); 'Done' → 'Materialized' no batch memos modal; MCA insufficient com contagens reais; image fallback alinhado com PDF (${shape} em vez de ${shape} region); truncation '…' Unicode → '...' ASCII em 3 arquivos (alinhado com previewText helper). Image: menu position com Math.max/min bounds clamping; regionLabels color fallback #888 theme-agnóstico (era #6200EE purple invisível em light theme); imageToolbar shortcut em mode fora whitelist gera console.warn (era silent fail). CSS: font-size 11px do margin label vai pra .codemarker-margin-label CSS class; 8 inline styles do segment editor header viram .csv-segment-editor-header. Analytics palette: SOURCE_COLORS de chartHelpers reusado em acmMode + frequencyMode (eram dicts locais ou hardcoded); TRIVIAL_THRESHOLD do MCA com docstring explicando origem (centering MCA); N_FILES_WARN_THRESHOLD da Files Dendrogram 200→150 (custo O(n³) vs O(n²) do File Similarity). Misc: Clear cache error com path do arquivo no contexto; 2 console.log debug do main.ts removidos (warns/errors mantidos); minAppVersion 1.5.0 → 1.7.0; tooltip (undefined) fallback no drawToolbarFactory; README sem menção a Intercoder reliability (feature ainda não implementada). Tests: 2 fixes pré-existentes descobertos no caminho — csvCodingModel ellipsis assertion (length 61→63 + endsWith '…'→'...') + performanceBenchmark calculateMCA com assinatura nova de 4 args (drift do fix 0.4.2 não pego pelo bench)
  • Filter sem flash branco em parquet/CSV lazy (2026-05-08) — LazyTextFilter custom (src/csv/duckdb/lazyTextFilter.ts) substitui agTextColumnFilter padrão em todas colunas (real + virtual cod-frow/cod-seg/comment). Pre-fetch da query DuckDB (count) + chama gridApi.refreshInfiniteCache() em vez de params.filterChangedCallback(). Diferença chave: refreshInfiniteCache mantém rows visíveis durante re-fetch (vs purgeInfiniteCache que limpa viewport sync e causava o flash). UI replica agTextColumnFilter — 8 ops (contains/notContains/equals/notEqual/startsWith/endsWith/blank/notBlank) + AND/OR + 2 conditions + caret SVG via pseudo-element. Schema do model compatível com buildWhereClause/buildVirtualFilterClause existentes. Bug do MCA Biplot encontrado/corrigido no caminho: calculateMCA recebia enabledCodeNames mas comparava com marker.codes (IDs pós Phase C) → matching falhava → "Insufficient data for MCA". Fix: assinatura calculateMCA(markers, codeIds, codeNames, colors) separando matching de display. Trade-off residual: cells virtuais (cellRenderer custom + field não-existente no parquet) têm delay ms-pequeno no swap visual após refresh — efeito do mecanismo refreshInfiniteCache que mantém DOM visível durante re-fetch
  • Code Explorer build latency em vault com muitos markers (2026-05-08, commits 611a99b + c3e6a10 + f7f98d0) — ~30s → ~13s (2.3× mais rápido) no pathological 200k markers × 5 cols / M1 8GB. Mitigações: yield UI entre chunks (setTimeout(0)) + chunkSize=1000→10_000 + Promise.all paralelizando queries por column dentro do batchGetMarkerText + inline style.paddingLeft/height/position → CSS classes/vars (.qc-explorer-code-self, .qc-explorer-list, .qc-vlist-row). Diagnóstico via DevTools profile (gargalo era 1000 round-trips DuckDB-Wasm sequenciais saturando microtask queue, não CPU work do main thread). Mitigações C (rebuild parcial) e D (lazy viewport hydration) explicitamente descartadas — conflitam com decisões arquiteturais já tomadas
  • Export Parquet enriquecido — multi-file fallback automático (2026-05-07/08, commits fdbaa55 + bc71ceb + fd945e5 + 3f38eda) — single-file (UX padrão) → catch OOM via regex → multi-file dataset (<base>.qualia-enriched/part-NNN.parquet). Decisão dinâmica em runtime, máquina-agnóstico. Stress test 6 cenários sintéticos (50k a 200k markers + 0-228 MB comments + 9-15 vcols) em parquet 2.376M rows × 21 cols. Teto empírico M1 8GB: single-file aguenta até ~150k markers + ~54 MB comments + 12 vcols; fallback multi-file aguenta tudo. Modal info dinâmica de carga estimada (markers count + MB comments + vcols enabled) sem prever — só descreve. Tags pre-stress-export-baselinepost-stress-export-checkpoint
  • Tabular virtual cols (persist + filter + comment + export) (2026-05-07, release 0.4.0) — data.json csv.fileMeta[fileId].enabledVirtualColumns armazena toggles (cod-frow/cod-seg/comment); RowMarker.comment?: string per-cell com setter/getter no model; AG Grid filter unificado server-side via QualiaMarkersTable (DuckDB temp table long format) + virtualFilterResolver; BatchedMutationApplier coalesce events do canal SC3 em rAF batches; export "Parquet enriquecido" via SQL COPY com CTE per virtual col + LEFT JOIN single-pass. Spec: docs/superpowers/specs/20260506-tabular-virtual-cols-design.md (arquivada workspace externo após release)
  • Sidebar markerText preview pra arquivos lazy (2026-05-06) — MarkerPreviewHydrator orchestrator stateful popula markerTextCache em background quando consumers (Code Explorer, Code Detail, Smart Code list/detail, Memo View by-code) renderizam markers em parquet/CSV lazy não hidratados. Trigger per-file requestHydration(fileId) idempotente (dedup seen + inflight). Status indicator Hidratando previews… X/Y no toolbar. Cobre cold start de vault migrado (QDPX import)
  • Smart Codes Tier 3 + Phase 2 (2026-05-04/05, branch feat/smart-codes, 19 commits, 175 testes novos, mergida em main) — schema completo (PredicateNode AST com 10 leaves + nesting AND/OR/NOT), evaluator puro com short-circuit + cycle detection, SmartCodeCache com invalidação granular + chunked compute, SmartCodeApi CRUD + autoRewriteOnMerge, builder modal row-based + Smart Code Detail + List hub, command palette, audit log entity discriminator + 5 sc_* events, ⚡ icon na Codebook Timeline, QDPX export/import (qualia:SmartCodes namespace + 2-pass parse), CSV tabular smart_codes.csv + R/Python snippets. Phase 2: SC1 (Analytics modes via getSmartCodeViews), SC2 (Code Explorer grupo SC top-level), SC3 (canal onMarkerMutation paralelo a onChange em todos 5 engine models — invalidação cirúrgica + dead code removal indexByCode/indexByFile + cascade fix), SC4 (smartCodesSection no Code Detail All Codes mode + Convert to note pra SC memo). Stress: 10k markers + 100 SCs em <1s. Tags pre-smart-codes-baselinepost-smart-codes-checkpoint
  • Filter de virtual columns em lazy mode (2026-05-07) — AG Grid native filter (popover Contains/Equals/StartsWith/etc) ligado nas 3 virtuais via splitFilterModel + virtualFilterResolver traduz pra SQL contra temp table DuckDB. Antes: filter desabilitado (filter: !lazy)
  • Validação de 2 parquets pesados em paralelo (2026-05-06, smoke manual)
  • Reveal de marker em parquet lazy (2026-05-04, Fase 6 Slice A) — destaca a row corretamente após scroll
  • Pre-populate cache no startup (2026-05-04, Fase 6 Slice A) — labels antes de file open
  • Label de marker em CSV/parquet (2026-05-04, pre-populate fica pra Fase 6) — mostra coordenada quando cache vazio em vez de string vazia
  • Carla label vazia (whitespace-only cell) (2026-05-06) — previewText(s, maxLength): string | null em markerResolvers.ts centraliza trim+truncate em 4 callsites (PDF/CSV/markdown/markdown-via-editor) + smartCodeAccess.getMarkerLabel
  • "Missing DB manager" residual do DuckDB worker (2026-05-06) — DuckDBRowProvider.dispose() aguarda queries em flight terminarem antes de DROP TABLE / dropFile. Counter inflight em trackedQuery() privada
  • Bundle size pós-DuckDB (2026-05-04, Fase 6 Slice D) — main.js 49 MB → 14.2 MB (71% redução). esbuild plugin duckdbWasmGzipPlugin gzipa WASM em build-time (32.7 MB → 7.6 MB level 9). Runtime decompress lazy via getWasmBytes() em wasmAssets.ts (cached após primeira boot). Destrava Community Plugins
  • PDF undo stack removido (2026-05-07) — feature Undo last PDF coding action (Cmd+Z) era a única engine com undo, mantinha inconsistência cross-engine e o keybinding nunca foi wired no PdfCodingView. Saiu undoStack/pushUndo/reconcileCodes/UndoEntry/MAX_UNDO + 13 testes + TECHNICAL-PATTERNS.md §4.8

2026-04 (sprint de hardening)

  • §14 Analytics engine codeId vs name (2026-04-21, commits 1422bb7 + cf09894) — extractCodes retornava codeId mas consumidores indexavam por nome após Phase C. Fix: UnifiedCode.id obrigatório, consolidateCodes indexa por id, normalização canônica normalizeCodeApplications no load de cada model. Workbench vault: 241/241 canônico
  • §11.1 QDPX round-trip integrity (2026-04-21) — 4 bugs críticos: GUID mismatch Codebook↔CodeRef, frontmatter duplicado, vault.create não persistindo, models sem sync pós-import. qdcExporter.buildCodebookXml aceita ensureCodeGuid, importer usa vault.adapter.write direto, reloadAfterImport() no plugin sincroniza models
  • §16 Audio/Video scroll persistence (2026-04-22) — save retornava 0 (WaveSurfer reseta antes do unload) + restore sobrescrito por autoCenter. Fix: mirror lastKnownScroll via listener + setAutoCenter(false) durante restore
  • §13 ImageView/AudioView/VideoView → FileView (2026-04-22) — lifecycle limpo via onLoadFile/onUnloadFile. registerFileIntercept mantido (core-native ext rejeitam registerExtensions). MediaViewCore.currentFile parallel field eliminado
  • §15 Case Variables edge cases (2026-04-22) — emoji/unicode (já funcionava, teste empírico add), valor vazio (Notice + reject), hot-reload com popover (activePopoverClose no onunload), multi-pane sync via metadataCache
  • §12 Codebook Panel polish K1-K3 (2026-04-22/23) — K1 autoReveal removido (órfão), K2 drag-drop visual completo (ghost + drop indicator flutuante + is-just-dropped pulse + is-drop-rejected shake), K3 virtual scroll com row recycling (Map<nodeIndex, HTMLElement>)
  • §8b CB1-CB4 (2026-04-22) — ExpandedState { codes; folders } unificado, threshold 5 pra "Move to folder..." submenu, core/dialogs.ts substitui prompt/confirm nativos
  • §8c E1-E3 (2026-04-22) — drag de nós no Relations Network (mousedown/mouseup + redraw() extraído), AbstractInputSuggest substitui <datalist>, inline add-row de Relations migrado pra TextComponent/ExtraButtonComponent
  • §11 PDF round-trip (2026-04-23/24) — pdfPlainText.buildPlainText consolida via pdfjs, resolveMarkerOffsets com fallback whitespace-normalize, loadPdfExportData extrai dims reais, ensurePdfJsLoaded força carga em vault novo, rename NormalizedShapeCoordsPercentShapeCoords
  • §10 Toggle Media Coding (2026-04-23) — 4 mídias com autoOpen/showButton simétricos, pinnedFileByLeaf no fileInterceptor pra respeitar swap manual, PDF usa instrument/deinstrument in-place, higiene cosmética (file-menu rename, showButton live, detach actions no onunload)

2026-03 (consolidação técnica)

  • §3 Multi-pane / state isolation (2026-03-20) — PdfViewState (WeakMap per-view), keyboard scoped ao contentEl, hoveredMarkerIds em todos os models. M1/M2/M3 fechados em conjunto
  • §8 Core/Registry R1 (2026-03-20) — fromJSON corrigido (def.id = id garante consistência)
  • Incremental refresh/cache por engine (2026-03-20) — ConsolidationCache (analytics dirty flags) + UnifiedModelAdapter cache + debounce rAF via scheduleRefresh
  • Board snapshot vs live-linked (2026-03-20) — "Refresh on open" via boardReconciler.ts. Reconcilia cores/nomes/contagens, marca órfãos, remove arrows inválidas
  • §1 PDF lifecycle P1-P9 (2026-03) — timeouts em Map cancelados em stop, hover/popover state per-view, removeMarker chama notify, keyboard handler filtra contenteditable
  • §2 Image engine I1-I5 (2026-03) — origStrokeWidth em WeakMap per-shape, refreshAll após zoom/pan, keyboard scoped ao contentEl, mouseup condition simplificada
  • §4 Markdown CM6 C1-C5 (2026-03) — z-index normalizado (handles 1000, popover 2000), scrollDOM position salvo/restaurado, ch clampado, batch save, isPositionBefore strict
  • §5 CSV V1-V2 (2026-03) — node.sourceRowIndex em vez de node.rowIndex (estável após sort), btn.dataset.wrapped setado na criação e no toggle
  • §6 Analytics A1-A6 (2026-03) — dead code dendrogramMode removido, Chart.js destroy antes de recriar, PapaParse no textExtractor (multiline/quotes/CRLF), skip .parquet em extractBatch, sort por Cramér's V antes de slice
  • §7 Sidebar S1-S6 (2026-03) — navigateToSegment dispara eventos por engine (csv/image/pdf#page/audio/video), decisionTree filtra por markerIds com erro, searchTimeout cancelado no onClose

Permanência arquitetônica

  • Escala z-index Markdown (§4 C1): content auto, margin panel 1, resize handle 100, drag handles 1000, popover 2000
  • registerFileIntercept mandatory pros 4 engines de mídia: Obsidian rejeita registerExtensions em core-native (mp3/mp4/png) com Error: Attempting to register an existing file extension