Skip to content

RPS V1 PR4: Wall Detective-pack — brush-to-pin + missing-evidence panel#149

Merged
jukka-matti merged 13 commits into
mainfrom
response-path-system-v1
May 9, 2026
Merged

RPS V1 PR4: Wall Detective-pack — brush-to-pin + missing-evidence panel#149
jukka-matti merged 13 commits into
mainfrom
response-path-system-v1

Conversation

@jukka-matti
Copy link
Copy Markdown
Owner

Summary

Closes Wall Detective-pack gap #2 (per spec §6 D12) and lands the rule-driven "Missing Evidence — the Detective Move Nobody Ships" panel (spec §5 cat 2 + vision slide 3).

4 architectural moves:

  • ChartSelection discriminated union — new core type unifying I-Chart range + Boxplot category as one selection abstraction (packages/core/src/findings/chartSelection.ts)
  • FindingSource.ichart.brushedRange — additive optional field; migration-preserved; existing consumers unchanged
  • BrushToFindingFlow render-prop — confirmation popover → store-direct useInvestigationStore.getState().addFinding(...) + connectFindingToHub. F5 will subscribe addFinding to HubAction persistence; we don't dispatch FINDING_ADD here
  • MissingEvidenceDigest → rule-driven MissingEvidencePanelgaps/gapsByHubId props removed from WallCanvasProps; WallCanvas now computes surveyHints internally via surveyWallRules; hasGap derives from data-collection hint set. PWA + Azure consumers refactored in same PR per feedback_no_backcompat_clean_architecture. FRAME's gapDetector (different scope) untouched.

Survey rule cat 2 (data-collection) added to surveyWallRules — fires for 'evidenced' hypotheses (1 evidence type), suggests the missing 2 to triangulate.

Per-chart gestures: I-Chart drag → range; Boxplot tap → category. New hooks useIChartBrush + useBoxplotSelect. Pointer-capture + clamping + zero-width-drag rejection.

E2E deferred to follow-up — investigation state is session-only with no test hook today; future-anchor test.skip + decision-log entry cover the rationale. Unit coverage is comprehensive (5 test files).

Spec: `docs/superpowers/specs/2026-05-09-response-path-system-v1-design.md`
Plan: `docs/superpowers/plans/2026-05-09-response-path-system-v1.md` (PR-RPS-4 section)
Architectural refinements: `/Users/jukka-mattiturtiainen/.claude/plans/implement-pr-rps-4-per-greedy-mitten.md`

Test plan

  • `pnpm --filter @variscout/core test` — 3334 pass
  • `pnpm --filter @variscout/ui test` — 1843 pass
  • `pnpm --filter @variscout/hooks test` — 1156 pass
  • `pnpm --filter @variscout/ui build` — green (catches cross-package type-export gaps per `feedback_ui_build_before_merge`)
  • `bash scripts/pr-ready-check.sh` — all checks passed
  • Spec compliance + code quality review per task (subagent-driven-development)
  • Final Opus cross-cutting review — READY WITH NON-BLOCKING FOLLOW-UPS (2 bundled into 85d3f4e)
  • `--chrome` walk on Azure app — manual verification of the brush gesture + panel rendering

Decision-log entries (in this PR)

  • 2026-05-09 — `FindingSource.ichart.brushedRange` added for brush-to-pin findings
  • 2026-05-09 — `MissingEvidenceDigest` superseded by SurveyHint-driven `MissingEvidencePanel` on Wall
  • 2026-05-09 — PR-RPS-4 Wall brush-to-pin: automated Playwright E2E deferred

After merge

jukka-matti and others added 13 commits May 9, 2026 19:47
Introduces ChartSelection discriminated union (range | category) used
by the brush-to-pin Finding flow starting in PR-RPS-4. Exported from
@variscout/core/findings sub-path.

Co-Authored-By: ruflo <ruv@ruv.net>
useIChartBrush: pointer-capture drag gesture on SVG → normalized
{startIdx, endIdx} range via onCommit. Zero-width drags (clicks)
drop without firing. useBoxplotSelect: pointer-up on category group
→ sticky selectedCategory + onCommit callback. Both exported from
@variscout/hooks barrel.

Co-Authored-By: ruflo <ruv@ruv.net>
…plot

MiniIChart: optional onBrushEnd prop activates useIChartBrush; renders
amber overlay rect (chartColors.warning) during in-flight drag; touchAction
none prevents scroll-stealing. Read-only behavior preserved when prop absent.

MiniBoxplot: optional onCategorySelect prop activates useBoxplotSelect;
selected category gets dashed amber accent border rect; handlers spread onto
each category <g> only when prop is provided.

Co-Authored-By: ruflo <ruv@ruv.net>
Add optional brushedRange field to the ichart variant so brush-gesture
findings carry the exact index range alongside the midpoint anchorX/Y.
Add round-trip test to verify backward compatibility (no brushedRange)
and the new field (startIdx=12 / endIdx=28 survives JSON round-trip).

Co-Authored-By: ruflo <ruv@ruv.net>
…irect

Render-prop component wrapping mini-chart slots. Holds pendingSelection
state (range | category), shows an inline foreignObject confirmation panel,
and on confirm calls addFinding + connectFindingToHub directly from stores
(F5 will wire HubAction dispatch). Cancel via button or Escape clears state.

Adds 7 wall.brush.* i18n keys to all 32 locale files (English values;
other locales fall back per shared plan pattern). Persisted finding text
uses locale-independent English summaries. 6 tests covering happy-path,
cancel, Escape, boxplot path, and no-factor fallback.

Co-Authored-By: ruflo <ruv@ruv.net>
…hedRange in migration + HypothesisCard test stores mock

- BrushToFindingFlow: add aria-modal="true", tabIndex={-1}, and useEffect autofocus so Escape keydown fires in a real browser (not just JSDOM)
- migration.ts: preserve ichart brushedRange across schema migration so brushed findings survive .vrs reload; use Extract<> to narrow union type
- Add packages/core/src/findings/__tests__/migration.test.ts covering brushedRange preservation + backward compat + migrateFindingStatus + migrateActionAssignee
- HypothesisCard *.test.tsx: add @variscout/stores passthrough mock in all 3 test files so adding rows/columnTypes props can't silently break with store initialisation errors

Co-Authored-By: ruflo <ruv@ruv.net>
Emit a `data-collection` SurveyHint for every hypothesis whose derived
status is `evidenced` (exactly 1 evidence type), naming the present type
and the 2 missing types analysts should collect to triangulate. Reuses
`deriveHypothesisStatus` as the gate so the rule stays consistent with
the status engine. Adds 6 test cases; promotes `baseH` factory to file
scope so both describe blocks can share it.

Co-Authored-By: ruflo <ruv@ruv.net>
8 test cases: empty hints, irrelevant-kind filter, data-collection render,
triangulation-readiness render, both kinds + expand, kind filter, hub-link
click fires onFocusHub, action label rendered (informative-only V1).

Dashed-amber styling, collapsed by default, severity glyphs, action buttons.

Co-Authored-By: ruflo <ruv@ruv.net>
…Id props

WallCanvas now owns hint computation via surveyWallRules({ hypotheses, findings })
internally. Replaces MissingEvidenceDigest with MissingEvidencePanel at both
render sites (desktop SVG branch + mobile card-list branch). Deletes the old
component + its test. WallCanvas.test updated to trigger panel via evidenced-hub
fixtures instead of explicit gaps prop.

Co-Authored-By: ruflo <ruv@ruv.net>
…ormative button + memoize filter

- Make SurveyContext.hub optional to match JSDoc — Wall rule doesn't consume it; required type contradicted the documented intent and broke WallCanvas tsc
- Add disabled to action button in MissingEvidencePanel (WCAG 2.1 §4.1.2: button must be actionable or marked disabled; V1 handler wiring deferred to V2)
- Wrap filtered hints in useMemo([hints]) to prevent redundant refilter on unrelated parent re-renders

Co-Authored-By: ruflo <ruv@ruv.net>
… skip + decision-log entry

Investigation state (useInvestigationStore) is session-only with no IndexedDB persistence and
no window test hook today; unit coverage is comprehensive (BrushToFindingFlow + hook + chart
tests); manual --chrome walk covers UX. Adds test.skip future-anchor at
apps/azure/e2e/wall-brush-to-pin.spec.ts and decision-log entry dated 2026-05-09.

Co-Authored-By: ruflo <ruv@ruv.net>
…tedAt from migration test factory

Co-Authored-By: ruflo <ruv@ruv.net>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
mean-beoynd-lite-pwa Ready Ready Preview, Comment May 9, 2026 6:59pm
variscout_website Ready Ready Preview, Comment May 9, 2026 6:59pm

@jukka-matti jukka-matti merged commit f2d42fe into main May 9, 2026
3 checks passed
@jukka-matti jukka-matti deleted the response-path-system-v1 branch May 9, 2026 19:03
jukka-matti added a commit that referenced this pull request May 13, 2026
…80, log shipment

All 10 PRs of Response Path System V1 merged on main 2026-05-09 → 2026-05-13
(#144 / #147 / #148 / #149 / #150 / #151 / #152 / #153 / #154 / #155). This
commit syncs tracking docs that the squash merges left stale:

- docs/roadmap.md: PR-RPS-9 + PR-RPS-10 SHIPPED rows; flip §3 to "10 of 10";
  free up ADR-080 slot from the 8f canvas viewport item (taken by Sustainment)
- docs/decision-log.md: pin "2026-05-13 — RPS V1 SHIPPED — full lifecycle live"
- docs/07-decisions/adr-080-sustainment-auto-fire-pattern.md (new): document
  the Sustainment-shaped lifecycle pattern (auto-fire + Inbox prompt +
  signoff tier gate) as a pattern reference for future response-path
  lifecycles, per plan §PR-RPS-9 ledger line 2231
- docs/07-decisions/index.md: add rows 078 / 079 / 080 (078+079 also weren't
  indexed when shipped)
- Spec + plan frontmatter: draft/active → delivered, last-reviewed 2026-05-13

Co-Authored-By: ruflo <ruv@ruv.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant