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.
- Smart Codes — leaf
textContains+ cache invalidation viavault.on('modify')(2026-05-12, noite) — 11º leaf do predicate AST (filtra markers cujo texto pesquisável contém substring, case-insensitive default + opt-incaseSensitive). Resolve item gated "Smart Code cache hash-based invalidation" sem precisar de hash: invalidação file-level viaSmartCodeCache.invalidateForFileText(fileId)wired novault.on('modify')existente (que já era usado prasourceHashRegistry.recompute+markerTextCache).dependencyExtractorganha flagneedsText. HelpergetMarkerSearchableTextemmarkerResolversresolve texto por engine (markdown/pdf viamarker.text, csv viamarkerText, image viashapeLabel, audio/video viamarkerLabel). QDPX/Tabular transparente (predicateSerializer é JSON-genérico). Markdown in-Obsidian já era coberto viaapplyMarkerMutation—vault.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 viascripts/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
LazyTextFiltercustom emsrc/csv/duckdb/lazyTextFilter.ts). Causa-raiz: built-in filter chamaparams.filterChangedCallback()que internamente rodasetColFilterActive(col, isActive, ...)noFilterManager— 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 dispararpurgeInfiniteCacheque causa flash branco — razão de existir do filter), então flagscolumn.filterActivee classes.ag-header-cell-filtered/.ag-filter-active(esta última traz o::aftercom o dot) nunca atualizavam. Fix: novo método privadosyncColumnFilterActive()setacolumn.filterActivedireto + dispatcha só os eventos da column (dispatchColEvent, escopo local — não vaza proeventSvcglobal, então InfiniteRowModel não reseta). Wired emapplyFilter()(apóscurrentModel = 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 porcurrentSelectionda overview viafilterRegionsBySelectionpuro emregionDerivation; banner inline + clear button nos 2 drilldowns; não toca scope do extract (§46 verificado —visibleCoderIdsNUNCA no scope). B2 drill-down P1 spatial responde a cliques diferentes —collectRelevantFilesaplica 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çastate='all-pairs'quandooptions.pair === undefined; chippar únicoganhais-disabled+ tooltip ("Selecione um par primeiro"). Smoke real verde viascripts/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) —
reportPairwiseganhou paramperPairInputs?: Map<pairKey, EngineKappaInput[]>pra inputs já-per-pair (bbox κ via Hungarian é per pair). Matrix Mode A montaperPairBboxmap só pra Cohen e passa ao reporter — bbox naturalmente entra no aggregate weighted pormarkers.length(mesma regra que já existia entre text-likes). Eliminou avg 50/50 que era trade documentado em E5b. Cache: cacheKey ganha suffix::bboxquando perPair não-vazio — preserva reuso entre re-renders no mesmo scope, invalidação viabumpReportCacheao 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 pathway —computeBboxKappaForPairwrapbboxAdapter.buildKappaInputper-pair em modes unified (1 colunaspatial-bboxvirtual) 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 BoverviewTable— 1 row por código × 5 coeficientes, sort default por pior κ ascendente, Cohen aparece pra N=2 / Fleiss pra N≥3. Mode CoverviewHeatmap— codes × engines visíveis + spatial-bbox; bbox como avg de C(N,2) Cohen pareados pra N>2. Polish E1 (κ=0 vacuous) — filterincludeCodersWithoutMarkers(default false) esconde coders com 0 markers; chip do coder sem markers ganhais-empty(cinza claro + tooltip). FilterhideAgreementTotalfuncional — 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-outgeneral.showNarrativeDiagnosis(default true). ~75 testes novos (3075 → 3150 verde). Tagpost-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 emBACKLOG.md > Polish curto > Image enginecom 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).entityvestigiais removidos deauditLog.ts(AuditEntry.entityjá existe no tipo); 3as anyemdataManager.deepMergeviramRecord<string, unknown>casts + generic constraintT extends object; 12 inline styles repetidos viram 2 CSS classes (.qc-hidden-inputem 2 hidden color pickers +.qc-scroll-containerem 3 scroll containers); BACKLOG seção Permanente atualizada com números reais (era 6 → na verdade 18as anyjustificados, 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 noPredicateNode(AND/OR/NOT + 10 leaf kinds +smartCodenesting com cycle protection) detecta SCs cujo predicate referencia variável plotada — flagtautologicalForVariable?emCodeMetadataResult.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 novolastDendrogramClusterCount?emAnalyticsViewContext. 2 frentes deferidas: !important AG Grid audit (defensive, exige runtime) + cooccurrence reorder async (refactor invasivoModeEntry.renderem 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 compreviewTexthelper). Image: menu position comMath.max/minbounds clamping; regionLabels color fallback#888theme-agnóstico (era#6200EEpurple invisível em light theme); imageToolbar shortcut em mode fora whitelist geraconsole.warn(era silent fail). CSS: font-size 11px do margin label vai pra.codemarker-margin-labelCSS 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; 2console.logdebug 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 '…'→'...') + performanceBenchmarkcalculateMCAcom 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) —
LazyTextFiltercustom (src/csv/duckdb/lazyTextFilter.ts) substituiagTextColumnFilterpadrão em todas colunas (real + virtual cod-frow/cod-seg/comment). Pre-fetch da query DuckDB (count) + chamagridApi.refreshInfiniteCache()em vez deparams.filterChangedCallback(). Diferença chave:refreshInfiniteCachemantém rows visíveis durante re-fetch (vspurgeInfiniteCacheque 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 combuildWhereClause/buildVirtualFilterClauseexistentes. Bug do MCA Biplot encontrado/corrigido no caminho:calculateMCArecebiaenabledCodeNamesmas comparava commarker.codes(IDs pós Phase C) → matching falhava → "Insufficient data for MCA". Fix: assinaturacalculateMCA(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 mecanismorefreshInfiniteCacheque 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.allparalelizando queries por column dentro dobatchGetMarkerText+ inlinestyle.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. Tagspre-stress-export-baseline↔post-stress-export-checkpoint - Tabular virtual cols (persist + filter + comment + export) (2026-05-07, release 0.4.0) —
data.json csv.fileMeta[fileId].enabledVirtualColumnsarmazena toggles (cod-frow/cod-seg/comment);RowMarker.comment?: stringper-cell com setter/getter no model; AG Grid filter unificado server-side viaQualiaMarkersTable(DuckDB temp table long format) +virtualFilterResolver;BatchedMutationAppliercoalesce 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) —
MarkerPreviewHydratororchestrator stateful populamarkerTextCacheem 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-filerequestHydration(fileId)idempotente (dedupseen + inflight). Status indicatorHidratando previews… X/Yno 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 emmain) — 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:SmartCodesnamespace + 2-pass parse), CSV tabularsmart_codes.csv+ R/Python snippets. Phase 2: SC1 (Analytics modes viagetSmartCodeViews), SC2 (Code Explorer grupo SC top-level), SC3 (canalonMarkerMutationparalelo aonChangeem todos 5 engine models — invalidação cirúrgica + dead code removalindexByCode/indexByFile+ cascade fix), SC4 (smartCodesSectionno Code Detail All Codes mode + Convert to note pra SC memo). Stress: 10k markers + 100 SCs em <1s. Tagspre-smart-codes-baseline↔post-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+virtualFilterResolvertraduz 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 | nullemmarkerResolvers.tscentraliza 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. CounterinflightemtrackedQuery()privada - Bundle size pós-DuckDB (2026-05-04, Fase 6 Slice D) —
main.js49 MB → 14.2 MB (71% redução). esbuild pluginduckdbWasmGzipPlugingzipa WASM em build-time (32.7 MB → 7.6 MB level 9). Runtime decompress lazy viagetWasmBytes()emwasmAssets.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 noPdfCodingView. Saiu undoStack/pushUndo/reconcileCodes/UndoEntry/MAX_UNDO + 13 testes +TECHNICAL-PATTERNS.md §4.8
- §14 Analytics engine codeId vs name (2026-04-21, commits
1422bb7+cf09894) —extractCodesretornava codeId mas consumidores indexavam por nome após Phase C. Fix:UnifiedCode.idobrigatório,consolidateCodesindexa por id, normalização canônicanormalizeCodeApplicationsno 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.createnão persistindo, models sem sync pós-import.qdcExporter.buildCodebookXmlaceitaensureCodeGuid, importer usavault.adapter.writedireto,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
lastKnownScrollvia listener +setAutoCenter(false)durante restore - §13 ImageView/AudioView/VideoView → FileView (2026-04-22) — lifecycle limpo via
onLoadFile/onUnloadFile.registerFileInterceptmantido (core-native ext rejeitamregisterExtensions). 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 (
activePopoverCloseno 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-droppedpulse +is-drop-rejectedshake), 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.tssubstituiprompt/confirmnativos - §8c E1-E3 (2026-04-22) — drag de nós no Relations Network (
mousedown/mouseup+redraw()extraído),AbstractInputSuggestsubstitui<datalist>, inline add-row de Relations migrado praTextComponent/ExtraButtonComponent - §11 PDF round-trip (2026-04-23/24) —
pdfPlainText.buildPlainTextconsolida via pdfjs,resolveMarkerOffsetscom fallback whitespace-normalize,loadPdfExportDataextrai dims reais,ensurePdfJsLoadedforça carga em vault novo, renameNormalizedShapeCoords→PercentShapeCoords - §10 Toggle Media Coding (2026-04-23) — 4 mídias com
autoOpen/showButtonsimétricos,pinnedFileByLeafno fileInterceptor pra respeitar swap manual, PDF usa instrument/deinstrument in-place, higiene cosmética (file-menu rename, showButton live, detach actions no onunload)
- §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) —
fromJSONcorrigido (def.id = id garante consistência) - Incremental refresh/cache por engine (2026-03-20) —
ConsolidationCache(analytics dirty flags) + UnifiedModelAdapter cache + debounce rAF viascheduleRefresh - 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.sourceRowIndexem vez denode.rowIndex(estável após sort),btn.dataset.wrappedsetado 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
- Escala z-index Markdown (§4 C1): content
auto, margin panel 1, resize handle 100, drag handles 1000, popover 2000 registerFileInterceptmandatory pros 4 engines de mídia: Obsidian rejeitaregisterExtensionsem core-native (mp3/mp4/png) comError: Attempting to register an existing file extension