viberadar 0.3.205 → 0.3.206

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -815,10 +815,6 @@
815
815
  .obs-copy-btn:disabled { opacity:0.35; cursor:not-allowed; }
816
816
  .obs-select-all { font-size:12px; color:var(--dim); cursor:pointer; background:none; border:none; padding:4px 8px; }
817
817
  .obs-select-all:hover { color:var(--accent); }
818
- .obs-tier-badge { display:inline-block; padding:3px 8px; border-radius:3px; font-size:11px; font-weight:700; letter-spacing:0.5px; }
819
- .obs-tier-critical { background:rgba(248,81,73,0.2); color:var(--red); }
820
- .obs-tier-important { background:rgba(227,179,65,0.2); color:var(--yellow); }
821
- .obs-tier-normal { background:rgba(139,148,158,0.15); color:var(--muted); }
822
818
  .obs-fp-list { font-size:11px; color:var(--muted); margin:4px 0 0 18px; }
823
819
  .obs-fp-item { display:flex; gap:6px; padding:1px 0; align-items:baseline; }
824
820
  .obs-noisy-detail { display:none; padding:6px 0 2px 0; border-top:1px dashed var(--border); margin-top:4px; }
@@ -4581,18 +4577,11 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
4581
4577
  const _blCurrFPs = missingV2.reduce((s, m) => s + (m.failurePoints || []).length, 0);
4582
4578
  const _blCurrNoise = topNoisy.length;
4583
4579
  const _blCurrEnrich = Object.entries(fieldGapsData).filter(([, v]) => v > 0).length;
4584
- const _blCurrTiers = {};
4585
- ['critical', 'important', 'normal'].forEach(tier => {
4586
- const items = missingV2.filter(m => m.riskTier === tier);
4587
- _blCurrTiers[tier] = { modules: items.length, fps: items.reduce((s, m) => s + (m.failurePoints || []).length, 0) };
4588
- });
4589
-
4590
- if (!_bl) {
4591
- _bl = { ts: Date.now(), noiseRatio, structPct, actionPct, coveragePct,
4592
- missing: _blCurrMissing, fps: _blCurrFPs, noise: _blCurrNoise, enrich: _blCurrEnrich,
4593
- tiers: _blCurrTiers };
4594
- try { localStorage.setItem('vr_obs_bl_' + _bsKey, JSON.stringify(_bl)); } catch(e) {}
4595
- }
4580
+ if (!_bl) {
4581
+ _bl = { ts: Date.now(), noiseRatio, structPct, actionPct, coveragePct,
4582
+ missing: _blCurrMissing, fps: _blCurrFPs, noise: _blCurrNoise, enrich: _blCurrEnrich };
4583
+ try { localStorage.setItem('vr_obs_bl_' + _bsKey, JSON.stringify(_bl)); } catch(e) {}
4584
+ }
4596
4585
 
4597
4586
  // Delta badge helpers
4598
4587
  const _d = (curr, base, invert = false) => {
@@ -4706,7 +4695,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
4706
4695
  </div>`;
4707
4696
  }).join('') || '<div class="obs-sub">Шумных паттернов не обнаружено</div>';
4708
4697
 
4709
- // ── Missing critical logs (V2: grouped by risk tier with failure points) ──
4698
+ // ── Missing failure logs (V2: flat list; no heuristic risk tiers in UI) ──
4710
4699
  const v2Data = missingV2.filter(m => m.failurePoints.length > 0);
4711
4700
  window.__obsMissingV2 = v2Data;
4712
4701
  window.__obsMissingGroupMeta = {};
@@ -4714,66 +4703,56 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
4714
4703
  'empty-catch':'пустой catch','catch-no-log':'catch без лога','promise-catch-no-log':'.catch без лога',
4715
4704
  'http-no-error-handling':'HTTP без обработки','db-no-error-handling':'DB без обработки',
4716
4705
  'throw-no-log':'throw без лога','error-check-no-log':'if(err) без лога',
4717
- };
4718
- let missingSection = '';
4719
- if (v2Data.length > 0) {
4720
- const tierLabels = { critical:'Критичные', important:'Важные', normal:'Обычные' };
4721
- const tiers = ['critical','important','normal'];
4722
- const tierSections = tiers.map(tier => {
4723
- const items = v2Data.filter(m => m.riskTier === tier);
4724
- if (!items.length) return '';
4725
- const groupId = 'missing-' + tier;
4726
- const groupIndices = items
4727
- .map(m => (o.missingCriticalLogsV2 || []).indexOf(m))
4728
- .filter(idx => idx >= 0);
4729
- window.__obsMissingGroupMeta[groupId] = {
4730
- missingLogIndices: groupIndices,
4731
- recommendationType: 'add event',
4732
- };
4733
- const expandBtn = hasAgent ? `<button class="obs-expand-btn" onclick="event.stopPropagation();toggleObsDetail('${groupId}')">▼</button>` : '';
4734
- const copyGroupBtn = `<button class="obs-copy-btn" title="Скопировать prompt для всей группы" onclick="event.stopPropagation();obsCopyPrompt('obs-fix-selected',window.__obsMissingGroupMeta['${groupId}'])">📋 Промпт</button>`;
4735
- const totalFPs = items.reduce((s,m) => s + m.failurePoints.length, 0);
4736
- const detailItems = items.map(m => {
4737
- const globalIdx = (o.missingCriticalLogsV2 || []).indexOf(m); // index in full unfiltered array must match server's missingCriticalLogsV2
4738
- const fpCount = m.failurePoints.length;
4739
- const fpPreview = m.failurePoints.slice(0,3).map(fp =>
4740
- `<div class="obs-fp-item"><span class="obs-fp-type">${fpTypeLabels[fp.type]||fp.type}</span><span class="obs-fp-line">~${fp.lineApprox}</span></div>`
4741
- ).join('');
4742
- const moreCount = fpCount > 3 ? `<div class="obs-fp-item" style="color:var(--dim)">...и ещё ${fpCount-3}</div>` : '';
4743
- const covBadge = m.hasAnyWarnError ? '<span style="font-size:10px;color:var(--dim)" title="Есть warn/error, но не все точки покрыты">частично</span>' : '';
4744
- return `<label class="obs-detail-item" style="flex-wrap:wrap">
4745
- <input type="checkbox" data-missing-idx="${globalIdx}" onchange="obsUpdateSelectedCount('${groupId}')">
4746
- <span title="${escapeHtml(m.modulePath)}" style="flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${escapeHtml(m.modulePath.split('/').slice(-2).join('/'))}</span>
4747
- <span style="color:var(--dim);flex-shrink:0;font-size:10px">${escapeHtml(m.roleHint)}</span>
4748
- <span style="color:var(--yellow);flex-shrink:0">${fpCount} точек</span>
4749
- ${covBadge}
4750
- ${fpPreview || moreCount ? `<div class="obs-fp-list" style="width:100%">${fpPreview}${moreCount}</div>` : ''}
4751
- </label>`;
4752
- }).join('');
4753
- const addBtn = hasAgent ? `<button class="obs-run-selected" disabled onclick="obsMissingRunSelected('${groupId}')">добавить логи выбранным</button><button class="obs-copy-btn obs-copy-selected" disabled title="Скопировать промпт" onclick="obsCopyMissingSelected('${groupId}')">📋</button>` : '';
4754
- const detail = hasAgent ? `
4755
- <div id="obs-detail-${groupId}" class="obs-detail" data-obs-action="missing" data-obs-label="${tierLabels[tier]}">
4756
- <div class="obs-detail-bar" style="border-top:none;padding-top:0;margin-bottom:4px">
4757
- <button class="obs-select-all" onclick="obsToggleAll('${groupId}')">выбрать все / снять</button>
4758
- </div>
4759
- <div class="obs-detail-list">${detailItems}</div>
4760
- <div class="obs-detail-bar">${addBtn}</div>
4761
- </div>` : '';
4762
- const _blTier = _bl?.tiers?.[tier];
4763
- return `<div class="obs-tier-group">
4764
- <div class="obs-tier-group-header">
4765
- <span class="obs-tier-badge obs-tier-${tier}">${tierLabels[tier]}</span>
4766
- <span>${items.length}${_d(items.length, _blTier?.modules)} модулей, ${totalFPs}${_d(totalFPs, _blTier?.fps)} точек отказа</span>
4767
- ${copyGroupBtn}
4768
- ${expandBtn}
4706
+ };
4707
+ let missingSection = '';
4708
+ if (v2Data.length > 0) {
4709
+ const groupId = 'missing-all';
4710
+ const groupIndices = v2Data
4711
+ .map(m => (o.missingCriticalLogsV2 || []).indexOf(m))
4712
+ .filter(idx => idx >= 0);
4713
+ window.__obsMissingGroupMeta[groupId] = {
4714
+ missingLogIndices: groupIndices,
4715
+ recommendationType: 'add event',
4716
+ };
4717
+ const expandBtn = hasAgent ? `<button class="obs-expand-btn" onclick="event.stopPropagation();toggleObsDetail('${groupId}')">▼</button>` : '';
4718
+ const copyGroupBtn = `<button class="obs-copy-btn" title="Скопировать prompt по всем точкам отказа" onclick="event.stopPropagation();obsCopyPrompt('obs-fix-selected',window.__obsMissingGroupMeta['${groupId}'])">📋 Промпт</button>`;
4719
+ const totalFPs = v2Data.reduce((s,m) => s + m.failurePoints.length, 0);
4720
+ const detailItems = v2Data.map(m => {
4721
+ const globalIdx = (o.missingCriticalLogsV2 || []).indexOf(m);
4722
+ const fpCount = m.failurePoints.length;
4723
+ const fpPreview = m.failurePoints.slice(0,3).map(fp =>
4724
+ `<div class="obs-fp-item"><span class="obs-fp-type">${fpTypeLabels[fp.type]||fp.type}</span><span class="obs-fp-line">~${fp.lineApprox}</span></div>`
4725
+ ).join('');
4726
+ const moreCount = fpCount > 3 ? `<div class="obs-fp-item" style="color:var(--dim)">...и ещё ${fpCount-3}</div>` : '';
4727
+ const covBadge = m.hasAnyWarnError ? '<span style="font-size:10px;color:var(--dim)" title="Есть warn/error, но не все точки покрыты">частично</span>' : '';
4728
+ return `<label class="obs-detail-item" style="flex-wrap:wrap">
4729
+ <input type="checkbox" data-missing-idx="${globalIdx}" onchange="obsUpdateSelectedCount('${groupId}')">
4730
+ <span title="${escapeHtml(m.modulePath)}" style="flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${escapeHtml(m.modulePath.split('/').slice(-2).join('/'))}</span>
4731
+ <span style="color:var(--yellow);flex-shrink:0">${fpCount} точек</span>
4732
+ ${covBadge}
4733
+ ${fpPreview || moreCount ? `<div class="obs-fp-list" style="width:100%">${fpPreview}${moreCount}</div>` : ''}
4734
+ </label>`;
4735
+ }).join('');
4736
+ const addBtn = hasAgent ? `<button class="obs-run-selected" disabled onclick="obsMissingRunSelected('${groupId}')">prompt по выбранным</button><button class="obs-copy-btn obs-copy-selected" disabled title="Скопировать промпт" onclick="obsCopyMissingSelected('${groupId}')">📋</button>` : '';
4737
+ const detail = hasAgent ? `
4738
+ <div id="obs-detail-${groupId}" class="obs-detail" data-obs-action="missing" data-obs-label="точки отказа">
4739
+ <div class="obs-detail-bar" style="border-top:none;padding-top:0;margin-bottom:4px">
4740
+ <button class="obs-select-all" onclick="obsToggleAll('${groupId}')">выбрать все / снять</button>
4769
4741
  </div>
4770
- ${detail}
4771
- </div>`;
4772
- }).join('');
4773
- missingSection = tierSections || '<div class="obs-sub" style="color:var(--green)">Критичные сценарии покрыты</div>';
4774
- } else {
4775
- missingSection = '<div class="obs-sub" style="color:var(--green)">Критичные сценарии покрыты</div>';
4776
- }
4742
+ <div class="obs-detail-list">${detailItems}</div>
4743
+ <div class="obs-detail-bar">${addBtn}</div>
4744
+ </div>` : '';
4745
+ missingSection = `<div class="obs-tier-group">
4746
+ <div class="obs-tier-group-header">
4747
+ <span>Точки отказа без достаточного логирования: ${v2Data.length}${_d(v2Data.length, _bl?.missing)} модулей, ${totalFPs}${_d(totalFPs, _bl?.fps)} точек</span>
4748
+ ${copyGroupBtn}
4749
+ ${expandBtn}
4750
+ </div>
4751
+ ${detail}
4752
+ </div>`;
4753
+ } else {
4754
+ missingSection = '<div class="obs-sub" style="color:var(--green)">Точки отказа покрыты</div>';
4755
+ }
4777
4756
 
4778
4757
  const fieldGaps = fieldGapsData;
4779
4758
  window.__obsFieldGroupMeta = {};
@@ -4967,7 +4946,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
4967
4946
  <div class="obs-list">
4968
4947
  <div class="obs-list-item"><span style="color:var(--red)">Мусор (убрать)</span><strong>${o.classification.trash}</strong></div>
4969
4948
  <div class="obs-list-item"><span style="color:var(--green)">Полезные</span><strong>${o.classification.useful}</strong></div>
4970
- <div class="obs-list-item"><span style="color:var(--blue)">Критичные</span><strong>${o.classification.critical}</strong></div>
4949
+ <div class="obs-list-item"><span style="color:var(--blue)">Actionable warn/error</span><strong>${o.classification.critical}</strong></div>
4971
4950
  </div>
4972
4951
  </div>
4973
4952
  <div class="obs-card">
@@ -5094,12 +5073,12 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
5094
5073
  </div>
5095
5074
  <div class="obs-hint-section">
5096
5075
  <div class="obs-hint-section-title">Как использовать</div>
5097
- <p>Модули разбиты по уровню риска: <span style="color:var(--red)">Критичные</span> трогать в первую очередь (платежи, авторизация, запись данных). Раскрой группу, выбери модули и нажми <strong>«добавить логи выбранным»</strong>.</p>
5076
+ <p>Это не шкала критичности и не команда “логировать всё”. VibeRadar показывает найденные точки отказа: скопируй промпт, дай агенту прочитать контекст и добавлять warn/error только там, где это реально operational-сбой.</p>
5098
5077
  </div>
5099
5078
  </div>
5100
5079
  </div>
5101
5080
  <div class="obs-card">
5102
- <div class="obs-title">Нет критичных логов</div>
5081
+ <div class="obs-title">Точки отказа без достаточного логирования</div>
5103
5082
  <div class="obs-list" style="gap:4px">${missingSection}</div>
5104
5083
  </div>
5105
5084
  </div>
@@ -5180,7 +5159,7 @@ function renderObsGlobalDetail(c, filterFeatureKey) {
5180
5159
 
5181
5160
  <span class="hl-dim">действие</span> suppress — модуль генерирует шум, логи нужно убрать/понизить.
5182
5161
  enrich fields — логи есть, но без нужных полей.
5183
- add event — нет вообще никаких логов в критичных местах.
5162
+ add event — найдены точки отказа без достаточного warn/error покрытия.
5184
5163
  downgrade level— используется INFO там, где достаточно DEBUG.</div>
5185
5164
  </div>
5186
5165
  <div class="obs-hint-section">
@@ -5355,19 +5334,18 @@ function renderObservabilityOverview(c) {
5355
5334
  `<div class="obs-row"><span class="obs-priority-${i.priority}">[${i.priority}]</span> ${escapeHtml(i.pattern)} · x${i.count} → <b>${i.recommendation}</b></div>`
5356
5335
  ).join('') || '<div class="obs-row">Нет шумных паттернов</div>';
5357
5336
 
5358
- const v2Missing = o.missingCriticalLogsV2 || [];
5359
- let missing;
5360
- if (v2Missing.length) {
5361
- const tierLabels = { critical: '🔴 крит', important: '🟡 важн', normal: '⚪ обычн' };
5362
- missing = v2Missing.slice(0, 8).map(m =>
5363
- `<div class="obs-row"><span class="obs-tier-badge obs-tier-${m.riskTier}">${tierLabels[m.riskTier]}</span> ${escapeHtml(m.modulePath)} · ${m.failurePoints.length} точек отказа</div>`
5364
- ).join('');
5365
- if (v2Missing.length > 8) missing += `<div class="obs-row" style="color:var(--dim)">...и ещё ${v2Missing.length - 8}</div>`;
5366
- } else {
5367
- missing = (o.missingCriticalLogs || []).slice(0, 5).map(i =>
5368
- `<div class="obs-row"><span class="obs-priority-${i.priority}">[${i.priority}]</span> ${escapeHtml(i.pattern)} → <b>${i.recommendation}</b></div>`
5369
- ).join('') || '<div class="obs-row">Критичные логи покрыты</div>';
5370
- }
5337
+ const v2Missing = o.missingCriticalLogsV2 || [];
5338
+ let missing;
5339
+ if (v2Missing.length) {
5340
+ missing = v2Missing.slice(0, 8).map(m =>
5341
+ `<div class="obs-row">${escapeHtml(m.modulePath)} · ${m.failurePoints.length} точек отказа${m.hasAnyWarnError ? ' · частично покрыто' : ''}</div>`
5342
+ ).join('');
5343
+ if (v2Missing.length > 8) missing += `<div class="obs-row" style="color:var(--dim)">...и ещё ${v2Missing.length - 8}</div>`;
5344
+ } else {
5345
+ missing = (o.missingCriticalLogs || []).slice(0, 5).map(i =>
5346
+ `<div class="obs-row"><span class="obs-priority-${i.priority}">[${i.priority}]</span> ${escapeHtml(i.pattern)} → <b>${i.recommendation}</b></div>`
5347
+ ).join('') || '<div class="obs-row">Точки отказа покрыты</div>';
5348
+ }
5371
5349
 
5372
5350
  const catalogRows = (o.catalog || []).slice(0, 10).map(i =>
5373
5351
  `<div class="obs-cat-row"><span>${escapeHtml(i.modulePath)}</span><span>${i.level}</span><span>${i.format}</span><span>${i.frequency}</span><span>${escapeHtml(i.owner)}</span><span>${i.recommendation}</span></div>`
@@ -5385,7 +5363,7 @@ function renderObservabilityOverview(c) {
5385
5363
  ${noisy}
5386
5364
  </div>
5387
5365
  <div class="obs-list">
5388
- <h4>Отсутствующие критичные логи</h4>
5366
+ <h4>Точки отказа без логов</h4>
5389
5367
  ${missing}
5390
5368
  </div>
5391
5369
  </div>
@@ -5395,7 +5373,7 @@ function renderObservabilityOverview(c) {
5395
5373
  ${catalogRows || '<div class="obs-row">Логи не найдены</div>'}
5396
5374
  </div>
5397
5375
  <div class="obs-row" style="margin-top:8px">
5398
- Классификация: мусор ${o.classification.trash} · полезно ${o.classification.useful} · критично ${o.classification.critical}
5376
+ Классификация логов: шум ${o.classification.trash} · полезно ${o.classification.useful} · actionable warn/error ${o.classification.critical}
5399
5377
  </div>
5400
5378
  </div>`;
5401
5379
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viberadar",
3
- "version": "0.3.205",
3
+ "version": "0.3.206",
4
4
  "description": "Live module map with test coverage for vibecoding projects",
5
5
  "main": "./dist/cli.js",
6
6
  "bin": {