mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Drop Patrol state members no surface reads (#2695)
`usePatrolIntelligenceState()` returned 18 members that no file outside the hook reads. A TypeScript checker scan of src and tests found no readers and no spread, computed or `Object.*` escapes of the state object. Several were also dead inside the hook. ## Change - **Return object.** Drops activePatrolFindings, activityRefreshTrigger, acceptedManualRunId, assistantHandoffFindingId, circuitBreakerStatus, fullModeUnlocked, initialSurfaceReady, isRefreshing, loadAllData, openAssistantOperationsLoopForFinding, the four decision/outcome counts, both work-evidence counts, recordPatrolWorkflowStarterActivity and setFullModeUnlocked, plus handleAssistantFindingHandoff (see below). - **Dead locals.** Removes the write-only signals (initialSurfaceReady, isRefreshing, fullModeUnlocked, assistantHandoffFindingId), the 15 s background refresh timeout that only reset isRefreshing, the unread memos, and the never-called `openAssistantOperationsLoopForFinding`. That last one was a second copy of the handoff `FindingsPanel` already performs. Locals still used inside the hook (activePatrolFindings, loadAllData, activityRefreshTrigger, acceptedManualRunId) stay. - **Test-only exports.** `openPatrolAssistantWorkflowHandoff` and `recordPatrolWorkflowStarterActivity` were used only by that dead path and by their own tests, so they go. - **Workspace.** `handleAssistantFindingHandoff` only wrote the unread handoff signal, so `PatrolIntelligenceWorkspace` no longer passes `FindingsPanel` an `onAssistantHandoff` callback. The prop is optional. - **Tests.** Raw-source pins on removed code are dropped. The manual-sync timeout test now pins the Retry path's own generation guard; a mutation of its timeout fails it. The non-blocking starter test now exercises `recordPatrolControlStarterActivity`. - **Contracts.** - patrol-intelligence said a finding-to-Assistant handoff *must* record a `pulse_patrol` workflow starter. Only the dead path did that; the live `FindingsPanel` handoff never has, so `pulse_patrol` has no browser producer. The clause now says that and keeps the content-free rules as a condition. - The "local Patrol state must expose work evidence" sentence no longer requires counts nothing reads. - Three refresh clauses that described a header refresh action now name the stale-data Retry, the only operator refresh left. - api-contracts and frontend-primitives record that `FindingsPanel` owns the handoff. ## Not in this PR The store still fetches `GET /api/ai/circuit/status` for nothing. That removal is a follow-up after #2677, because it edits the same lines. ## Evidence - Production builds before and after compared with chunk hashes, SRI strings and short identifiers normalised. Only the removed hook code differs, the unused `pulse_patrol` constant drops out of `aiChat.js`, and `index.js` reorders the same preload list. `check-bundle-size.mjs` passes. - Private demo-mode stacks for both builds, driven by the same Playwright script at 1440x900 and 390x844: Patrol load, Activity > Finding options and history, Open in Assistant (drawer opens with the finding), tab hide/show, and the forced stale-data banner plus Retry. Each phase hit the same `/api` endpoints on both builds, and neither build had console errors. - `tsc --noEmit`, eslint, and vitest for `src/features/patrol`, `AIIntelligence.test.tsx`, `frontendResourceTypeBoundaries.test.ts` and `FindingsPanel.test.ts` pass, as does the full pre-commit battery. Stacked on #2687 (which carries #2682 and #2686). Until those merge, this PR shows their commits too. `git merge-tree` is clean against main, #2690, #2677 and #2691.
This commit is contained in:
@@ -3326,6 +3326,7 @@ a new API state machine, queue contract, or verification-accounting field.
|
||||
and any frontend presentation of the AI summary's `policy_posture` counts, which must render that canonical snapshot through one shared component instead of page-local posture loops; no frontend surface renders those counts today, and the resource drawer stays on per-resource policy lines
|
||||
and the dedicated `frontend-modern/src/features/patrol/patrolInvestigationContextModel.ts` owner, so if Patrol recent-change, learned-correlation, or policy-coverage summary text returns, it is derived from the canonical AI payload in that one place instead of as hook-local count and pluralization logic; Patrol renders no such summary today and the model carries no such derivation
|
||||
and the Watch-only forward-path handoffs owned by `frontend-modern/src/features/patrol/patrolControlPresentation.ts` together with the Actions inbox empty-state read of `GET /api/ai/patrol/autonomy`, so finding-level and inbox-level mode guidance consumes the canonical Patrol autonomy read/save contract through the Patrol state hook (`handleAutonomyChange`) instead of introducing a second mode mutation path or a page-local autonomy dialect
|
||||
and the Patrol finding-to-Assistant handoff owned by `frontend-modern/src/components/AI/FindingsPanel.tsx`, so the pending-approval, investigation, and proposed-fix reads behind that handoff happen once in the panel instead of in a second, unwired copy inside the Patrol state hook
|
||||
and that same Patrol investigation-context owner, so visible Assistant
|
||||
drawer handoffs may include live pending-approval metadata only as safe
|
||||
operator context: approval ID, status, risk, requested/expiry timestamps,
|
||||
|
||||
@@ -3767,11 +3767,11 @@ production table, router and styles; it does not qualify full-app scrolling.
|
||||
assessment readout, but shared drawer/chrome primitives stay free of
|
||||
the `FindingsTrustSummary` shape so adding new trust signals goes
|
||||
through the contract first rather than per-shell branching.
|
||||
Patrol header refresh controls stay on that same feature-owned shell
|
||||
Patrol refresh controls stay on that same feature-owned shell
|
||||
boundary: `frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts`
|
||||
must make the refresh affordance generation-aware and timeout-bounded, so
|
||||
a slow supporting intelligence read cannot permanently disable the shared
|
||||
Patrol header control while Patrol findings and status remain visible.
|
||||
a slow supporting intelligence read cannot permanently disable the
|
||||
stale-data Retry control while Patrol findings and status remain visible.
|
||||
That feature-owned
|
||||
presentation helper is the single emitter for investigation-record
|
||||
`impact` and `rollback` fields: when an investigation record exists but those fields
|
||||
@@ -3915,6 +3915,10 @@ production table, router and styles; it does not qualify full-app scrolling.
|
||||
finding-presentation destinations such as the Patrol provider-settings
|
||||
route, while `patrol_autonomy` and legacy Pro activation URLs remain parser
|
||||
aliases only and verified review links use the plain Patrol history anchor.
|
||||
The Patrol finding-to-Assistant handoff has one owner,
|
||||
`frontend-modern/src/components/AI/FindingsPanel.tsx`; the Patrol state
|
||||
hook keeps no second copy of it, and the Patrol workspace passes no
|
||||
handoff callback because nothing on the page reacts to a handoff.
|
||||
UI surfaces must not duplicate the `patrolControlStarter` query string or
|
||||
write Patrol control or legacy entry-point starter telemetry from local
|
||||
click handlers.
|
||||
@@ -6856,7 +6860,7 @@ That same Patrol shell ownership includes refresh affordance state:
|
||||
`frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts` must keep
|
||||
operator refresh controls generation-aware, timeout-bounded, and separate from
|
||||
background polling state, so a slow supporting intelligence read cannot make the
|
||||
shared Patrol header Refresh Patrol action spin indefinitely or stay disabled
|
||||
Patrol stale-data Retry action spin indefinitely or stay disabled
|
||||
while Patrol findings and status remain visible.
|
||||
Neither the Patrol load and poll path (the store's `loadDashboardData` bundle)
|
||||
nor the Retry path's background supporting reads fetch the global
|
||||
|
||||
@@ -329,13 +329,14 @@ or historical proof/counting for resolved-only work.
|
||||
shared parent node, or explicit correlated finding IDs. Grouping must not
|
||||
infer causality from title or description prose, and the queue's affected
|
||||
resource count must continue to count canonical resources rather than
|
||||
visual groups. Because a
|
||||
contextual Assistant handoff from that workflow is still a first-party Patrol
|
||||
starter for the same governed journey, it must record content-free workflow
|
||||
prompt activity through the shared marker route with the `pulse_patrol`
|
||||
surface before the drawer opens; it must not include finding IDs, prompt
|
||||
text, resource context, model output, or direct-action payloads in that
|
||||
marker.
|
||||
visual groups. A contextual Assistant handoff from that workflow opens
|
||||
through `frontend-modern/src/components/AI/FindingsPanel.tsx` and records no
|
||||
workflow starter today, so the first-party `pulse_patrol` marker has no
|
||||
browser producer. If that handoff starts recording one, it must write
|
||||
content-free workflow prompt activity through the shared marker route with
|
||||
the `pulse_patrol` surface before the drawer opens, with no finding IDs,
|
||||
prompt text, resource context, model output, or direct-action payloads in
|
||||
that marker.
|
||||
A compact Patrol work-group row may appear above the list only when it adds
|
||||
cross-source current-work grouping that the row title alone cannot express:
|
||||
pending approvals, failed governed actions, a failed/latest Patrol check,
|
||||
@@ -471,8 +472,11 @@ or historical proof/counting for resolved-only work.
|
||||
compact progress label must describe current work state (`ready`, `needs
|
||||
attention`, `approval needed`, `outcome verified`, `no active work`) instead
|
||||
of repeating the selected mode; the Patrol mode selector/header
|
||||
owns current-mode copy, and local Patrol state must expose work evidence as
|
||||
owns current-mode copy, and any local Patrol work evidence must be
|
||||
Patrol-owned issue/work counts rather than legacy proof counts.
|
||||
No Patrol surface reads issue-evidence, governed-action decision, or
|
||||
verified-outcome counts today, so `usePatrolIntelligenceState.ts` computes
|
||||
none of them.
|
||||
When no active finding or pending approval remains, terminal verified or
|
||||
rejected outcomes must read as history behind a `no active work` current
|
||||
state; current-state copy must not ask operators to reconcile old approved
|
||||
@@ -771,12 +775,12 @@ attention`, `approval needed`, `outcome verified`, `no active work`) instead
|
||||
only block the selected run view while the run references finding ids that
|
||||
still need the direct Patrol findings payload.
|
||||
Patrol page refresh state must also separate background data loads from the
|
||||
operator-clicked Update status action: slow or stalled supporting
|
||||
intelligence reads may continue in the background, but they must not make the
|
||||
shared header action spin or stay disabled once Patrol findings and status
|
||||
remain visible. The header action is a status/history sync affordance; it
|
||||
must not read like another Patrol run or imply that it changes
|
||||
infrastructure.
|
||||
operator-clicked Retry on the stale-data banner: background polls hold no
|
||||
busy state, and slow or stalled supporting intelligence reads may continue
|
||||
in the background, but they must not make Retry spin or stay disabled once
|
||||
Patrol findings and status remain visible. Retry is a status/history sync
|
||||
affordance; it must not read like another Patrol run or imply that it
|
||||
changes infrastructure.
|
||||
Patrol trigger-status copy in the default header and activity strip must stay
|
||||
actionable. Runtime policy pauses for alert/anomaly-triggered background
|
||||
checks, such as the local development safety guard, may explain a blocked
|
||||
|
||||
Reference in New Issue
Block a user