A permanently-offline derived identity flapped a docker-host alert and wrote 4,748 resolved/refired pairs in three days; each lifecycle event stores a full alert-state snapshot averaging ~170 KB, so events.db reached 1.2 GB and filled the host root filesystem (#2113 downstream evidence). The 90-day age retention is not a volume bound: one alert can still write unbounded payload inside the window.
The hourly prune now also enforces a total stored snapshot-payload cap and removes the oldest events first when it is exceeded, raising the same retention revision age pruning uses so the history projection rebuilds from the remaining log. Normal installs stay far below the cap and are unaffected; the bound only triggers on pathological amplification. Focused proof in eventlog_snapshot_test.go; the alerts subsystem contract records the bound.
Change-source: pulse-maintainer
The five unified syncs ran serially and each waited for its own SQLite commit, so a registry rebuild that carried new data for several resource types opened one transaction per type and re-committed the same WAL. Collect the agent, VM, storage and app-container writes through a batch sink and commit them once; the per-series replay guard still runs first, so the series, values and source observation times are unchanged. Standalone callers keep the immediate write. Focused proof in monitor_host_agents_test.go; contract sections recorded in monitoring.md and agent-lifecycle.md.
Change-source: pulse-maintainer
The unified physical-disk sync now anchors SMART history to the source
observation time and drops exact replays, so the monitoring and
agent-lifecycle contract sections record the disk-history behaviour and its
focused proof. The proof lives in monitor_host_agents_test.go alongside the
other unified-sync rebuild tests.
Change-source: pulse-maintainer
syncUnifiedPhysicalDiskMetrics stamped every SMART sample with the registry rebuild wall clock and wrote through the unguarded buffered path, so each read-side rebuild re-issued the same physical-disk observation as fresh rows (#1966). writeSMARTMetrics now anchors both the in-memory history and the persisted batch to the source observation time and drops exact replays through the existing unified guard; the unified sync passes unifiedResourceObservedAt. Adds a two-rebuild focused proof and updates the TrueNAS disk fixture to a current observation time.
Change-source: pulse-maintainer
The unified syncs now timestamp history with the source observation time, so the TrueNAS and VMware fixtures must carry a current collectedAt for the in-memory and chart windows to retain the samples. The previous fixed 2026-03 fixtures represented data older than the 24h history retention and would be trimmed. No production behaviour changes.
Change-source: pulse-maintainer
The replay guard added in df44238797 only suppressed repeats for storage, whose samples already carry the provider LastSeen. The agent, VM and app-container syncs still stamped every write with the rebuild wall clock, so dedupeUnifiedMetricWrites could never match and each read-side registry rebuild re-issued the whole batch as fresh rows. That is the same WAL churn described in #1966, still live for VMware/TrueNAS VMs, TrueNAS apps and supplemental agents.
Resolve each resource's observation time from its metric source (unifiedResourceObservedAt) and use it for both the in-memory history point and the store write, matching the storage path. Proxmox and libvirt VMs already have native history writers, so exclude libvirt VMs from the unified VM sync to avoid writing a second timeline for the same series.
Contract sections recorded in monitoring.md and agent-lifecycle.md; focused proof added in monitor_polling_test.go and monitor_host_agents_test.go. Local Go compilation is unavailable this turn (module cache read-only, toolchain snapshot missing); the canonical completion guard passes and gofmt is clean.
Change-source: pulse-maintainer
The Windows unified agent exits at startup when HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid is a braced GUID. gopsutil v4.26.6 reads the value through a fixed 74-byte buffer and rejects any length other than 36, so a braced 38-character GUID fails the whole InfoWithContext call and newAgent aborts with 'fetch host info'. Recover the host info on Windows when the host-ID read is the failing field: read MachineGuid directly, strip braces and fill the other fields from gopsutil accessors, while keeping any non-host-ID failure fatal. Canonicalise Windows machine IDs by removing braces so both forms map to one stable agent identity. Includes agent-lifecycle contract section and focused proof in the registry-accepted agent_new_test.go. Windows recovery is cross-compiled with GOOS=windows; runtime execution on Windows is not qualified in this environment.
Change-source: pulse-maintainer
Record the monitoring contract section for the TrueNAS legacy-REST memory telemetry repair and move its regression coverage into the registry-accepted internal/truenas/client_test.go proof file. The runtime commit and this contract/proof follow-up are one reviewed completion unit.
Change-source: pulse-maintainer
On the legacy REST transport used by TrueNAS CORE 13, GetSystemTelemetry had no reporting.realtime subscription, so MemoryAvailableBytes and ARCSizeBytes stayed zero and trueNASEffectiveMemoryUsed collapsed to total, reporting every CORE install as 100% used (#2077). Reconstruct live telemetry and host-chart history from reporting.get_data over REST, and when no available reading exists mark agent memory UsageUnavailable instead of fabricating usage from total-0.
Change-source: pulse-maintainer
The vmware test package defines writeJSON as a function-local closure, so the new request-shape test needs its own package-level helper.
Change-source: pulse-maintainer
The vSphere VI JSON API documents _typeName on request data objects. Calls whose only argument is a bare ManagedObjectReference (QueryPerfProviderSummary, QueryAvailablePerfMetric) succeed against vCenter 8.0.3, but every call that passes a composite data object (PerfQuerySpec/PerfMetricId for QueryPerf, EventFilterSpec/EventFilterSpecByEntity for QueryEvents) is rejected with HTTP 500. Issue #2070 shows exactly that split, so add the discriminators the documented schema carries to those request bodies. Morefs now carry _typeName too, matching the same schema. Focused tests pin the serialized request bodies.
Change-source: pulse-maintainer
The vSphere JSON API represents an absent or null property (for example the parent of a top-level folder) as a successful response with an empty body, which was decoded as a spurious 'not valid JSON' enrichment error. Non-2xx responses also carry a JSON fault body that was discarded. See #2070.
Change-source: pulse-maintainer
TrueNAS SCALE on AMD reports the bare `cpu` cputemp legend series at roughly 1.5x the hottest per-core reading, and the provider trusted that mapped `cpu_package` value unconditionally, firing an 80C threshold alert at a real ~60C. Compare `cpu_package` against the hottest `cpu*` per-core entry and fall back to the per-core max only when the package value exceeds it by more than 20%. Package-only and per-core-only payloads keep their existing behaviour. Adds focused provider coverage and records the selection contract for #2122.
Change-source: pulse-maintainer
Anthropic only received a cache breakpoint on the last tool, so the large
frozen system prompt was never cached and multi-turn Patrol investigations
repaid its full input cost every turn (#2118). Serialize the stable base plus
mode text as a system content block with its own ephemeral breakpoint, leaving
the per-turn clock and accumulated knowledge outside the cached prefix.
The system breakpoint covers the tool definitions too, so the redundant tool
breakpoint is dropped when it is present. Providers without prompt caching
ignore the new request field and send the system prompt unchanged. Cache
creation/read counters are logged at Info so effectiveness is visible in
production.
Change-source: pulse-maintainer
Restore the documented local-contention skip for load/SLO latency budgets on the shared release preflight worker: only a real GitHub-hosted run (GITHUB_ACTIONS=true and GITHUB_RUN_ID set) enforces the budgets. Hosted CI enforcement is unchanged; the worker keeps its cross-repo skip. Includes a focused predicate test.
Change-source: pulse-maintainer
Follow-up to the physical-disk endurance precedence fix. Records the
dependent agent-lifecycle contract section and moves the regression into the
accepted physical-disk proof file so later per-commit canonical guards find
both the contract and the verification artifact.
Change-source: pulse-maintainer
The physical-disk SMART merge let a linked host agent raise a disk's
remaining life above the Proxmox inventory value. An intermittent NVMe
PercentageUsed 0 reading therefore resolved a genuine low-life disk-wearout
alert, which re-fired on the next physical-disk poll and emitted a fresh
resolved notification every poll interval (#2112).
The merge now takes the agent value only when the Proxmox value is unreported
or more pessimistic, never raising a reported remaining-life value, while
still recording the agent SMART attributes. This does not change agent
admission, token binding or removal-block behaviour.
Regression: TestMergeHostAgentSMARTIntoDisks_AgentWearoutDoesNotHideLowPVELife
and TestMergeHostAgentSMARTIntoDisks_AgentWearoutFillsUnreportedPVELife in
internal/monitoring/monitor_integration_test.go. The monitoring contract is
updated in this commit.
Change-source: pulse-maintainer
Contract-Neutral: Behavioral bug fix in the physical-disk SMART merge; no public API or external contract delta. The monitoring contract is updated in this commit and the dependent agent-lifecycle contract and accepted proof file follow in the next commit.
The shared release preflight worker exports GITHUB_ACTIONS=true so isolated single-repository checkouts take their private-sibling skip. That flag also made the load/SLO latency guards hard-fail on a contended shared host, where the tests' own documented local-contention skip is the intended behaviour. Distinguish a real GitHub Actions run by GITHUB_RUN_ID, which only a hosted runner sets, so the worker keeps the cross-repo skip while latency overruns skip instead of failing. Hosted CI enforcement is unchanged.
Change-source: pulse-maintainer
Restore the remaining focused regressions for the all-local-RepoDigests update comparison carried on the earlier core-runtime candidate: multi-digest resolution in getImageRepoDigests, false-update suppression in CheckImageUpdate, and the DigestsDiffer multi-digest cases. Test-only additions; the runtime change and contract sections are in the preceding fix(docker) commit.
Change-source: pulse-maintainer
A removed host agent could re-enroll under a derived base-hex identity because identity resolution forked the machine before the removal block was consulted. The block is keyed on the base machine identity, so the forked ID bypassed it and the machine was silently re-admitted (#2113). ApplyHostReport now consults the base-identity removal block when the presenting token had no prior binding, so a fresh install token clears the block and heals to the base identity while an established distinct forked host (#1753) is left alone.
Record the behaviour in the monitoring and agent-lifecycle contracts and add the focused regression to the accepted monitor.go proof file. Change-source: pulse-maintainer
Change-source: pulse-maintainer
Docker update check compared a single RepoDigest against the registry tag digest, so a current image that carries two RepoDigests (postgres:16.15-alpine3.24) reported update-available. Compare the whole local RepoDigest set in CheckImageUpdate and in the typed update preflight; the primary digest is still reported for display.
Record the behaviour in the monitoring and agent-lifecycle contracts and add focused regression tests in the accepted docker proof files. Proof: go test ./internal/dockeragent/ passes including TestRegistryChecker_MultipleLocalRepoDigestsSuppressFalseUpdate and TestAgent_getImageRepoDigests_MultipleDigestsForOneImage.
Change-source: pulse-maintainer
Read-side registry rebuilds re-run the unified metric sync as often as every two seconds, so one poll observation was re-written many times between polls. The metrics store upserts on (resource, metric, tier, timestamp), so each replay UPDATEs the same row and commits a fresh transaction for no new data, churning the SQLite WAL and driving the disk-write amplification reported in #1966.
Track the last sample handed to the store per series and skip exact timestamp+value repeats before the batch is enqueued. A corrected value at the same observation time is still written, so the guard cannot mask a real change. Record the behaviour in the monitoring and agent-lifecycle contracts and move the focused regression into the accepted monitor.go proof file.
Change-source: pulse-maintainer
Initialize the persistent CSRF store for middleware tests that construct session-cookie requests, and restore the package test store afterward. This keeps exact release preflight runs from panicking before they can report qualification results.
Update the Pulse Account portal Vitest dependency to 4.1.11, clearing Dependabot security alerts 154 and 155 for Vitest and @vitest/mocker.
Contract-Neutral: Dev-only Vitest security dependency update; no product contract or runtime behavior changed.
Reloading configuration replaced the monitor's config pointer while API and
authentication handlers retained the original object. Tokens created afterwards
could authenticate successfully while Agent Doctor reported an unlisted token.
Refresh the canonical runtime configuration in place before constructing the
replacement manager. Cover repeated reloads, live token creation and revocation.
The per-commit API guard needs the actual dedicated preservation test declared in its verification registry. Restore that tested artifact and add its exact path to the existing backend API proof list. Retain all existing requirements and reviewed commit identities; no history rewrite, contract-neutral override, or unrelated proof substitution is used.
Change-source: pulse-maintainer
Place the authenticated settings-preservation regression in the established API contract proof surface so the owning contract guard consumes its actual assertions, without waiving verification or changing runtime behavior.
Change-source: pulse-maintainer
Quick security setup previously replaced system.json with defaults even for authenticated force reconfiguration. Initialize only absent settings under the persistence save mutex, preserving existing bytes and read failures. Cover credential rotation, custom and malformed settings, missing settings, and read errors without changing authorization or token scopes.
Change-source: pulse-maintainer
Preserve snapshot refresh and formatted alerts when legacy args are scalar, array or null. Restrict SMART metadata to typed object fields and cover repeated snapshot collection plus error boundaries for #2077.
Change-source: pulse-maintainer
Skipped disk polls must write the Proxmox source key back into inventory rather than hashing the canonical resource ID again. Add repeated-cycle runtime and JSON projection coverage for serial-less disks, distinct node/controller scopes and removal.
Change-source: pulse-maintainer
Include the canonical 8.0.3.0 release in the API handler fixtures and expected negotiation sequence. This repairs the exact hosted API-suite failure on the reviewed VMware candidate without changing runtime behavior.
Change-source: pulse-maintainer
Probe 8.0.3.0 before the legacy spelling and older API schemas. Issue #2070 demonstrates method routing on the canonical version while Pulse reports 8.0.2.0. Retain legacy fallback and hard authentication/permission failures.
Add canonical negotiation, legacy/older fallback and auth/permission regression controls; update the runtime contract. Five reduced-function race probes fail before and pass after. Full package validation is unavailable with the installed offline dependency cache. This repairs negotiation, not the unresolved metrics/events/folder enrichment report.
Change-source: pulse-maintainer
Headerless HTTP 200 error pages were hashed into unrelated latest image digests and cached as updates. Require a schema-2 manifest envelope before trusting fallback body metadata, preserving valid indexes, platform comparison and existing error backoff. Retain before/after collector, ingest and resource endpoint qualification; this reproduces a mechanism, not the exact reporter cause in #2048.
Change-source: pulse-maintainer
Complete the JSON-only checkpoint fast path: compare sorted, bounded actual pending-state bytes before replacement. Preserve changes, clearing, failed-write retry and unsafe-destination repair. Focused before regression fails; repeated race proof passes. Sixty unchanged synthetic checkpoints fall from 245760 process write bytes to zero; changing alert freshness remains a separate contributor, not aggregate issue #1966 acceptance.
Change-source: pulse-maintainer
Reconcile parallel release-version test fixtures while preserving the
current provider settings changes. Refresh browser verification against
the combined source before landing the diagnostic update safeguards.
Refs #1913
Release-update tests must exercise published builds even when the checkout is shallow and has no version tags. Use the existing build-version fixture instead of inferring release eligibility from the test runner checkout. Pin the source-marker case to a release version as well so it proves the marker disables updates.
Refs #1913
Mock-mode reset replaces the state pointer while API and mock-alert readers can still be active. Capture the initialized pointer under the monitor lock and preserve its fallback alerts rather than reading the replaceable pointer again.
Reproduce the race without Start workers, verify reset snapshot isolation, and retain live alert-manager precedence. This repairs the beta.3 preparation failure without masking its test cleanup schedule or changing monitoring schemas.
Contract-Neutral: Synchronization-only snapshot repair; resource identity, API fields, alert policy and canonical ownership are unchanged.
Change-source: pulse-maintainer
The backend supports authenticated Ollama servers but the provider editor omitted its credential fields. Expose write-only password editing with explicit clearing and preserve unchanged credentials. Verify Settings persistence, authenticated connection tests and the Patrol streaming factory using synthetic endpoints.
Change-source: pulse-maintainer
Repair stale transport-only availability fixtures without weakening runtime planner or policy checks. Exercise planner removal with execute authority, transport-only provider projections, and read-only policy with an installed planner.
Change-source: pulse-maintainer
Exercise shared-IP org and runtime-capability requests through universal middleware, including production and development saturation and independent login enforcement.
Contract-Neutral: Regression coverage for existing development-only E2E budget isolation; no production behaviour or limit changes.
Change-source: pulse-maintainer
PR #2034 source-build exclusion exposes five tests that implicitly assume a published checkout. Give ordinary-release fixtures an explicit restored version so CI source identity cannot suppress their release discovery. Keep this correction separate from the pending diagnostic implementation and its frontend verification.
Change-source: pulse-maintainer
Replaces google/gemini-2.5-flash with deepseek/deepseek-v4.1-flash (released 2026-09-10) as the diagnosticModel for the hosted lifecycle diagnostic and its synthetic fixture/wire tests.
Diagnostic versions must keep their exact identity without advertising a published server or agent update target. Reuse the canonical source-build classification and discard cached release offers when runtime identity changes.
Show source-build status and manual image replacement guidance. Verify release and preview controls remain available.
Refs #1913
The hosted synthetic lifecycle diagnostic offered no control tool despite an installed canonical planner: availability still depended on retired execution transports. Match exposure to the plan-only boundary while preserving read-state and control-level policy. Assert provider and gateway tool offers so scripted calls cannot hide this mismatch, and retain literal-search behaviour as separate evidence.
Change-source: pulse-maintainer