mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
Remove unread Patrol summaryStats and its audit rule
usePatrolIntelligenceState() still returned summaryStats, a closure that
counted critical, warning and active Patrol findings plus fixed outcomes.
Its only reader was PatrolIntelligenceSummary.tsx, deleted in 27ba85ddc6
(2026-06-23). A type-checker scan of the whole program (src and tests)
finds no reference to the member outside the hook's return object, and
nothing spreads, iterates or index-reads the returned state, so the
closure and its return entry go.
The canonical-patrol/no-local-summary-card-presentation rule in
canonical-platform-audit.mjs matched only text shaped like that card's
tint ternaries on summaryStats().criticalFindings, warningFindings and
fixedCount, and told authors to use patrolSummaryPresentation, which no
longer holds any summary-card presentation. With the accessor gone the
rule guards a name nothing can call, so it goes, along with the three
not.toContain guards in frontendResourceTypeBoundaries.test.ts that
pinned the same strings. patrolSummaryPresentation.ts also leaves the
audit allowlist: its remaining recency and verification presenters trip
no rule, and without the entry the audit scans the module like any other
(a planted "Loading messages..." string is now reported).
The JavaScript output changes only by the removed code. Of 187 dist
files, 94 are byte-identical and 92 differ only in chunk-hash references
and SRI strings. In the AIIntelligence chunk, after normalising hashes
and short identifiers, the only residual is the summaryStats closure and
its entry in the returned state. The bundle-size check passes. The Patrol
Inbox, Activity and Protection tabs render without console errors at
desktop and phone widths.
The contracts now record that the hook derives no client-side severity
tally, that the page's open-issue severity counts come from the This week
card's digest read, and that the audit carries no Patrol summary-card
rule. The patrol-intelligence section-owner sentence named a summary
surface that no longer exists; it now names the live tab panels.
Contract-Neutral: Only residual guard demand is the platform support manifest frontend projection proof that the canonical-platform-audit.mjs path policy names (resource.test.ts, sourcePlatformOptions.test.ts, sourcePlatforms.test.ts). This commit deletes a Patrol summary-card rule and one allowlist entry and leaves the projection sync check untouched, so editing those tests would be fabricated proof. patrol-intelligence, api-contracts and frontend-primitives carry substantive notes, and frontendResourceTypeBoundaries.test.ts is the staged patrol page-and-state proof.
This commit is contained in:
@@ -3325,6 +3325,7 @@ a new API state machine, queue contract, or verification-accounting field.
|
||||
action artifact so the Assistant runtime can refresh finding and action posture
|
||||
from IDs and safe summaries instead of relying on pasted chat text
|
||||
and the dedicated `frontend-modern/src/stores/aiIntelligenceSummaryModel.ts` owner, so recent-change counts and governed policy-posture fallbacks normalize once at the shared store boundary instead of as Patrol-hook-local payload repair
|
||||
and the Patrol findings list the state hook reads from `aiIntelligenceStore.patrolFindings`, so `usePatrolIntelligenceState.ts` does not re-derive page-level severity tallies from it: the hook's unread `summaryStats` tally has been removed, the hook derives no client-side severity tally from that list today (the backend's per-severity `findings_count` reaches it only inside the AI summary payload it passes through), and the Activity tab's `This week` card takes its open-by-severity counts from `GET /api/ai/patrol/digest` instead of recounting that list
|
||||
and the shared `frontend-modern/src/components/Infrastructure/ResourceCorrelationSummary.tsx` card, so learned correlations and correlation context stay rendered through one governed frontend card instead of separate page-local list loops
|
||||
and the same shared correlation card's ordering and truncation rule, so callers pass raw correlations instead of encoding their own top-N sort behavior
|
||||
and the shared `frontend-modern/src/components/Infrastructure/ResourceChangeSummary.tsx` and `frontend-modern/src/components/Infrastructure/ResourceCorrelationSummary.tsx` cards' optional `buildResourceHref` input, so a surface that needs resource-filter links passes them into the shared card instead of rebuilding infrastructure URLs inline; the cards carry no link default since the cross-resource drilldown links were retired, and render resource labels as plain text
|
||||
|
||||
@@ -4901,6 +4901,16 @@ or not fully verified.
|
||||
The same empty-state helper must consume Patrol trust-history evidence so a
|
||||
historical regression reads as history review context, not as a current issue
|
||||
and not as a healthy all-clear.
|
||||
`frontend-modern/scripts/canonical-platform-audit.mjs` carries no Patrol
|
||||
summary-card rule. Its `canonical-patrol/no-local-summary-card-presentation`
|
||||
regex matched only text shaped like the deleted summary card's tint ternaries
|
||||
on `summaryStats().criticalFindings`, `warningFindings` and `fixedCount`. The
|
||||
Patrol state hook's `summaryStats` accessor has had no reader since that card
|
||||
was deleted, so the accessor and the rule are both gone.
|
||||
`frontend-modern/src/utils/patrolSummaryPresentation.ts` is off the audit
|
||||
allowlist too: it now holds only the recency and verification presenters,
|
||||
which no audit rule needs to exempt, so the audit scans it like any other
|
||||
module.
|
||||
The Patrol page renders no summary shell today. If one returns, the same
|
||||
hierarchy applies inside it: once its primary assessment strip states Patrol's
|
||||
current risk and verification basis,
|
||||
|
||||
@@ -1508,15 +1508,29 @@ provider/settings affordances.
|
||||
The feature surface now also keeps the same shell/runtime split internally:
|
||||
`frontend-modern/src/features/patrol/PatrolIntelligenceSurface.tsx` owns feature
|
||||
composition, the Patrol-owned section files under
|
||||
`frontend-modern/src/features/patrol/` own the header, banner, summary, and
|
||||
workspace render surfaces, and
|
||||
`frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts` owns Patrol
|
||||
state, transport, polling, and effect lifecycle. The shell and section surfaces
|
||||
must not re-accumulate Patrol API calls, timer orchestration, or store refresh
|
||||
semantics, and `frontend-modern/src/stores/aiIntelligenceSummaryModel.ts` now
|
||||
`frontend-modern/src/features/patrol/` own the header, banner, workspace, and
|
||||
tab-panel render surfaces (the Inbox attention list, Protection objectives, and
|
||||
the Activity tab's `This week` digest and recent work), and
|
||||
`frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts` owns the
|
||||
page's shared Patrol state, transport, polling, and effect lifecycle. The shell
|
||||
and the header, banner, and workspace surfaces must not re-accumulate those
|
||||
Patrol API calls, timer orchestration, or store refresh semantics; the
|
||||
attention list, objectives, recent work, and `This week` panels each own their
|
||||
own typed read and refresh instead, and `frontend-modern/src/stores/aiIntelligenceSummaryModel.ts` now
|
||||
owns the canonical summary normalization so Patrol consumers inherit one
|
||||
governed recent-change and policy-posture snapshot instead of reintroducing
|
||||
hook-local fallback logic.
|
||||
The hook no longer returns the summary card's severity and fix tallies. Its
|
||||
`summaryStats` accessor (critical, warning, and total active findings plus
|
||||
fixed outcomes, counted client-side over the Patrol findings list) lost its
|
||||
only reader when the Patrol summary card was deleted and has been removed,
|
||||
together with the `canonical-patrol/no-local-summary-card-presentation` rule in
|
||||
`frontend-modern/scripts/canonical-platform-audit.mjs`, whose regex matched only
|
||||
text shaped like the deleted card's tint ternaries on
|
||||
`summaryStats().criticalFindings`, `warningFindings` and `fixedCount`. The open-issue severity counts the page shows today come from
|
||||
the Activity tab's `This week` card, which reads them from
|
||||
`GET /api/ai/patrol/digest` (see that card's section below); a count surface
|
||||
that returns must not revive a hook-local tally of the findings list.
|
||||
That same Patrol hook boundary now consumes shared AI settings/model truth
|
||||
through `frontend-modern/src/stores/aiRuntimeState.ts` instead of mounting its
|
||||
own `/api/settings/ai` or `/api/ai/models` reads. Patrol-specific state still
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"version": 1,
|
||||
"base_sha": "421d1e5423e5b83b7923ea8c3b133ad520cd5f60",
|
||||
"verified_at": "2026-10-07T15:23:47Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/features/patrol/usePatrolIntelligenceState.ts": "0fef3795b2a6e2bcb1a979583deceeabd8536868adcb08eb383425dd97bb85ad"
|
||||
},
|
||||
"routes": [
|
||||
"/patrol",
|
||||
"/patrol (Activity tab)",
|
||||
"/patrol (Protection tab)",
|
||||
"/patrol?attention=<first attention row>"
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
"width": 1440,
|
||||
"height": 900
|
||||
},
|
||||
{
|
||||
"width": 390,
|
||||
"height": 844
|
||||
}
|
||||
],
|
||||
"states": [
|
||||
"Embedded production build of this tree (vite build into internal/api/frontend-modern/dist, go build) on a private DEMO_MODE mock stack (port 7693, fresh data dir, telemetry off).",
|
||||
"Inbox: tablist Inbox/Protection/Activity with Inbox selected; '50 decisions need you' attention list with 5 rows (for example 'Open clickhouse-2 · Docker container memory limit'); header recency line 'Last check: just now · checked 1377 resources'.",
|
||||
"Activity: 'This week' digest card ('Patrol runs 11', 'New issues 6', '6 still open (2 critical, 4 warning)') above Recent work; Protection panel renders.",
|
||||
"No console errors and no page errors at either width.",
|
||||
"Dist proof against the parent tree (built at 333e51d2de, whose frontend-modern tree is identical to the parent 421d1e5423): 187 files each side; 94 byte-identical, 92 differ only in chunk-hash references and SRI strings; only assets/AIIntelligence-*.js differs in code, and after normalising hashes and 1-3 character identifiers its only residual is the removed summaryStats closure and its summaryStats entry in the returned state object. check-bundle-size.mjs passes."
|
||||
],
|
||||
"interactions": [
|
||||
"Demo auto sign-in, navigate to /patrol, read the header and Inbox attention rows.",
|
||||
"Click the first attention row: URL gains ?attention=<id> and the detail panel opens; Escape, reload /patrol.",
|
||||
"Click Activity, Protection, then Inbox tabs; Inbox re-selects.",
|
||||
"Same script in a 1440x900 desktop context and a 390x844 phone context; screenshots of Inbox, opened row and Activity inspected at both widths."
|
||||
]
|
||||
}
|
||||
@@ -130,7 +130,6 @@ const ALLOWLIST = new Set([
|
||||
'src/utils/remediationPresentation.ts',
|
||||
'src/utils/patrolEmptyStatePresentation.ts',
|
||||
'src/utils/patrolRunPresentation.ts',
|
||||
'src/utils/patrolSummaryPresentation.ts',
|
||||
'src/utils/rbacPresentation.ts',
|
||||
'src/utils/rbacPermissions.ts',
|
||||
'src/utils/systemLogsPresentation.ts',
|
||||
@@ -581,13 +580,6 @@ const HELPER_RULES = [
|
||||
message:
|
||||
'Do not define local AI quickstart credits badge presentation in page code. Use @/utils/aiQuickstartPresentation instead.',
|
||||
},
|
||||
{
|
||||
rule: 'canonical-patrol/no-local-summary-card-presentation',
|
||||
regex:
|
||||
/\bsummaryStats\(\)\.criticalFindings\s*>\s*0\b[\s\S]{0,320}bg-red-50[\s\S]{0,320}text-red-600|\bsummaryStats\(\)\.warningFindings\s*>\s*0\b[\s\S]{0,320}bg-amber-50[\s\S]{0,320}text-amber-600|\bsummaryStats\(\)\.fixedCount\s*>\s*0\b[\s\S]{0,320}bg-green-50[\s\S]{0,320}text-green-600/g,
|
||||
message:
|
||||
'Do not define local patrol summary card presentation in page code. Use @/utils/patrolSummaryPresentation instead.',
|
||||
},
|
||||
{
|
||||
rule: 'canonical-patrol/no-local-empty-state-copy',
|
||||
regex:
|
||||
|
||||
@@ -916,24 +916,6 @@ export function usePatrolIntelligenceState() {
|
||||
window.history.replaceState(window.history.state, '', nextPath);
|
||||
}
|
||||
|
||||
const summaryStats = () => {
|
||||
const patrolFindings = allPatrolFindings();
|
||||
const activeFindings = patrolFindings.filter((finding) => finding.status === 'active');
|
||||
|
||||
return {
|
||||
criticalFindings: activeFindings.filter((finding) => finding.severity === 'critical').length,
|
||||
warningFindings: activeFindings.filter((finding) => finding.severity === 'warning').length,
|
||||
totalActive: activeFindings.length,
|
||||
fixedCount: patrolFindings.filter(
|
||||
(finding) =>
|
||||
finding.investigationOutcome === 'fix_verified' ||
|
||||
finding.investigationOutcome === 'fix_executed' ||
|
||||
finding.investigationOutcome === 'resolved',
|
||||
).length,
|
||||
hasAnyPatrolFindings: patrolFindings.length > 0,
|
||||
};
|
||||
};
|
||||
|
||||
const activePatrolFindings = () =>
|
||||
allPatrolFindings().filter((finding) => finding.status === 'active');
|
||||
const shouldShowPatrolSetupOnly = createMemo(() => {
|
||||
@@ -1134,7 +1116,6 @@ export function usePatrolIntelligenceState() {
|
||||
showBlockedBanner,
|
||||
showReadinessBanner,
|
||||
shouldShowPatrolSetupOnly,
|
||||
summaryStats,
|
||||
triggerPatrolDisabledReason,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3649,15 +3649,6 @@ describe('frontend resource type boundaries', () => {
|
||||
'historicalRegressionCount={state.historicalRegressionCount()}',
|
||||
);
|
||||
expect(patrolIntelligenceBannersSource).not.toContain('trackUpgradeClicked');
|
||||
expect(patrolIntelligenceSurfaceSource).not.toContain(
|
||||
"summaryStats().criticalFindings > 0\n ? 'bg-red-50 dark:bg-red-900/25 border-red-200 dark:border-red-800'",
|
||||
);
|
||||
expect(patrolIntelligenceSurfaceSource).not.toContain(
|
||||
"summaryStats().warningFindings > 0\n ? 'bg-amber-50 dark:bg-amber-900/25 border-amber-200 dark:border-amber-800'",
|
||||
);
|
||||
expect(patrolIntelligenceSurfaceSource).not.toContain(
|
||||
"summaryStats().fixedCount > 0\n ? 'bg-green-50 dark:bg-green-900/25 border-green-200 dark:border-green-800'",
|
||||
);
|
||||
expect(patrolIntelligenceSurfaceSource).not.toContain(
|
||||
"(patrolStatus()?.quickstart_credits_remaining ?? 0) > 0\n ? 'bg-blue-50 dark:bg-blue-950/25 border-blue-200 dark:border-blue-800 text-blue-700 dark:text-blue-300'",
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user