Preserve the exact reviewed private-input candidate and its source-bound receipts. Qualify changed drawer composition separately; no native or release acceptance is claimed.
Change-source: pulse-maintainer
Use a POSIX root/sudo prefix inside the isolated subshell rather than duplicating the long quoted reader. Synchronise PTY command entry and exit with the caller prompt, retain full terminal/privacy/overflow assertions, and follow current help rows by their labels. The browser driver now inspects the full Linux card.
Change-source: pulse-maintainer
Preserve exact specialist commits and retained consuming document proof. The Docs consumer and dependency bytes are unchanged; this help maintenance is not a baseline-memory repair.
Change-source: pulse-maintainer
Preserve the exact reviewed tip and incorporate current upstream History default, marker shape and readout behavior additively.
Change-source: pulse-maintainer
Mock chart history thinned each metric with LTTB on its own. LTTB keeps
value-dependent points, so the metrics of one resource ended up with
different timestamps. The public demo (6.5.0) showed this: a container's
24h history had eight ~48-point series spread over 162 distinct
timestamps, and a node's had 166. The drawer History panels break a line
wherever another series in the panel has a reading, so every mock chart
drew as dots with "Missing observations". Real poller history writes all
of a resource's metrics at the same times.
Mock series are now thinned onto an epoch-aligned grid. Each bucket
keeps its first reading, the newest reading is kept too, and every point
keeps its own timestamp. Point targets and values are unchanged.
Verification:
- `TestMockChartHistorySharesTimestampsAcrossMetrics`
(`monitor_metrics_slo_test.go`) checks a mock VM, container and node, on
synthetic and seeded history, at 1h, 4h, 24h and 7d. It fails on the
previous code (5 of 20 memory timestamps shared with cpu) and passes
now. `internal/monitoring` passes in full.
- On a mock-mode build of this branch, `/api/metrics-store/history`
returns a timestamp union equal to the per-series count for a VM, a
container, a node and an agent at 1h, 24h and 7d. The drawer History tab
draws one continuous path per series with no "Missing observations". The
unpatched build of the same estate showed 82 dots and the note on all
three panels.
Select the BusyBox stty applet only when standalone stty is absent, fail before unsafe entry on terminal-control errors, and restore modes with the selected tool. Expose the existing private-file installation alternative on Linux/NAS alongside FreeBSD without changing issuance, TLS, removal or privilege.
Change-source: pulse-maintainer
Two drawer History presentation fixes, both reported while previewing
the drawer redesign:
- **Oval dots.** The plot stretches its viewBox to the panel
(`preserveAspectRatio="none"`), so the `<circle>` markers for single
observations and the hover cursor rendered as wide ovals. They are now
zero-length, round-capped strokes with a non-scaling stroke, so they
stay round at any width. Series lines carry `data-history-series` so
tests can tell lines from dots.
- **Jumping note.** "A dash means no stored observation at this time"
appeared and vanished as the inspected time changed, pushing the chart
up and down while scrolling past it. A missing value now reads **no
reading** in the readout itself, and the line is gone. In a pointer
sweep the chart height stayed constant (202px at 1024, 327px at 390).
Tests: History tests select lines by `path[data-history-series]` and
hover markers by `[data-history-hover-marker]`. A new guard checks the
plot has no `<circle>` and that dots are round non-scaling strokes. The
readout assertions now expect "no reading". Workloads, Infrastructure
and Docker suites pass (3,692 tests). Contract notes in
`frontend-primitives` and `performance-and-scalability`.
Mock chart history thinned each metric with LTTB on its own. LTTB keeps
the points whose values stand out, so cpu, memory and disk of one guest
kept different timestamps: on the public demo a 24h container history
had eight ~48-point series spread over 162 distinct timestamps. The
drawer History panels break a line wherever another series in the panel
has a reading this one lacks, so every mock chart drew as dots with a
"Missing observations" note. Real history does not do this because the
poller writes all of a resource's metrics at the same times.
Thin mock series onto an epoch-aligned grid instead: keep the first
reading in each bucket plus the newest reading, at their own
timestamps. Which readings survive now depends only on when they were
taken, so series sampled together keep identical timestamps, values
stay real readings, and point targets are unchanged. The synthetic
generator no longer pre-thins to 500 points, since every caller thins
onto the grid.
The History plot stretches its viewBox to the panel width
(preserveAspectRatio="none"), so the <circle> markers for single
observations and the hover cursor rendered as wide ovals. They are now
zero-length, round-capped strokes with a non-scaling stroke, drawn in
screen pixels, so they stay round at any width. Series lines carry
data-history-series so tests can tell lines from dots.
The readout explained a missing value with a separate line, "A dash
means no stored observation at this time", which appeared and vanished
as the inspected time changed and pushed the chart up and down, most
visibly while scrolling past it. A series without a reading at the
inspected time now says "no reading" in the readout itself, and the
extra line is gone.
Merge exact Web candidate f034be1854. Resolve drawer overlap to its browser-verified contents and System facts controls; retain canonical GuestDrawer assertions, newer agent help, updater repair and consolidated contracts. Retained source and browser proofs qualify presentation only, not native workload or QGA recovery.
Change-source: pulse-maintainer
The guest and node drawer Overview now shows 24h trend cards for CPU,
memory, disk and temperature, so a History tab that also opened on 24
hours repeated them. History now opens on 7 days for those drawers:
Overview answers "what is it doing now", History "what is normal this
week", with any range still selectable. The free plan keeps 7 days, so
the default is never locked.
The trend cards read their own 24h constant, and a 24h History
selection still reuses their cached read. Drawers without trend cards
(Docker host, resource detail) keep the 24h History default.
The copyable healthcheck previously also imposed a 256 MB memory limit and half a CPU, without workload qualification. Preserve the check, separate sizing from health and repair, and retain existing deployment policies. Link the bounded read-only interpretation and cover the shipped document and actual Docs consumer.
Contract-Neutral: Existing documentation and offline consuming fixtures only. No runtime defaults, deployment policy, API, retention, polling, resource enforcement or subsystem contract changes.
Change-source: pulse-maintainer
Preserve exact reviewed d636bfdaea and published 0a44d276db ancestry. Retain both contract additions, readable System evidence and stable accessible update help alongside upstream alert-first trends, facts and Details.
Change-source: pulse-maintainer
Keep shared tenant-store, backup association, source identity, grouping,
installer qualification and alert evidence rules at their canonical owners.
Consumer contracts retain scoped references and their distinct local rules.
Remove obligations for the deleted Discovery scanner and backfill. Replace
superseded chart-padding expectations, telemetry schema history and test
names with the current source contracts while retaining VM backup precautions,
privacy limits, paid behavior and native qualification boundaries.
Cover closed-Details OS and filesystem guidance plus stable update help across readings, relative ages and evidence changes. Add a compiled safe-observation browser fixture for the combined drawers and shipped Docs.
Contract-Neutral: Connected composition regression and browser fixtures retain existing source behaviour and document the merge outcomes.
Change-source: pulse-maintainer
Keep removal safety requirements in agent lifecycle and replace deployment
copies with scoped references. Keep legacy Assistant mode-echo compatibility
and security setup settings preservation in the API owner, so their consumers
do not maintain separate copies of the same obligations.
Runtime behavior, paid entitlement checks and native qualification limits
remain unchanged.
Preserve the original guidance candidate and existing source history; this isolated composition is not canonical integration or publication.
Change-source: pulse-maintainer
Keep published alert-first 24-hour trends and closed Details. Preserve phone filesystem guidance, full OS facts, and a drawer-owned update-access help dialog outside the demoted inventory. Retain both independent subsystem contract additions.
Change-source: pulse-maintainer
Avoid rewriting an already-replaced QNAP executable through an aliased persistent path. Stage split QNAP and Unraid copies in owned same-directory temporaries, set execute permissions before atomic replacement, and clean every failed stage without changing saved state or update trust. Add authenticated HTTPS and real child-exec regressions plus persistence failure and recovery controls. Native appliance and old-installed-updater recovery remain separate.
Change-source: pulse-maintainer
Patrol's operator-state projection dereferenced the one-shot
MaintenanceStartAt/EndAt whenever IsInMaintenanceAt was true. A
recurring window also reports active but leaves those fields nil, so
the first finding Patrol evaluated during a recurring occurrence
panicked the provider. The projection now takes its bounds from the
active occurrence.
Alerts already silence guests under a host window scoped to
resource_and_descendants, but Patrol read only the exact resource, so
the same planned work dismissed a guest's alerts and still raised its
Patrol findings. Both now resolve maintenance through one rule,
unifiedresources.ActiveMaintenanceCoverageAt: own window plus
descendant-scoped ancestor windows, latest active end wins. Only
maintenance is inherited; monitoring mode, lifecycle and remediation
locks stay exact-resource state. An inherited dismissal says the window
is on a parent resource and names it on the lifecycle event, and the
Manage help now says descendants' new Patrol findings are dismissed
too.
Distinguish private prompt preparation, preflight and read-only profile inspection from installation and destructive removal. Keep existing unavailable-agent and automatic-update investigations separate, and route FAQ and troubleshooting readers to the existing private-file and recovery guides.
Contract-Neutral: Help copy and rendered-document regression checks only; installer, credential, lifecycle and monitoring contracts are unchanged.
Change-source: pulse-maintainer
Retain the shared resolver and request authority while retrying only failed socket establishment. Usable addresses share one bounded dial budget; cancellation prevents further attempts and TLS still authenticates the original hostname and pin. Connected controls reproduce the first-address defect and cover cache reuse, families, deadlines and cancellation.
Change-source: pulse-maintainer
The Proxmox guest and node drawers' Overview was a grid of equal-weight
inventory cards, much of it repeating the table row, while the trend
that answers "is this getting worse?" sat on the History tab.
**Overview now leads with what is wrong:**
- Active alerts first (unchanged component), or one "No active alerts"
line.
- 24h trend cards for the metrics the row shows: CPU, memory and disk
for guests; CPU, memory, CPU temperature and root disk for nodes. A card
with an active alert on its metric is coloured and draws the alert's own
trigger.
- "Worth checking": any warning- or danger-toned detail row, lifted from
whichever section owns it, so demotion never hides a reason a reading
cannot be trusted.
- Guest filesystems, physical disks, RAID, node GPU/NVMe sensors, and
any availability check that is not both fresh and healthy stay visible.
- A one-line facts strip (OS, address, healthy last completed backup,
tags).
- Everything else in a closed **Details** disclosure that keeps its rows
mounted for find-in-page.
**Correctness details:**
- Trend cards and the History tab share one query and cache key
(`guestDrawerHistoryQuery.ts`); each polls only while its tab shows. The
node drawer's History no longer stays mounted and polling while hidden.
- Node cards are coloured only by the node's own alerts, which
`ProxmoxNodesTable` now passes as `ownAlerts` by identity; the drawer's
`alerts` list also carries its guests' alerts by node name.
- Offline or stale nodes, last-known or unknown memory, and unmeasured
disks show as not current or last known, never as live values or
filled-in zeros.
- Ranges use bucket min/max, so a spike averaged away inside a bucket
still shows (delly's CPU temperature reads 42–92°C, not 44–73°C).
- A failed refresh says it is showing the last loaded trend.
**Governance:** amends the `frontend-primitives` rule that curated
drawer facts must not need another tap, for these two drawers only.
Recorded as a named bet in the demand ledger (rcourtman/pulse-pro#419),
graded at +30 days. Contract notes in `frontend-primitives`,
`performance-and-scalability` and `unified-resources`.
**Verification:**
- Full frontend suite: 23,213 passed. Lint, typecheck, production build
and bundle budget pass (`useWorkloadsState` 55.88 kB of 70.23 kB).
- Six negative controls: reverting each fix fails its targeted test.
- Browser pass on the real homelab estate at 1280, 1024 and 390px. The
receipt is in `frontend-modern/browser-verification/`.
Preserve reviewed dd2dbeab8f and exact published aa0c25de4c additively after upstream advanced at the publication boundary.
Change-source: pulse-maintainer
Bind the credential-free capture handshake to the polling context under the existing five-second ceiling. Recheck cancellation before publishing a runtime pin; retain established trust, endpoint selection and ordinary declared-member first use. Add local stalled-handshake, peer-closure, no-dial and later-recovery controls.
Change-source: pulse-maintainer
The Manage tab's operator overrides explained themselves in
implementation terms: "one persisted resource policy", "the action broker
logs every refused dispatch as a Failed audit record", "Pulse's canonical
inventory hierarchy". A homelab user reads those to learn what a control
will do, and the jargon hid the answer.
Each control keeps its consequence beside it, in shorter words, checked
against the runtime. The maintenance window now says it silences alerts
and dismisses new Patrol findings; the old text named findings only,
though an active window also suppresses alert activation. The descendant
scope help claims only alerts for descendants, because Patrol reads the
exact resource's own state. Never auto-remediate keeps its name, because
the help pages and the Assistant's refusal message refer to it, and now
reads "Block every automated fix on this resource, including approved
ones. Blocked runs are logged as failed actions."
The Proxmox guest and node drawer Overview had grown into a grid of
equal-weight inventory cards (coverage, platform, hardware, telemetry,
thermals, observation paths), much of it repeating the table row, while
the trend that answers "is this getting worse?" sat on the History tab.
Overview now leads with active alerts, or one "No active alerts" line,
then 24h trend cards for the metrics the row shows: CPU, memory and disk
for guests; CPU, memory, CPU temperature and root disk for nodes. An
active alert on a card's metric colours it and draws the alert's own
trigger. Any warning- or danger-toned detail row moves into a "Worth
checking" section in front, so demoting inventory never hides a reason a
reading cannot be trusted. Guest filesystems, physical disks, RAID, node
GPU/NVMe sensors and any availability check that is not fresh and healthy
stay visible; a facts strip carries OS, address, a healthy last completed
backup and tags. Everything else sits in a closed Details disclosure that
keeps its rows mounted for find-in-page.
The trend cards and the History tab share one query and cache key, and
each polls only while its tab shows: the node drawer's History no longer
stays mounted and polling while hidden. Node cards read only the node's
own alerts, which the Proxmox node table now passes by identity (the
drawer's list also carries its guests' alerts by node name), and withhold live values
when the node is offline or its Proxmox readings are stale. Ranges use
bucket extremes, so an averaged-away spike still shows.
This deliberately amends the frontend-primitives rule that curated drawer
facts must not need another tap, for these two drawers only, as a named
bet in the demand ledger (pulse-pro#419) to grade at +30 days.
Expected offline is availability-specific everywhere else: the canonical
ResourceOperatorState doc says it "suppresses availability noise", the
alert runtime suppresses only offline and availability signals, and both
monitoring-policy controls tell the operator it hides availability noise
only, with Mute all as the way to stop Alerts and Patrol. Patrol was the
outlier. Its projection returned a suppression cause for expected_offline
(and the legacy IntentionallyOffline flag) regardless of the finding, so
a disk, memory, backup or security finding on an expected-offline
resource was auto-acknowledged exactly as if the resource were muted.
The suppression decision is now per finding. Retired and muted still
silence every finding; expected_offline and the legacy flag (when no
MonitoringMode is projected, as in the alert runtime) silence only
findings in the shared down condition class that alert mirroring already
uses. The wake path judges the re-detected finding with the same helper,
so findings auto-acknowledged under the old behaviour wake on their next
detection.
That classifier matched "offline" in any reliability title, which would
have read a SMART "offline uncorrectable sectors" report as the resource
being down and hidden a failing disk. SMART findings now fall outside the
down class, which also stops them mirroring an offline alert.
A new test pins the split (availability silenced; disk, memory and SMART
findings visible) with muted as the negative control, plus a muted to
expected-offline transition that wakes only non-availability findings.
Each test fails when the old behaviour, the wake-path scoping or the
SMART guard is reverted.
When cluster/resources polling fails, containers come from the per-node
collector, which built memory without a MemoryObservation. The unified
resource layer preserves that absence and the Workloads classifier then
reads every container on the node as "Freshness unknown", although the
same guest polled through the cluster listing reads current.
The fallback now annotates through the shared guestMemoryObservation
builder with the selected source, the listing time, the previous
snapshot
and the linked agent, so running containers read current from
cluster-resources (or agent) and stopped ones unavailable from
powered-off. Numeric selection, stabilisation and alerting are
unchanged.
Give the existing safety guidance link a 44px phone target and a theme-aware keyboard focus outline, keeping desktop density and the shipped destination. Exercise read-reason updates and the consuming documentation in both themes.
Change-source: pulse-maintainer
Preserve the three exact PI commits and retained real-curl plus consuming Docs proof. The change disables curl URL globbing in the existing copied helper; API runtime and authentication contracts are unchanged.
Change-source: pulse-maintainer
When cluster/resources polling fails, containers come from the per-node
collector, which built memory without a MemoryObservation. The unified
resource layer preserves that absence and the Workloads classifier then
reads every container on the node as "Freshness unknown", although the
same guest polled through the cluster listing reads current.
The fallback now annotates through the shared guestMemoryObservation
builder with the selected source, the listing time, the previous snapshot
and the linked agent, so running containers read current from
cluster-resources (or agent) and stopped ones unavailable from
powered-off. Numeric selection, stabilisation and alerting are unchanged.
A guest's per-filesystem disk alert is raised under <guest>-disk-<key>,
which names nothing the resource registry can resolve, so the Alerts
overview left its name linking to the top of the platform page. A full
filesystem is the most common guest alert, and the operator still had to
find the guest among every other one.
CheckGuest now stamps the owning guest on every filesystem alert as
guestResourceId metadata: the same guest ID the guest's own alerts are
raised under, on the canonical-spec and legacy checkMetric paths alike.
The card links a filesystem alert to ?resource=<guestResourceId>, so the
workloads table opens that guest's drawer, where the Filesystems panel
shows the mount that filled. Filesystem alerts raised before this change
carry no stamp and keep the platform page link; the card never falls
back to the filesystem id.
The private-response helper promises one request, but real curl expands quoted brace lists and bracket ranges into two or three requests, including POST, PUT and DELETE. Disable URL globbing without changing token-file transport, response privacy, scopes, TLS, deadlines or no-retry rules. Explain the literal-path and separate URL-encoding boundary.
Exercise the copied helper with both authentication headers, every supported method, encoded identifiers and adverse write responses. Add consuming desktop and narrow Docs/router verification.
Contract-Neutral: Documentation and synthetic recipe/browser checks only; API authentication, endpoint and runtime contracts are unchanged.
Change-source: pulse-maintainer
Accept exact Delivery candidate 00f0cbeb56 with retained complete documentation proof and consuming desktop/phone browser evidence. Preserve current main proxy-auth safety changes; no native QGA recovery or human PR delivery is claimed.
Change-source: pulse-maintainer
The guest-reading docs control required a literal Unavailable caption even though the reading state and its explanation are the contract. Keep retained labels, disk-specific title/assistive wiring and unavailable producer checks; negative controls reject lost reasons while permitting caption-only changes. Guide keyboard and phone users through the existing reading indicator and same-guest details without treating a dash as an agent-installation diagnosis. Add a consuming current-source Docs browser check. No human PR is imported, amended or re-authored; its source and independent integration remain separate.
Contract-Neutral: Align existing filesystem guidance and its executable checks with unchanged reading states and accessible reasons; no polling, telemetry, runtime, access, safety or recovery contract changes.
Change-source: pulse-maintainer
Honour the server-owned stale signal only for the selected Pulse Agent observation. Preserve its original value and time as last known in rows, sorting, metric search and both History consumers, while independent Proxmox/QGA sources remain current. Add regression and connected browser fixtures without a client TTL, wire rewrite or guest operation.
Change-source: pulse-maintainer
The copied loopback recipe inherits http_proxy and ALL_PROXY even with curl --disable. Real-curl parent controls sent the synthetic administrator-capable header to the proxy and could report its denial as a Pulse role result. Explicitly bypass proxies for the selected backend and keep the protocol boundary clear.
Exercise both response directions and three proxy environment selectors, preserving privacy, deadlines, cleanup and the existing role/IdP trust boundary. Add a repeatable production Docs/browser check for the exact copied guide.
Contract-Neutral: Documentation and synthetic recipe/browser checks only; proxy authentication semantics and runtime contracts are unchanged.
Change-source: pulse-maintainer
Reject impossible physical counters and overflowing cache estimates. Keep the original trusted source through repeated failed/negative-cache polls within the unchanged observation-age and capacity fences, instead of clearing the incident on an independent provider fallback after one retained poll.
Exercise all eight refusals through both collectors and both HTTP clients, original percentage/byte History, backup admission, real alert decisions, valid recovery and measured zero. Preserve TLS, operation locks, shared uncertainty, deadlines and native recovery exclusions. This completes the original guest-memory outcome coherently, not a replay of source-xubz2c16.
Change-source: pulse-maintainer
Validate PVE and PBS hosts before logging them, omit url.Parse input from syntax errors, and keep cluster logging, health snapshots, recovery summaries and returned error labels separate from configured routing and TLS identity. Exercise actual rejected-host constructors, cluster routing/recovery and accepted-host controls with synthetic credentials. Connection policy, authentication and guest safety fences are unchanged.
Change-source: pulse-maintainer
Preserve exact Web candidate c8e4276ca4 with published alert navigation. Retain its complete source and per-content browser proof; native guest safety and restart recovery remain separate owning work.
Change-source: pulse-maintainer
Share byte-reading admission across host summaries and filesystem drawers. Keep unavailable rows neutral without counting missing capacity or unknown usage as healthy space, while preserving genuine omitted-zero bytes and independent aggregate readings. Exercise canonical resource refreshes through desktop and phone host tables and register the contract regression proofs.
Change-source: pulse-maintainer