diff --git a/docs/release-control/v6/internal/subsystems/api-contracts.md b/docs/release-control/v6/internal/subsystems/api-contracts.md index e2fa3fb1fe..8ca4f91a91 100644 --- a/docs/release-control/v6/internal/subsystems/api-contracts.md +++ b/docs/release-control/v6/internal/subsystems/api-contracts.md @@ -7141,12 +7141,14 @@ introducing VMware-only mention payloads or provider-local inventory reads under `/api/vmware/*`. Runtime-specific container/app mentions remain shared unified-resource mentions as well; VMware network inventory does not create a provider-local mention family. -That same `/api/ai/chat` payload boundary owns per-request execution-mode -overrides. Dashboard Pulse Brief and other scoped handoffs may include -`autonomous_mode:false` on the chat request to force approval-required command -execution for that exchange, but the transport must treat the field as a -request override only and must not mutate the user's persistent AI control -setting. +That same `/api/ai/chat` payload boundary owns request-local execution mode, +and the server sets it. `ChatRequest` in `internal/api/ai_handler.go` has no +`autonomous_mode` field, so the `autonomous_mode:false` that scoped handoffs +such as an explain-this-issue request still send is dropped at decode, and the +handler passes approval-required mode into the chat service for every +exchange; an Autonomous control level runs as Controlled for that request. +That clamp is request-local and must not mutate the user's persistent AI +control setting. That same chat transport boundary owns new-session anchoring. When the request omits `session_id`, the handler may generate and stream a session ID immediately so the browser can anchor the visible turn, but that generated ID is @@ -7199,7 +7201,7 @@ not serialize the model-only `handoff_context`, runtime failure detail, action preflight/result bodies, remediation descriptions, raw commands, or approval command payloads, and it must not preserve Patrol-authored next-step recommendation fields from legacy handoffs. -Patrol finding handoffs are stricter than ordinary chat requests: when a request +Patrol finding handoffs keep that clamp on their own path: when a request carries a non-empty `finding_id` or resolves to model-only Patrol briefing, resource, or action context, `internal/api/ai_handler.go` must clamp the request-local autonomous mode to false even if the caller supplied diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md index c358925b52..20e738b7e5 100644 --- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md +++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md @@ -5123,10 +5123,10 @@ KPI, problem-resource, or card shells. Workload-table and guest-row fallback copy that lives under `frontend-modern/src/components/Workloads/` must keep using `frontend-modern/src/utils/workloadEmptyStatePresentation.ts` and `frontend-modern/src/utils/workloadGuestPresentation.ts`. New route-level empty -states, tone mapping, or compact issue copy must extend the shared -`emptyStatePresentation`, `semanticTonePresentation`, and -`problemResourcePresentation` helpers instead of reviving deleted -dashboard-only KPI, metric, storage, recovery, or trend presentation helpers. +states or tone mapping must extend the shared `emptyStatePresentation` and +`semanticTonePresentation` helpers instead of reviving deleted dashboard-only +KPI, metric, storage, recovery, problem-resource, or trend presentation +helpers. That shell must also stay passive with respect to data ownership: future overview trend cards may render summary-range controls and operator-facing empty or error copy only after they have a governed owner, and they must not @@ -6405,20 +6405,6 @@ rollups, points, or facets payloads arrive, it must keep that selected platform present in the option set so the shared `LabeledFilterSelect` shows the owned value immediately instead of flashing back to `All Platforms` until recovery data warms. -`frontend-modern/src/utils/problemResourcePresentation.ts` now also belongs to -that same dashboard overview boundary so the problem-resource severity contract -stays shared with `ProblemResourcesTable.tsx` instead of floating as an -unowned helper. -Problem-resource table readability belongs to that same owner. Repeated rows -may collapse only when they share the same governed display label, resource -type, and problem signal; the header count and Pulse Brief counts must continue -to represent the underlying affected resources, and grouped links must route to -the broad owning surface rather than inventing a synthetic resource target. -Problem Resources and Pulse Brief wording must not amplify generic -status-shaped names such as `storage (offline)` into first-viewport prose or -grouped-row sublabels; when the resource name is only a type plus status, the -surface should summarize the type-level issue in operator language instead of -repeating raw backend-shaped labels. The retired dashboard action queue must not be reintroduced as a compact Patrol or infrastructure issue panel. Patrol-owned runtime findings remain governed by `frontend-modern/src/utils/aiFindingPresentation.ts` and their diff --git a/docs/release-control/v6/internal/subsystems/unified-resources.md b/docs/release-control/v6/internal/subsystems/unified-resources.md index ee14e0a1a2..7249be9f92 100644 --- a/docs/release-control/v6/internal/subsystems/unified-resources.md +++ b/docs/release-control/v6/internal/subsystems/unified-resources.md @@ -5497,12 +5497,14 @@ wording stays aligned with the drawer's recent-change cards and timeline. Timeline cards in that drawer surface change metadata when it is present, so the history view preserves the richer provenance already carried by the unified-resource model instead of flattening those fields away. -The same Infrastructure resource-only links now also default through the -shared `frontend-modern/src/components/Infrastructure/ResourceChangeSummary.tsx` +The shared `frontend-modern/src/components/Infrastructure/ResourceChangeSummary.tsx` and `frontend-modern/src/components/Infrastructure/ResourceCorrelationSummary.tsx` -cards from the Patrol page, resource drawer, and problem-resource dashboard -panels, so canonical resource-filter path construction stays owned by the -shared summary cards rather than being duplicated per surface. +cards keep resource links behind an optional `buildResourceHref` input with no +default, following the 2026-05-16 cross-resource drilldown retirement above. +The resource drawer passes none, so its change and correlation labels render +as plain text; a surface that needs resource links must pass a platform-route +builder into the shared card rather than rebuilding resource-filter paths per +surface. Platform tables supply the resource-label resolver to the resource drawer through `PlatformResourceDetailTableRow`. `createPlatformResourceLabelResolver(...)` in `frontend-modern/src/features/platformPage/PlatformResourceDetailTableRow.tsx` diff --git a/scripts/release_control/subsystem_lookup_test.py b/scripts/release_control/subsystem_lookup_test.py index ae75d43aa3..b2b903baa8 100644 --- a/scripts/release_control/subsystem_lookup_test.py +++ b/scripts/release_control/subsystem_lookup_test.py @@ -672,6 +672,15 @@ class SubsystemLookupTest(unittest.TestCase): self.assertEqual(file_entry["classification"], "runtime") self.assertEqual(file_entry["matches"], []) + def test_lookup_paths_reports_retired_problem_resource_helper_as_unowned(self) -> None: + path = "frontend-modern/src/utils/problemResourcePresentation.ts" + result = lookup_paths([path]) + self.assertEqual(result["unowned_runtime_files"], [path]) + self.assertEqual(result["impacted_subsystems"], []) + file_entry = result["files"][0] + self.assertEqual(file_entry["classification"], "runtime") + self.assertEqual(file_entry["matches"], []) + def test_lookup_paths_assigns_recovery_points_hook_to_storage_recovery(self) -> None: result = lookup_paths(["frontend-modern/src/hooks/useRecoveryPoints.ts"]) self.assertEqual(result["unowned_runtime_files"], [])