Slice 18 made will_fix_later a real operational commitment server-side, but
the new RemindAt field stayed invisible to operators until the reminder fired
a week later. This wires it through the API surface and renders it where the
operator decides and where they later revisit.
UnifiedFinding (Go and TS) and the Patrol Finding TS shape now carry
RemindAt / remind_at; router.go and AddFromAI mirror it like the other
user-feedback fields. FindingsPanel previews "Pulse will stay quiet for 7
days, then surface again on <date>" on the dismiss confirmation panel before
the operator confirms, badges dismissed-as-will_fix_later rows with
"Reminding <date>" in amber, and adds explanatory copy for the other two
dismissal reasons so all three paths feel deliberate rather than
undifferentiated.
Wire FindingsStore.GetTrustSummary through PatrolService and the
patrol-status API into the Patrol page so the operator can scan
"is Pulse useful?" at a glance. Adds a small Trust strip above the
Findings/Runs tab bar that renders compact signals: fixes verified,
auto-resolved, dismissed-as-noise, dismissed-as-expected, currently
active, and regressed-at-least-once. The strip is hidden when every
signal is zero so a fresh install sees no empty pill.
Plumbing:
- PatrolService.GetFindingsTrustSummary accessor (delegates to the
store-level method shipped in the prior slice)
- PatrolStatusResponse carries Trust *FindingsTrustSummary; populated
from the active patrol service, omitted when no service is available
(snapshot semantics, not lifetime totals)
- TS FindingsTrustSummary mirror in api/patrol.ts and a trust field on
PatrolStatus
- PatrolIntelligenceWorkspace reads state.patrolStatus()?.trust and
conditionally renders the strip
Verification artifacts:
- internal/ai/patrol_test.go: TestPatrolService_GetFindingsTrustSummary
- internal/api/contract_test.go: TestContract_PatrolStatusTrustJSONSnapshot
pinning the canonical wire shape
- frontend-modern/src/api/__tests__/patrol.test.ts: round-trip test for
the trust block on the patrol-status response
- frontend-modern/src/features/patrol/__tests__/PatrolIntelligenceWorkspace.test.ts:
source-text test pinning state.patrolStatus()?.trust read,
aria-label, and field names so future strip additions go through
the FindingsTrustSummary contract first.
- frontend-modern/src/features/patrol/__tests__/patrolInvestigationContextModel.test.ts:
pins that the per-finding context model does not synthesize impact
from trust counters; trust is an aggregate operator-page concern,
not a per-finding text source.
Updates the api-contracts, ai-runtime, patrol-intelligence,
agent-lifecycle, frontend-primitives, and storage-recovery contracts
to pin the trust block's shape, the strip's contract-first rule, and
the scope boundary (trust counters are advisory operator context, not
enrollment/storage/recovery action authority).
The /api/diagnostics handler builds its own test client per PVE node
to run a live connectivity probe. The PBS branch already passed
node.Fingerprint into the test client config, but the PVE branch did
not. With VerifySSL=true and a self-signed Proxmox cert (the standard
configuration), tlsutil.CreateHTTPClientWithTimeout falls into
default-secure mode and validates against the system CA chain, which
fails the handshake even when the actual poller — which DOES pass
the fingerprint — is connecting fine.
The result was that /api/diagnostics reported delly + pi as
"Failed to connect to Proxmox API" while /api/resources was happily
ingesting all 27 workloads from the same hosts. Mirror the PBS
branch by passing node.Fingerprint into the PVE testCfg so the
diagnostic probe uses the same TLS verification path as the runtime
poller.
Add a regression test that spins up an httptest TLS server, captures
its leaf cert SHA-256, configures a PVE instance with VerifySSL=true
and that fingerprint, and asserts computeDiagnostics reports
Connected=true. The pre-fix code fails this with a "tls: bad
certificate" handshake error.
Capture the prior InvestigationRecord.ProposedFix.Description into a
new Finding.PreviousResolvedFixSummary field at regression time, before
the InvestigationRecord is cleared. Without this capture the next
investigation starts from blank context whenever a finding regresses,
and operational memory of "what worked last time" is lost.
The summary propagates through:
- FindingsStore.Add regression branch (capture before clear)
- Finding.MarshalJSON / UnmarshalJSON (wire shape)
- Both Finding to UnifiedFinding conversion sites in router.go
- UnifiedFinding (struct + JSON shadow + Marshal/Unmarshal)
- UnifiedStore.AddFromAI update branch (non-empty overwrite)
- Assistant chat context as a "Previous Resolved Fix" line so the LLM
sees what worked previously rather than blank-slate diagnosing each
regression.
Adds a unit test that walks the full lifecycle (detect, resolve via
UpdateInvestigationRecord + ResolveWithReason, re-detect) and asserts
PreviousResolvedFixSummary is preserved while InvestigationRecord is
cleared, plus two chat-context tests covering the surfaces-when-set and
omits-when-empty cases. Adds a contract test pinning the canonical
"previous_resolved_fix_summary" JSON key. Updates the api-contracts,
ai-runtime, and the dependent agent-lifecycle, performance-and-
scalability, and storage-recovery contracts to pin the operational
memory propagation rule and its scope boundary.
Carry the Finding.Impact text added in the previous slice through the
Finding to UnifiedFinding boundary and onto the FindingsPanel surface
so the runtime-failure consequence-if-ignored copy is visible to the
operator. Add Impact to the UnifiedFinding struct, JSON snapshot, and
both Marshal/Unmarshal mirrors; copy f.Impact into both Finding to
UnifiedFinding conversion sites in router.go; mirror impact in the TS
UnifiedFindingRecord and Finding API types and the aiIntelligence
store normalizers; render an Impact line between Description and
Recommendation in FindingsPanel.
Also fix the FindingsStore.Add dedup-merge path so re-detected findings
overwrite existing.Impact alongside Description and Recommendation
rather than preserving the stale empty value left by an older binary.
Without this fix, a freshly-classified runtime failure with new Impact
text would be merged onto the persisted finding but the Impact field
would be silently dropped.
Verified end-to-end against the live runtime: triggered a Patrol run,
watched the runtime-failure finding regenerate, confirmed the
operator-visible card now renders "Impact: While Patrol cannot
analyze..." between Description and Recommendation. Updates the
api-contracts, ai-runtime, patrol-intelligence, and the dependent
agent-lifecycle, performance-and-scalability, and storage-recovery
contracts to pin the propagation rule and the dedup-merge invariant.
Promote the seven-field investigation-record shape so Patrol findings
can carry consequence-if-ignored context and a record-level rollback
plan alongside the existing verification array. The shared
aicontracts.InvestigationRecord struct gains top-level Impact and
Rollback fields with matching TS mirrors, normalizes Rollback to an
empty slice, and the Patrol-owned investigation surface renders an
explicit "Impact not assessed" / "Rollback not specified" placeholder
so the operator-visible gap is conspicuous to both the operator and
Assistant when Patrol has not populated them. Backend default leaves
both empty rather than fabricating analysis from severity/category.
Also closes the existing Trigger.cause drift between Go and TS so
frontend handoff context preserves backend-attributed failure cause,
and updates the api-contracts, ai-runtime, frontend-primitives, and
patrol-intelligence subsystem contracts to pin the new shape.
- store requester provenance on approval records
- carry requester metadata through approval APIs and Assistant handoffs
- document the safe Patrol approval provenance boundary
- derive approval requester identity from investigation-fix approvals
- stamp pending action-audit lifecycle events with Patrol as the producer
- document the requester boundary for Patrol handoffs and timelines
- force non-empty Patrol finding handoffs into approval-required mode
- add direct helper coverage for finding, scoped, resource, action, and metadata handoffs
- align subsystem contracts with the backend-owned clamp
- mark DeepSeek V4 Flash and Pro tool-ready for Patrol readiness
- resolve synthetic Patrol runtime findings after provider-backed scoped runs
- cover readiness and run-history resolved counts
Separate first-class platform support from Pulse Agent host profiles and classify Unraid as an agent-backed host profile while preserving it as presentation-only platform vocabulary.
- rehydrate Patrol run context from Patrol history for chat requests and follow-up sessions
- send only browser-safe run metadata from the frontend
- classify and redact provider runtime failures in handoff prompts and briefings
Classify Assistant and Patrol provider-test failures through the Patrol runtime failure taxonomy, redact secret-shaped provider evidence, and preserve safe recommendations in the settings shell.
Refs #1463