Source: PRD-018 SC-2 audit — minor warnings consolidated.
A handful of small, low-risk cleanups across the migrated files. Bundling them into one issue.
1. Silent try/catch needs FIXME (rule 10)
template/src/widgets/timeline/ui/Timeline.svelte:97-105
releasePointerCapture is wrapped in try { … } catch {} without a comment. Per .claude/rules/10-comments-policy.md, suppressed errors require // FIXME(reason): …. Add:
// FIXME(pointer-capture-race): release may throw if onPointerDown was preempted by capture transfer
2. Inline <span class="kind"> re-implements Badge (Arch [W13])
template/src/widgets/insights-rail/ui/InsightsRail.svelte:647-655
The widget uses <Badge variant="ghost" size="sm" class="kind"> correctly elsewhere (e.g. ArtifactPanel.svelte:188). Replace the inline <span class="kind"> with the same <Badge> (after Badge tone="mono" lands — see rule-24 cleanup tracker).
3. InsightsRail double-call of t.badge() (Logic [W3], Frontend [W10])
template/src/widgets/insights-rail/ui/InsightsRail.svelte:97
{#if t.badge() !== null && t.badge() !== 0}
<Badge ...>{t.badge()}</Badge>
{/if}
Three calls per tab per render. Use {@const}:
{#each TABS as t (t.key)}
{@const n = t.badge()}
...
{#if n !== null && n !== 0}<Badge ...>{n}</Badge>{/if}
{/each}
Also: n !== 0 check is dead (badge: () => x.length || null already collapses 0 → null). Drop one.
4. Missing key on InsightsRail {#each TABS} (Frontend [W7])
Same file, line 89. Stable identity, no real bug, but every other widget uses keyed each. Add (t.key) for consistency.
5. PaneFrame drag-guard depends on Select internals (Logic [W6])
template/src/widgets/mosaic/ui/PaneFrame.svelte:36-49
closest("[data-select-trigger], …") relies on shared/ui/Select emitting that attribute on its trigger. Verify it does; if not, the drag-guard silently no-ops on the Select's trigger zone. Add a // TODO(select-trigger-marker): confirm shared/ui/Select forwards data-select-trigger if the verification is deferred.
6. Timeline fetch lacks AbortController (Security [W3])
template/src/widgets/timeline/ui/Timeline.svelte:43-66
Slow /api/timeline-events will leave loadingEvents=true for the lifetime of the request. Add AbortController with a timeout (matches the server's 10s GIT_TIMEOUT_MS).
7. Clipboard fallback DOM leak edge case (Security [W2])
template/src/widgets/artifact-panel/ui/ArtifactPanel.svelte:91-108
document.body.removeChild(ta) runs in finally only after ta.select() — if ta.select() throws (rare; iOS Safari), the textarea is leaked. Wrap from ta.select() inside the try. Already has TODO(clipboard-fallback).
Acceptance
Each item resolved or marked as a TODO with a tracking issue. Single PR is fine.
Audit traceability
- Reviewers: Logic, Frontend, Security
Source: PRD-018 SC-2 audit — minor warnings consolidated.
A handful of small, low-risk cleanups across the migrated files. Bundling them into one issue.
1. Silent try/catch needs FIXME (rule 10)
template/src/widgets/timeline/ui/Timeline.svelte:97-105releasePointerCaptureis wrapped intry { … } catch {}without a comment. Per.claude/rules/10-comments-policy.md, suppressed errors require// FIXME(reason): …. Add:// FIXME(pointer-capture-race): release may throw if onPointerDown was preempted by capture transfer2. Inline
<span class="kind">re-implements Badge (Arch [W13])template/src/widgets/insights-rail/ui/InsightsRail.svelte:647-655The widget uses
<Badge variant="ghost" size="sm" class="kind">correctly elsewhere (e.g. ArtifactPanel.svelte:188). Replace the inline<span class="kind">with the same<Badge>(afterBadge tone="mono"lands — see rule-24 cleanup tracker).3. InsightsRail double-call of
t.badge()(Logic [W3], Frontend [W10])template/src/widgets/insights-rail/ui/InsightsRail.svelte:97{#if t.badge() !== null && t.badge() !== 0} <Badge ...>{t.badge()}</Badge> {/if}Three calls per tab per render. Use
{@const}:{#each TABS as t (t.key)} {@const n = t.badge()} ... {#if n !== null && n !== 0}<Badge ...>{n}</Badge>{/if} {/each}Also:
n !== 0check is dead (badge: () => x.length || nullalready collapses 0 → null). Drop one.4. Missing key on InsightsRail
{#each TABS}(Frontend [W7])Same file, line 89. Stable identity, no real bug, but every other widget uses keyed each. Add
(t.key)for consistency.5. PaneFrame drag-guard depends on Select internals (Logic [W6])
template/src/widgets/mosaic/ui/PaneFrame.svelte:36-49closest("[data-select-trigger], …")relies onshared/ui/Selectemitting that attribute on its trigger. Verify it does; if not, the drag-guard silently no-ops on the Select's trigger zone. Add a// TODO(select-trigger-marker): confirm shared/ui/Select forwards data-select-triggerif the verification is deferred.6. Timeline fetch lacks AbortController (Security [W3])
template/src/widgets/timeline/ui/Timeline.svelte:43-66Slow
/api/timeline-eventswill leaveloadingEvents=truefor the lifetime of the request. AddAbortControllerwith a timeout (matches the server's 10sGIT_TIMEOUT_MS).7. Clipboard fallback DOM leak edge case (Security [W2])
template/src/widgets/artifact-panel/ui/ArtifactPanel.svelte:91-108document.body.removeChild(ta)runs infinallyonly afterta.select()— ifta.select()throws (rare; iOS Safari), the textarea is leaked. Wrap fromta.select()inside the try. Already hasTODO(clipboard-fallback).Acceptance
Each item resolved or marked as a TODO with a tracking issue. Single PR is fine.
Audit traceability