Preserve the exact Web candidate and its connected source and production-component browser proof. Unusable completion times stay cautionary in existing rows and drawers; running activity and genuine absence remain distinct.
Change-source: pulse-maintainer
Preserve the exact Core candidate and its retained focused, lifecycle, race, full-alert, monitoring and embedded-build evidence. Non-finite readings remain unknown rather than changing trusted incident state.
Change-source: pulse-maintainer
Preserve malformed timestamp evidence through resource projection and label future, invalid or unusable dates as unknown in existing row indicators, tooltips and drawer protection. Keep explicit absence, configured age thresholds and running activity distinct. Validate real API and canonical snapshot replacements with parent controls and production-component browser fixtures; no native backup or thaw claim.
Change-source: pulse-maintainer
Treat non-finite current observations, authoritative rolling-history samples and overflowing averages as unknown. Preserve trusted incident and notification state instead of opening, recovering or poisoning JSON snapshots. Retain timestamp/duplicate authority, normal finite evaluation and explicit rule disable.
Change-source: pulse-maintainer
Accept exact Core candidate fcd9b65b82 with retained semantic, allocation, race, monitoring-suite and actual embedded build evidence. Preserve observations and caller isolation; no native performance or release acceptance is asserted.
Change-source: pulse-maintainer
Keep canonical guidance aligned with the actual unchanged header and copied member-aware templates. Pin the correction in the same safety guard so a later maintainer does not restore permanent header-only deduplication.
Contract-Neutral: Documentation clarification and its verification only; webhook wire format, retry stability and runtime behaviour are unchanged.
Change-source: pulse-maintainer
Reject mismatched resource, range and metric envelopes and malformed samples at the shared client boundary. Preserve explicit Kubernetes compatibility, real access failures, valid empty history and measured zero. Exercise drawer, single-metric and row-cache consumers, and inspect desktop and phone-emulated browser renders.
Change-source: pulse-maintainer
Count retained samples before allocating detached snapshots for guest, node, disk and storage readers. Preserve exclusive cutoffs, unordered inputs, original observations and empty arrays. Cover public series, snapshot isolation, connected chart/window consumers and same-executable allocation comparisons; no SQL, retention or source-selection change.
Change-source: pulse-maintainer
Contract-Neutral: In-memory History copy allocation only; public API/JSON shape, sample order/cutoffs, retention and observation authority are unchanged.
Preserve the exact Web candidate and its parent-bound browser receipt; retain the unrelated backup-date timeout and source-proof exit discrepancy as adverse evidence.
Change-source: pulse-maintainer
Withdraw another target’s service and URL while its replacement is loading or unavailable. Preserve final access status without denied bodies, label same-target transient evidence and offer an in-place retry. Dispose per-guest forms and the replaced discovery consumer without cancelling or repeating server operations. Preserve existing same-target query reuse and independent saved operator URLs. Add connected identity/access regressions, contracts and exact-content desktop/phone browser evidence.
Change-source: pulse-maintainer
Accept exact Core candidate 0ea87307e2. Retained source-0qcd2wj7 proves parent omissions, final retention and connected readers under race, vet and affected-package build; intervening canonical changes do not touch the affected Go source.
Change-source: pulse-maintainer
Accept a stable exact Node pin only within the governed major instead of
comparing its entire string with the major selector. Keep all other lines,
ranges and unresolved selectors rejected. This repairs the deterministic
required-check failure on the published-RC browser workflow without removing
its exact Node pin.
Give fake npm audit tests their own default timing controls and exercise
poisoned caller environments while preserving explicit watchdog tests.
No production audit verdict, dependency graph, benchmark threshold or release
gate changes.
Change-source: pulse-maintainer
Periodic guest and node cleanup omitted raw memory-used samples from both expiry and live-entry checks. Trim them with the existing retention and backing-array policy without deleting a still-live byte series. Cover every supported History series, byte-array reclamation, concurrent cleanup and poll-to-chart/metric-window resumption. No SQL retention, source-selection or wire changes.
Change-source: pulse-maintainer
Forward existing disk deferrals, guest-agent state and VM locks through API and canonical snapshots. Supersede omitted optional fields only on an explicit native VM outcome, consistently across full and fast merges. Withdraw unavailable row numerics while preserving valid prior and measured-zero readings. Add connected hook, merge, mounted and inspected browser controls without issuing guest or backup commands.
Change-source: pulse-maintainer
Preserve current safety evidence, installer guidance and reviewed release-browser source while validating the previously unexecuted runtime response-boundary correction. No native thaw or old executor cleanup is inferred.
Change-source: pulse-maintainer
Preserve the exact History and incomplete-reading candidates and their own-parent browser receipts while including the current assigned main. No frontend resolution or receipt rebinding.
Change-source: pulse-maintainer
Retain exact Core candidate. Nineteen focused committed-source checker and CLI methods establish rejection of unsupported post-task resumption while preserving calibrated healthy records. No production polling or native thaw acceptance is changed.
Change-source: pulse-maintainer
Require finite capacity and measured used bytes in the existing filesystem list and guest Overview. Missing, invalid and sentinel readings remain unavailable rather than a healthy empty disk; measured zero and valid byte-derived readings stay visible. Preserve the exact retained History correction and add mounted, multi-filesystem and browser controls.
Change-source: pulse-maintainer
Reject a resumed disk or memory History claim when the complete native trace lacks the corresponding successful new guest read after backup completion. Preserve calibrated clock bounds, normal later polls, independent filesystem writes and native provenance review; no QGA command or runtime behaviour changes.
Contract-Neutral: Tighten consistency checks for the existing backup-safety measurement only; production polling, interfaces, access boundaries and release gates are unchanged.
Change-source: pulse-maintainer
Use a dedicated Auth Keys write client restricted to tag:ci-deploy, never the broader demo registration. Reject missing configuration and validate the actual running Self tag and DNS before Serve. Keep exact-source, denial-stop, no-replay and cleanup contracts, with connected offline registration and Serve controls.
Change-source: pulse-maintainer
Preserve the reviewed denial and recovery corrections for an additive least-privilege registration repair. No native acceptance is inferred.
Change-source: pulse-maintainer
Separate current and explicitly retained disk evidence in the existing guest drawer. Show the fixed safe read reason beside History, preserve dated observations and access withdrawal, and clear retained provenance only with fresh source evidence. Record desktop and touch browser verification; native backup thaw and release delivery remain separate.
Change-source: pulse-maintainer
Do not admit guest commands or publish their payloads from an unlocked JSON prefix when the authoritative config response is incomplete. Preserve bounded ordinary config reads, live CPU and I/O observations, cache timestamps and healthy resumption.
Change-source: pulse-maintainer
Bind anonymous probes at request start, record bounded navigation/API/SSE denial, close the page immediately and suppress recovery authentication when the upgrade receipt is refused or unavailable. Exercise real Chromium response controls through the actual shell recovery guard.
Change-source: pulse-maintainer
Follow up #2118/#2350: ordinary input can be zero while cache writes or reads remain billable. Preserve cache-only successful and partial results, record them in the usage ledger, and include them in the history median and triggered-spend rate. Keep genuinely empty/expired history excluded and retain the existing five-minute prices and budget semantics.
Change-source: pulse-maintainer
Live stable and RC archive metadata exceed 256 MiB; retain a streaming bounded 512 MiB archive/16 KiB signature/1 GiB binary contract instead. Disable automatic setup caches in the CI credential job and encode derived command outputs with the reviewed writer. Add regressions; do not relax workflow or release guards.
Change-source: pulse-maintainer
Show retained or unavailable read context beside filesystem values across bars, sparklines and history lenses, with the full safe reason available to assistive readers and the existing drawer. Announce retained chart values as last known, and let narrow chart plots yield width to the numeric value without growing dense rows. Include fixed-reason regressions, subsystem obligations and inspected final-content Chromium/WebKit proof.
Change-source: pulse-maintainer
Reuse the signed-install lifecycle assertions on a fresh public hosted VM without Docker identity overrides. Bind immutable release assets/control, observe one real UI apply/SSE/modal journey, retain sanitised terminal evidence and stop access refusals without reauthentication. Update the deployment contract and execute its recovery-access guard; release judgment and gates are unchanged.
Change-source: pulse-maintainer
Merge exact upstream 99927467f5. Resolve only the agent-lifecycle contract append conflict by retaining both monitor recovery ownership and AI usage export clauses. Frontend auto-merges preserve reviewed final bytes; no runtime conflict correction or browser receipt rebinding.
Change-source: pulse-maintainer
A saved connection test reads system.info on a separate client. Keep both probe results out of runtime timestamps, failures, retry cadence and inventory readiness. Preserve stored-secret and tenant boundaries, and validate the existing API evidence through real local client/poller/handler controls. Update the matching API, monitoring, lifecycle and recovery contracts together. This repairs the diagnostic gap in #2382; its native polling/session cause remains unverified.
Change-source: pulse-maintainer
Retain a baseline on every response and fall back to interval counters for zero, absent or invalid compatibility percentages. Preserve positive native units and Docker calculations, rebaseline on restarts and reject out-of-order intervals. Add connected collector controls and the matching monitoring and agent contracts. Addresses the source gap reported in #2447; native payload and reporter acceptance remain unverified.
Change-source: pulse-maintainer
Preserve reviewed backup-reader and canonical deferred-read status guidance with upstream measured-width disk labels. Resolve only additive test assertions, keeping lifecycle refusal, PMG replacement, phone projection and word-wrapping controls. The combined disk model matches the previously diagnosed 9f50f630 content and requires fresh owning-lane browser proof.
Change-source: pulse-maintainer
Since 3 October the required Frontend check has failed on every open
pull request, including Go-only ones, because of GHSA-vfj7-8cjw-p6xm
(`braces` <= 3.0.3, high, no patched release). `braces` reaches the
frontend graph only through dev-only `tailwindcss` 3 and `jscpd` 4. `npm
audit --omit=dev` is clean, so the shipped bundle is not affected.
A pull request that leaves `package.json` and `package-lock.json`
untouched has the same dependency graph as its base commit. It can
neither add a finding nor remove one, so failing it blocks every fix
without making anything safer.
## What changes
`scripts/npm-audit-retry.sh` now treats findings the same way it already
treated an unreachable advisory endpoint:
- **The change moves the dependency graph, or edits the runner**
(`NPM_AUDIT_REQUIRE_RESULT=true`): any finding at any severity fails, as
before. A missing answer also fails.
- **The graph is the base commit's** (`NPM_AUDIT_REQUIRE_RESULT=false`):
the run warns instead, still naming every finding. A missing answer also
only warns, as before.
- **Only an explicit `false` relaxes the verdict.** An empty or
unrecognised value stays strict. This also tightens the outage path,
which previously relaxed on any value other than `true`.
The scheduled `npm-audit` scan and the daily dependency advisory watch
keep the strict default. An inherited advisory therefore still fails
once a day until the graph is fixed; `test_dependency_advisory_watch.py`
now proves this. No severity threshold, allowlist or suppression is
added.
## Landing
This change edits the runner, so its own Frontend audit runs in strict
mode and fails on this same advisory. It cannot pass the required
checks, so it lands only by an explicit maintainer merge. That is
intentional: the policy is relaxed by a human decision, never by a
change passing its own check.
Removing `braces` for real means migrating to Tailwind 4 and jscpd
5.4.0; that is tracked separately. Dependency PRs (#2352, #2278) stay
blocked until that lands.
## Verification
- `scripts/tests/test-npm-audit-retry.sh`: 19 cases pass.
- `test_npm_audit_retry.py` and `test_dependency_advisory_watch.py`
pass.
- `TestFrontendDependencySecurityAuditsAreRequired` passes.
- `check_workflow_trust.py` passes.
- The real runner against main's lockfile exits 0 with the warning and
all 7 findings named when `NPM_AUDIT_REQUIRE_RESULT=false`, and exits 1
with `::error::` when it is `true`.
Supersedes #2435, whose branch conflicted with the Tailwind 4 move
(#2443) in `proxmoxHostTableModel.test.ts`. Same change, rebuilt as one
commit on current main with a fresh browser pass and receipt.
- **Coverage:** the Restore column is now Last backup, meaning the
newest completed PBS snapshot or PVE backup file. Guest snapshots no
longer count, matching the posture engine.
- **Phones:** the node, backup server, coverage and By date tables keep
their values whole on phones.
- **By date Details:** shows the archive format (`vma.zst`, `tar.zst`)
with the full volid on hover and in search.
Verified on a private mock stack at 1440, 560, 440 and 390px, in light
and dark. On phones, only identity strings clip.
A second commit restores two `storage-recovery.md` notes from main,
covering History touch inspection and pool-to-disk ownership. The
original branch had dropped them with a stale copy of the file.
Fixes#2350 (from #2118).
The Anthropic client logged `cache_creation_input_tokens` and
`cache_read_input_tokens` and then returned only `input_tokens` and
`output_tokens`, so every cached Patrol run reached the usage ledger,
the cost preview, the budget check and the weekly digest with its cache
buckets missing. #2350 reproduced the loss on both the `Chat` and
`ChatStream` paths.
Both response paths now carry the two buckets as fields disjoint from
`InputTokens` (streaming assigns them from `message_start` and the final
cumulative `message_delta` rather than summing). The agentic loops,
Patrol responses and run records sum them beside the ordinary totals,
the usage ledger and its persisted copies keep them, and
`cost.EstimateUsageUSD` prices each bucket at Anthropic's published
cache rates (5-minute write 1.25x, read 0.1x of the input rate), falling
back to the input rate for providers without a known cache price. Spend
summaries, the digest spend, the cost projection medians and the usage
export expose the buckets and price them the same way. `InputTokens`
keeps its meaning everywhere, so the telemetry token buckets are
unchanged.
Proof: `anthropic_test.go` (both response paths keep the buckets; the
final delta does not double them), `pricing_anthropic_test.go`,
`store_test.go`, `patrol_digest_test.go`,
`patrol_cost_projection_test.go`, `cost_persistence_test.go`, and
`ai_handlers_more_test.go` for the export in both formats. This repairs
lost accounting data; it is not a measured provider bill or a claim of
savings across six-hourly runs.
Supersedes #2432, whose branch conflicted with the Tailwind 4 move
(#2443) in `StackedDiskBar.tsx` and `DockerTasksTable.tsx`. Same eight
fixes, rebuilt as one commit on current main. The conflict resolution
keeps both this change and main's class renames (`rounded-sm` to
`rounded-xs`). A fresh browser pass and receipt are included.
Proxmox
- PBS datastores read Online in the storage vocabulary instead of
Unknown.
- The mock estate carries shared PBS storage as one cluster row.
- Storage types read LVM-Thin and NFS, and cluster-merged storage reads
"Shared · N nodes".
- REST-mapped resources carry PMG metadata, so the Mail Gateway table no
longer paints dashes on fresh loads.
- In Bars mode, multi-disk hosts show their fullest disk's percentage.
- REST rows carry source status, action readiness and technology.
Docker
- The containers table fits at laptop and phone widths.
- Swarm states read as words, and task times show as ages.
- Demo container names are unique per host.
Verified on a private mock stack built from this tree at 1440, 1280 and
390px, in light and dark.
## Why
The Workload Controllers table hides its Detail column below a 76rem
container, and that column was the only place a Job's completion time
and a CronJob's last success or last run were shown. The row expansion
rendered only the generic Observed state, Last seen, Identity and
Aliases, so a phone or a half-width pane had no way to read when a job
finished. At 390px the 15 percent Kind track also clipped "DaemonSet",
"StatefulSet" and "CronJob", and the Target track clipped "1
completions".
## What
- The drawer's Kubernetes model builds a per-kind controller section
(Job, CronJob, DaemonSet, StatefulSet, ReplicaSet) that the
always-visible summary tables render in the same slot as the Docker
container section, so the facts are one tap away at every width and on
the Infrastructure drawer too. Job rows lead with Started, Completed and
Duration; CronJob rows with Schedule, Last run and Last success; each
timestamp is the absolute time with its age in parentheses and wraps in
a phone-width cell. Target, counts, the StatefulSet service name,
Namespace and Cluster follow.
- The phone projection keeps Controller, Kind, Ready and Issues and
demotes Target with `platform-table-phone-hidden`, widening Kind to 25
percent so every kind label fits whole.
- The Target count pluralizes through `getPlatformResourceCountNoun`, so
a single completion reads "1 completion" in the row as it does in the
expansion.
## Verification
Playwright clip sweep (scrollWidth over clientWidth on every th/td and
their children) at 1440, 1280, 900 and 390px against a private mock-mode
stack, with each CronJob, Job, DaemonSet and StatefulSet row expanded at
every width:
- 390px: the Kind track is 90px and no kind label or target value clips;
only the four long controller names truncate with an ellipsis. The
wrapped timestamp values in the expansion no longer clip (a single-line
value had needed 169px in a 142px cell).
- 1440px: no new clipped cell; the StatefulSet service name, which the
Detail column truncates, now reads whole in the expansion.
- No viewport scrolls horizontally.
Unit tests cover the controller section per kind and the table's phone
classes and expansion content.
`frontend-modern/browser-verification.json` carries the receipt.
Builds on #2411. Supersedes #2417, which conflicted with main on the
shared browser-verification receipt.
## What was wrong
The metric, stacked memory and stacked disk bars choose between `60%`
and `60% (265 GB/440 GB)` by estimating the label's width. The estimate
was 5.5px per character plus 8. At the label's 10px type a digit is
6.7px wide and a full stop 3px, so the estimate was off by -7px to +5px
on real labels.
In the Kubernetes clusters table at a 560px viewport the memory bar is
113px wide, the estimate came to 112.5px, the label needs 118px, and it
rendered with an ellipsis. A sweep of the platform tables found 24 such
bars on `main`, all stacked memory bars: 3 on Kubernetes clusters at
560px, 4 on Proxmox overview at 900px, 16 on Docker overview and 1 on
Kubernetes nodes at 1440px.
## The fix
`estimateTextWidth` sums per-glyph advances instead of multiplying a
character count.
- It reads the advances once per page from a hidden probe that carries
the label's type classes, so the estimate follows whichever system font
the browser renders. The advances measured for the macOS system font
stand in where there is no layout (unit tests).
- The value is measured semibold and the detail after it at normal
weight.
- Each model adds the padding its own label sits in (4px in the metric
and disk bars, 8px in the memory bar's chip) instead of sharing one
constant.
Two more gaps in the same decision are closed:
- The stacked memory and disk bars now count the anomaly marker that
shares the label's line.
- The inline per-disk slots are sized after the gap between them. A
two-disk Proxmox node at 900px clipped `backup 80%` by 2px.
A flat safety margin was not enough: the error depends on which glyphs
the label holds, so a margin that stops the clipping also hides labels
that fit. Measuring each label in the DOM would add a layout read per
bar on the Workloads hot path.
## Verification
Playwright sweep of every table on 32 platform routes at 1440, 900, 700,
560 and 390px (160 loads, 2,579 bars), on this branch and on `main`
against the same mock backend:
| | `main` | this branch |
| --- | --- | --- |
| Bars whose chosen label does not fit | 24 | 0 |
| Clipped inline disk labels | 3 | 0 |
| Bars showing the long label | 567 | 550 |
Of the 17 fewer long labels, 24 are the clipped ones, 14 Proxmox guest
disk bars at 900px gained the long form, and 7 memory bars dropped it: 5
that had 1.0px to 2.8px to spare and 2 that overflowed by under 0.5px.
With every glyph forced to Verdana (10% wider) no bar clips; with Arial
(7% narrower) no bar clips and 237 more show the long label. WebKit
matches Chromium.
The probe is the estimator's only layout read: 1.7ms on the 429-bar
Proxmox overview, about 110ns per estimate afterwards. Bar widths still
come from the resize observer alone.
## Not changed here
The storage usage bar on Proxmox > Storage still clips at 390px (72
rows) and by up to 2.3px at 700px (19 rows). It is a different component
that always renders the long label and does not use the estimator; #2418
reworks it.
Validate backup envelopes, source collections and consumed row fields without coercing completion flags, dropping bad rows or treating missing data as empty. Preserve independent evidence and explicit nil PVE collections, keep format errors private and retry only the failed source. Include parser and mounted regressions, subsystem contracts and inspected Chromium/WebKit final-content proof.
Change-source: pulse-maintainer
The original PR 2435 branch carried a stale copy of storage-recovery.md and deleted main's History touch-inspection and pool-to-disk ownership notes, which are unrelated to this change. The squashed rebuild inherited the deletion; this puts both notes back so the change only adds its own coverage clause.