Commit Graph

7753 Commits

Author SHA1 Message Date
pulse-triage[bot] e1e2860d35 Fix accessible controls, resource provenance and deep drawer scrolling (#3222)
Scrolling through a long platform drawer could unmount its owning row
and close the detail being read. REST resource projection also dropped
source provenance, hiding vCenter context and host placement from
owning-snapshot consumers. Diagnostic commands lacked keyboard
scrolling, and dark-theme text and several Patrol control names failed
accessibility checks.

Measure summary rows and inline details together in the shared bounded
window, preserve canonical resource sources, make diagnostic command
blocks focusable, and repair shared contrast and visible control naming.
Browser fixtures await mounted authentication and keep synthetic
provider inventory authoritative. Journey assertions follow current
read-only capabilities, technical disclosures and composed resource
queries. Long settings audits traverse the actual scroll extent; curated
estate checks use native inventory disclosures and search; disk proofs
follow canonical serial-bound shared history; the published
completed-restore-point calendar checks remain intact, including day
selection and filter reset. Update API proofs no longer mount an
unrelated dashboard before each request.

Fresh password login now waits for mounted bootstrap too. The
delayed-bootstrap regression owns and revokes its own token, so it runs
with cookie-only and primary-token fixtures without replacing the
fixture credential. Update API cases share an admitted cookie fixture.
Growth assertions use the current fixed-window header, LXC refresh
assertions use the fixture's canonical identity, and the gated-panel
observer follows actual gate readiness while still detecting visible
unlocked controls. The Docker browser stack explicitly opts into a
bounded development update budget for its shared bridge IP. Production
and login limits remain unchanged.

The remaining recovered failures exposed three test synchronization
defects. Alerts now leaves the whole editor before judging a staged
change and exercises its sibling-focus contract. Protected panel
assertions wait for mounted bootstrap before their existing readiness
timeout. The delayed-token regression uses its own page, avoiding
interception of reads from a departing setup document. CI retains
failed-attempt HTML diagnostics after a successful retry and small JUnit
results for each completed tier, including stable receipts before
probation starts.

Validation includes negative controls for the original drawer,
provenance and password-bootstrap defects, 335 focused frontend tests,
23 authentication-fixture tests, type-checking and a production build.
The cookie-only follow-up matrix passed 39 cases across Chromium, mobile
Chrome and mobile Safari with 18 existing skips. Twelve additional
onboarding cases passed with no retries, and the token-bootstrap matrix
passed 12 cases with cookies alone and 12 with a primary token. Native
Chromium and WebKit checks exercise the gated-panel detector's positive
and negative controls. The earlier remaining-failures matrix passed 31
cases with 10 existing skips, and both disk-history cases passed on
desktop.

Current-build browser verification covers onboarding, accessibility,
VMware context and exclusion boundaries, demo commercial isolation,
persisted Alerts settings, Patrol, availability and background refresh.
Pixel and interaction review covers infrastructure, Agent Doctor,
Patrol, Docker, Kubernetes and vSphere at desktop, tablet and phone
widths in both themes where applicable. Existing timeouts, skips,
mounted-row limits and the 90 ms chart budget remain in place.

The final recovered-failure matrix passed 27 cases with 14 existing
mobile skips using cookies alone, followed by 12 passes with a primary
token, all without retries. The forced desktop table control reproduces
the old focus failure and passes after leaving the editor. The preceding
qualified tree completed all required source checks and the full
stable/probation matrix. Its executed strict chart proof measured p95
61.1 ms against 90 ms with valid capacity. The updated head is being
qualified again before landing.

Governed work: L12 journey verification and the shared L10 windowing
proof. This source change does not publish a release.
2026-10-25 02:30:21 +00:00
rcourtman 12d050a5be Wait for resolved workspace routes before browser journeys
A mounted cookie shell can still be waiting for its default workspace
redirect. Admitting that entry races the next deep link in WebKit. Wait
for the destination and retain controlled missing-admission and resource
snapshot coverage, including rejection of the old helper predicate.

Use the shared content-owner geometry audit for infrastructure onboarding
and assert SPA route changes without waiting for the document load event.
2026-10-25 01:41:31 +00:00
pulse-triage[bot] ef05dae072 Clarify the target and authority for configuration recovery (#3229)
**Clarify the target and authority for configuration recovery**

Put installation and organisation checks before backup transfer.
Separate session management authority, API scopes and archive
decryption; disclose excluded membership state and retained token
bindings. Link the checklist from Recovery and API help, with registered
renderer and mirror controls.

Contract-Neutral: Documents existing configuration-transfer scope and
authorization only; no runtime, route, API, permission or recovery
contract changes.

**Match the documentation viewer routing marker in access controls**

The focused run found that data-doc-link is an empty presence marker,
not the string true. Assert presence without weakening the exact
destination checks, and apply the locked formatter output to the long
token-binding assertion.

Contract-Neutral: Registered test expectation and formatting repair
only; rendered documentation and runtime contracts are unchanged.

---
Fleet candidate `20261025T000604Z-web-product` from the `web-product`
lane. Reviewed tip `bc0e53e577d7f8a4e4810af2853a7e3874f2ee84` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-25 00:59:05 +00:00
rcourtman 2a149603f0 Run native settings scroll regressions in browser CI
Exercise Chromium and WebKit geometry once after browser installation,
before the first shard admits its runtime fixture. Content growth must
complete the new scroll extent and unchanged-extent resets must still fail.
2026-10-25 01:54:59 +01:00
pulse-triage[bot] 1076c78ddd Require observed capacity for storage warnings (#3228)
Keep static and forecast occurrences and timing honest when a storage
percentage has missing or contradictory byte counters. Preserve
empty-store recovery and let explicit usage disablement release an alert
without requiring telemetry. Add real-manager controls and give existing
positive-reading fixtures actual capacity.

Contract-Neutral: Refine admission to the existing capacity lifecycle;
no new alert policy, API, schema, collector, transport or subsystem
shape. The existing alerts contract and registered manager controls
document and verify the boundary.

---
Fleet candidate `20261024T233026Z-core-runtime` from the `core-runtime`
lane. Reviewed tip `e2684f689369d77c876376ff0e3d29753a5d539c` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-25 00:40:21 +00:00
rcourtman 7a211a6f92 fix(e2e): audit scroll position and width in one snapshot
Finish content that reflows after native settings traversal before judging
its width. Measure bottom position and horizontal overflow together, and
keep unchanged-extent scroll resets as failures.

Native Chromium and WebKit controls reproduce the separate-read race,
verify the newly revealed footer, and retain overflow and reset detection.
2026-10-25 01:38:54 +01:00
pulse-triage[bot] d2e38d3505 Clarify the target and authority for configuration recovery
Put installation and organisation checks before backup transfer. Separate session management authority, API scopes and archive decryption; disclose excluded membership state and retained token bindings. Link the checklist from Recovery and API help, with registered renderer and mirror controls.

Contract-Neutral: Documents existing configuration-transfer scope and authorization only; no runtime, route, API, permission or recovery contract changes.
Change-source: pulse-maintainer
2026-10-25 01:10:40 +01:00
pulse-triage[bot] 420bf67363 Explain completed backup counts without losing incomplete evidence (#3227)
**Explain completed backup counts without losing incomplete evidence**

Distinguish the loaded inventory, completed-point totals, dated activity
and reported-size volume in the shipped Recovery guide. Keep snapshots,
unknown chronology, list filters and guest safety separate. Register
consumer/model checks for the explanation and its existing safety links.

Contract-Neutral: Documents existing Proxmox completion and display
semantics only; no runtime, API, policy, permission, retention or
recovery contract changes.

**Keep the registered backup guidance assertions readable**

Wrap the new long assertions and section traversal for the locked
formatter. The host formatter file is unreadable; exact offline-source
checks remain the validation route.

Contract-Neutral: Test formatting only; no runtime or contract change.

**Match the named backup help entry instead of its position**

CI for PR 3224 selected the new PBS evidence link because it shares the
existing health-help destination. Keep both useful links and assert that
each guide still has one health-help entry with the exact PBS target and
documentation routing attribute.

Contract-Neutral: Registered test selector repair only; guide copy and
rendered behaviour are unchanged from the composed reviewed candidate.

**Validate repeated named health-help links independently**

The full frontend suite found that Troubleshooting already has two
legitimate links with the same health-help label. Require at least one
named entry in each guide and check every matching entry's exact target
and viewer routing instead of imposing an unsupported uniqueness
constraint.

Contract-Neutral: Registered test assertion correction only; no document
or rendered behaviour change.

---
Fleet candidate `20261024T230015Z-web-product` from the `web-product`
lane. Reviewed tip `d677be8d59303884a1a3580829e91d2b07ffbe44` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-25 00:02:37 +00:00
pulse-triage[bot] e2684f6893 Require observed capacity for storage warnings
Keep static and forecast occurrences and timing honest when a storage percentage has missing or contradictory byte counters. Preserve empty-store recovery and let explicit usage disablement release an alert without requiring telemetry. Add real-manager controls and give existing positive-reading fixtures actual capacity.

Contract-Neutral: Refine admission to the existing capacity lifecycle; no new alert policy, API, schema, collector, transport or subsystem shape. The existing alerts contract and registered manager controls document and verify the boundary.
Change-source: pulse-maintainer
2026-10-25 00:37:07 +01:00
rcourtman 72f6d2cf7d fix(e2e): synchronize editor commits and retain retry diagnostics
Judge consuming panels after their protected document has mounted, and
give the delayed-token regression its own bootstrap page. Leave the whole
Alerts editor before checking for a staged change, including its desktop
focus and card Save contracts. Keep the existing panel timeouts.

Preserve failed-attempt HTML diagnostics when a first retry succeeds and
retain small JUnit results for every completed tier. Upload stable evidence
before probation starts. Integrate the published node disk observation
repair before qualification.
2026-10-25 00:33:48 +01:00
pulse-triage[bot] 51d1a5f503 Merge reviewed backup guidance for CI repair
Compose the retained guide candidate on current main before correcting its existing help-link test. No frontend runtime or contract change.

Contract-Neutral: Source composition only; backup guide behaviour is unchanged from the reviewed candidate.
Change-source: pulse-maintainer
2026-10-25 00:01:03 +01:00
rcourtman c0c54de765 fix(e2e): await authenticated bootstrap in cookie-only fixtures
Fresh password login must await the mounted workspace before a caller
opens an onboarding route. Own and revoke the bootstrap regression token
without replacing the primary credential, and bootstrap update API tests
once per worker when CI provides cookies alone.

Opt the synthetic shared-IP stack into a finite development update budget
without changing production, authentication or configuration limits.

Observe gated panels through actual gate readiness. Keep the fixed 24h
growth assertion on its native header and select the retained LXC drawer
with the fixture's canonical resource identity. Integrate the published
filesystem-observation and issue-topic repairs before qualification.
2026-10-24 23:50:14 +01:00
pulse-triage[bot] b02f9659c0 Keep unavailable Proxmox node disks from resolving warnings
Reuse canonical disk observation admission before node alert evaluation. Missing capacity and contradictory readings preserve trusted occurrences and restart activation timing; measured zero, explicit policy and real linked-agent handover keep their semantics.

Contract-Neutral: Reuse existing disk observation and alert lifecycle contracts; no API, schema or ownership policy shape changes.
Change-source: pulse-maintainer
2026-10-24 23:24:06 +01:00
pulse-triage[bot] 8bd7fa4f5d Explain completed backup counts without losing incomplete evidence
Distinguish the loaded inventory, completed-point totals, dated activity and reported-size volume in the shipped Recovery guide. Keep snapshots, unknown chronology, list filters and guest safety separate. Register consumer/model checks for the explanation and its existing safety links.

Contract-Neutral: Documents existing Proxmox completion and display semantics only; no runtime, API, policy, permission, retention or recovery contract changes.
Change-source: pulse-maintainer
2026-10-24 22:53:37 +01:00
rcourtman 708e8f94fb merge: reconcile current monitoring and E2E contracts
Preserve published absent-disk, completed-backup and accessible-name fixes
alongside the verified drawer and resource-provenance changes.

Follow native inventory disclosures, full settings scroll geometry and
shared disk-history responses so browser proofs exercise the current UI
without weakening row, layout, signature or chart-latency budgets.
2026-10-24 22:39:27 +01:00
pulse-triage[bot] 02aff4ab7a Keep the established disk owner when a listed capacity is unknown
Retain the linked summary filesystem identity when its capacity becomes unavailable. Correct synthetic activation and authoritative-removal fixtures to exercise existing rules: disk recovery stays immediate, and an empty report does not establish removal. No delay, collector or policy change.

Contract-Neutral: Apply established identity and observation rules only; public API, canonical projection, thresholds and recovery policy are unchanged.
Change-source: pulse-maintainer
2026-10-24 22:10:21 +01:00
rcourtman 58f9398a41 fix(e2e): preserve accessible controls and deep drawer navigation
Preserve source provenance in REST-loaded resources so owning-snapshot
consumers retain provider context and host placement. Keep visible control wording in accessible names and retain readable command
and navigation text in both themes. Token fixtures now await mounted browser
bootstrap before handing control to the next journey.

Measure bounded platform table items together with their inline details so
scrolling down a tall drawer cannot unmount the resource being inspected.
Retain regression coverage for bootstrap timing, drawer state and scroll
extent, responsive controls, Patrol and availability, and align navigation
assertions with current read-only capabilities and composed resource queries.
Provider fixtures retain one authoritative inventory across transport updates.
2026-10-24 21:41:34 +01:00
pulse-triage[bot] 6e35e3252b Keep unavailable agent filesystems from resolving disk alerts
Apply existing canonical disk observation admission to filesystem alert evaluation. Hold incidents across unavailable rows or empty reports, interrupt timed evidence and retain linked-node ownership only for held alerts. Keep measured-zero recovery, policy changes and authoritative removal.

Contract-Neutral: Shares existing disk metric admission and unavailable-observation rules without API, schema, collection or canonical projection changes.
Change-source: pulse-maintainer
2026-10-24 21:40:10 +01:00
pulse-triage[bot] be5a59d66c Keep incomplete backup entries out of completed restore totals (#3218)
**Keep incomplete backup entries out of completed restore totals**

Use the same completion predicate for latest backups, restore-point and
byte totals, PBS coverage and per-day count/volume charts. Keep running
and failed entries visible, with separate counts and honest
inventory-entry labels. Completion is not verification, restore or guest
thaw.

Add registered model and consuming-table regressions for mixed and
incomplete-only inventories, unknown chronology and completion
transitions. Guest operations and server policy are unchanged.

Contract-Neutral: Apply established completion semantics and
inventory-entry wording only; resource transport, identity, persistence
and shared table contracts are unchanged.

**Use supported role-query options in backup completion tests**

The committed-source type check rejected exact on ByRoleOptions. String
role names already match exactly; remove the two unsupported options
without changing assertions or runtime source.

**Verify completed backup totals in production browsers**

Record actual production-asset proof at 1440px Chromium and 320px
WebKit, including count/volume, incomplete-only inventory,
keyboard/touch details and Coverage navigation. Preserve initial driver
failures and targeted follow-up evidence; all fourteen retained captures
were opened natively.

Keep the both-inventories-failed negative assertion matched to the new
completed-point wording, so it still rejects a fabricated zero summary
rather than merely rejecting retired copy.

**Keep visible Infrastructure and Patrol text in accessible action
names**

Name Add shortcuts by their action and group, retain update counts and
affected systems, and let Patrol rows expose their full visible
evidence. Preserve scoped handlers, read-only restrictions and native
selection; keep the WCAG rule unchanged.

Contract-Neutral: Accessible-name correction only at unchanged
agent-lifecycle and API boundaries: no enrollment, update execution, API
payload, authorisation, state or route changes. Frontend and Patrol
contracts and registered consuming tests are updated.

**Keep read-only update indicators inert even with a retained callback**

The new read-only control found that the component relied solely on its
parent to remove Agent Doctor callbacks. Guard both responsive chips
locally. Match the existing registry-routing fixture by its displayed
non-resource-leading title.

Contract-Neutral: Enforce the existing read-only UI invariant only; no
agent lifecycle, API, update execution, payload or permission change.
The frontend contract and registered component and Patrol consuming
tests cover the boundary.

**Align Infrastructure architecture guard with visible Add naming**

The complete frontend suite passed 22,274 tests and failed only this
retired source-string assertion. Keep its route-backed action guard and
require the new visible-action/group accessible name instead.

**Verify accessible Infrastructure and Patrol controls in browsers**

Bind final built producer bytes to desktop Chromium and narrow WebKit
interaction/pixel evidence. Preserve the original backup own-parent
receipt and all adverse fixture, query and manual-review results in the
lane receipts.

---
Fleet candidate `20261024T184532Z-web-product` from the `web-product`
lane. Reviewed tip `5f1c3d36fb69772f1371a5a7bc68368e5866ad93` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 20:30:28 +00:00
pulse-triage[bot] 30b3e4c63b Keep absent host disk readings out of live charts and history (#3217)
**Keep absent host disk readings out of live charts and history**

Share canonical disk admission with host-agent recording and fallback,
preserve measured zero and recorded observations, and check both History
and summary routes.

Contract-Neutral: Restore existing canonical disk-presence semantics; no
new API, authentication, identity, persistence schema or retention
contract.

**Use store precision in host disk preservation regression**

Seed a whole-second observation, as existing metrics-store round-trip
tests do, while retaining the exact timestamp and value assertions.
Production source is unchanged.

---
Fleet candidate `20261024T184532Z-core-runtime` from the `core-runtime`
lane. Reviewed tip `cd4790a9f0a4a409b420113ac4be7f70d108c3d9` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 20:26:49 +00:00
courtmanr@gmail.com c4486a177a Keep a real change out of the Highlights example
The Highlights guidance used "Resource Overview shows alerts, recent
trends and longer history together" as its example. That is a real
v6.6.0 change, and a test draft of the v6.6.0 notes copied it almost
word for word, so a later release could repeat it as if it were new.

The generator and the release-notes template now describe the shape
instead, the page or feature and then what it now does, and say to
describe only changes in this release. The slogan counterexamples stay,
and the release-assets test pins the new sentence.
2026-10-24 20:43:52 +01:00
pulse-triage[bot] c93757fb4b Keep absent host disk readings out of live charts and history
Share canonical disk admission with host-agent recording and fallback, preserve measured zero and recorded observations, and check both History and summary routes.

Change-source: pulse-maintainer
Contract-Neutral: Restore existing canonical disk-presence semantics; no new API, authentication, identity, persistence schema or retention contract.
2026-10-24 19:59:18 +01:00
pulse-triage[bot] 487455045c Keep read-only update indicators inert even with a retained callback
The new read-only control found that the component relied solely on its parent to remove Agent Doctor callbacks. Guard both responsive chips locally. Match the existing registry-routing fixture by its displayed non-resource-leading title.

Contract-Neutral: Enforce the existing read-only UI invariant only; no agent lifecycle, API, update execution, payload or permission change. The frontend contract and registered component and Patrol consuming tests cover the boundary.
Change-source: pulse-maintainer
2026-10-24 19:54:49 +01:00
pulse-triage[bot] d14efbfa4b Keep visible Infrastructure and Patrol text in accessible action names
Name Add shortcuts by their action and group, retain update counts and affected systems, and let Patrol rows expose their full visible evidence. Preserve scoped handlers, read-only restrictions and native selection; keep the WCAG rule unchanged.

Contract-Neutral: Accessible-name correction only at unchanged agent-lifecycle and API boundaries: no enrollment, update execution, API payload, authorisation, state or route changes. Frontend and Patrol contracts and registered consuming tests are updated.
Change-source: pulse-maintainer
2026-10-24 19:51:37 +01:00
pulse-triage[bot] 806b9ac516 Preserve backup completion and agent startup contracts together
Change-source: pulse-maintainer
2026-10-24 19:48:04 +01:00
pulse-triage[bot] a91d1ed89d Keep incomplete backup entries out of completed restore totals
Use the same completion predicate for latest backups, restore-point and byte totals, PBS coverage and per-day count/volume charts. Keep running and failed entries visible, with separate counts and honest inventory-entry labels. Completion is not verification, restore or guest thaw.

Add registered model and consuming-table regressions for mixed and incomplete-only inventories, unknown chronology and completion transitions. Guest operations and server policy are unchanged.

Change-source: pulse-maintainer
Contract-Neutral: Apply established completion semantics and inventory-entry wording only; resource transport, identity, persistence and shared table contracts are unchanged.
2026-10-24 18:49:17 +01:00
rcourtman 9cb06ef6ef Show agents awaiting a report after server restart (#3211)
After a server restart, Pulse showed saved agents offline before they
had a chance to report. Recent enrollments now show “Waiting for first
report” until an accepted report arrives or their existing reporting
lease expires.

The shared read model preserves identity and the historical receipt
without inventing metrics. Live updates carry the same source delivery
state, so a browser left open during an update withdraws its previous
current readings. The expanded drawer keeps stored history available and
shows an informational wait without a fabricated zero-value reading.
Expired agents remain offline, rejected buffered reports cannot end the
wait, removed agents remain absent, and provider errors retain their own
status. Machines, resource details and Settings consume the same state.

Validation: targeted frontend and backend regressions, broader registry
and connection checks, type checking, build, governance checks, and
desktop/mobile browser verification of startup, first report, restart
and expiry.

Refs #2980. This change addresses the startup display and does not
establish the cause of the cluster DNS failure reported there.
2026-10-24 18:44:11 +01:00
rcourtman bc5491b6d1 Withdraw cached live history when agent reporting stops
An open drawer could retain a current-only reply after its agent entered
the first-report wait. Withdraw live snapshots immediately and refresh on
reporting transitions while preserving real stored observations.

Integrate published main while retaining the webhook acknowledgement and
chart optimizations. Keep guest metric admission under provider ownership.

Refs #2980
2026-10-24 17:51:28 +01:00
pulse-triage[bot] 105fb05cc3 Decode native retained metric numbers without per-point reflection
Keep database/sql conversion for atypical values and rejection of NULL, malformed and overflowing observations. Compare native and fallback scans against primitive destinations and protect the allocation-free native path.

Contract-Neutral: Retained observations, numeric acceptance and rejection, SQL, sampling, source choice, extrema and access boundaries are unchanged; only application-side numeric assignment avoids per-observation reflection.
Change-source: pulse-maintainer
2026-10-24 17:32:56 +01:00
rcourtman ddaedc8c78 Keep unreported chart fallbacks empty after lease expiry
An expired saved enrollment still has no current telemetry. Keep summary
charts from turning that deadline into zero-valued live samples, while
preserving real stored history. Cover both sides of the reporting lease
and align the remaining pending-label assertions with the shared wording.

Refs #2980
2026-10-24 17:23:25 +01:00
pulse-triage[bot] 994e9388b5 Keep deleted webhook work bound to its original destination (#3210)
**Keep deleted webhook work bound to its original destination**

Require an enabled saved ID before queued firing or recovery delivery. A
sibling at the same URL cannot release a deleted destination’s retained
payload and credentials. Keep the URL fallback for legacy ID-less work,
preserve admitted snapshots and cancellation history, and prove
restart/operator-retry isolation with real receivers.

**Acknowledge persisted webhook deletion to the destination editor**

Return the explicit success boolean the existing editor requires after
durable and live removal, while retaining the legacy status field. Pin
the response contract so a successful deletion is not displayed as
failed and does not encourage blind retries.

---
Fleet candidate `20261024T150012Z-core-runtime` from the `core-runtime`
lane. Reviewed tip `94a50e75b017901ac31e15e27881aac46abce32c` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 16:18:28 +00:00
rcourtman 5f0037fc25 Show agents awaiting a report after server restart
Keep retained enrollments unknown while their accepted-report lease is
current, then show offline if no fresh report arrives. Preserve historical
timestamps, removals and report ordering without manufacturing telemetry.
Use the shared first-report state in Machines, resource details and Settings.

Refs #2980
2026-10-24 16:45:39 +01:00
pulse-triage[bot] 94a50e75b0 Acknowledge persisted webhook deletion to the destination editor
Return the explicit success boolean the existing editor requires after durable and live removal, while retaining the legacy status field. Pin the response contract so a successful deletion is not displayed as failed and does not encourage blind retries.

Change-source: pulse-maintainer
2026-10-24 16:21:39 +01:00
pulse-triage[bot] fbdef9ac69 Record counted-navigation semantics at the paid shell boundary
Document the actual shared AppLayout accessibility delta and its maintained tests, without reinstating the superseded portal graph contract. Keep visible label and badge numbers together in desktop/mobile accessible names while retaining severity descriptions, routes, counts and permissions. Runtime bytes and the existing own-parent browser receipt are unchanged.

Change-source: pulse-maintainer
2026-10-24 16:14:01 +01:00
pulse-triage[bot] 5e6ae65f52 Complete counted-navigation repair without replacing the landed portal fix
Compose retained 4ac1d7ba15 and its exact imported history on current main. Retain the proved WCAG label/count correction, its complete fixture coverage and the matching integration checker graph. Do not re-parent or repeat the browser proof.

Main e570ad4132 already patches portal Vitest/mocker to 4.1.12, Vite to 7.3.7 and Rollup to 4.65.0. Resolve all portal inputs, generated manifest and cloud-paid contract to those exact landed bytes, removing the superseded graph and its test instead of downgrading or extending it. No portal delta remains to validate. Preserve the original uncertain portal execution separately; this merge neither replays nor clears it.

Change-source: pulse-maintainer
2026-10-24 16:12:59 +01:00
pulse-triage[bot] 5c6811f93d Keep deleted webhook work bound to its original destination
Require an enabled saved ID before queued firing or recovery delivery. A sibling at the same URL cannot release a deleted destination’s retained payload and credentials. Keep the URL fallback for legacy ID-less work, preserve admitted snapshots and cancellation history, and prove restart/operator-retry isolation with real receivers.

Change-source: pulse-maintainer
2026-10-24 16:08:19 +01:00
pulse-triage[bot] ea99456ffd Assemble retained metric series directly by statement-local number (#3205)
**Assemble retained metric series directly by statement-local number**

Avoid per-observation string resolution and nested-map flushes for
interleaved filtered fleets. Bind only nonempty series after each read
and bound the direct buffers, preserving the existing wide-sparse
fallback, SQL snapshots, tiers and exact observations. Verify against
single-resource readers on both layouts.

**Cap retained chart observations before allocating wire points**

Share the existing time-nearest selection by original indices, so chart
conversion materialises only selected observations. Preserve exact
timestamps, values, tie breaks, degenerate spans and oldest-source
metadata. Check the frozen former sampler across 1,440 cases and the
exported fallback contract.

Contract-Neutral: Exact chart observations, wire schema, sampling policy
and guest/storage lifecycle contracts are unchanged; only index
selection and allocation order change.

---
Fleet candidate `20261024T123325Z-core-runtime` from the `core-runtime`
lane. Reviewed tip `bf9f0ed9822c8ee72ca25b5caecb35a2cd4a5881` on `main`.

[How Pulse handles
triage](https://github.com/rcourtman/Pulse/blob/main/docs/AI_TRANSPARENCY.md)
2026-10-24 14:51:32 +00:00
pulse-triage[bot] 5e30e90357 Compose retained portal and counted-navigation repair
Change-source: pulse-maintainer
2026-10-24 15:28:46 +01:00
rcourtman 97f55638c9 Prove demo auto sign-in in the public browser smoke (#3204)
Since v6.5.0 demo mode signs a fresh visitor in with the published
demo credentials, so the login form never stays on screen for a first
visit. The browser smoke still waited two minutes for that form and
failed, which blocked every stable demo convergence once the Tailscale
step worked again. It went unnoticed because the demo update had not
got past Tailscale since v6.5.0 shipped.

The smoke now proves the visitor's real path, a fresh tab reaching the
connected workspace, when the server reports demo mode. A second
context sets the frontend's own pulse-demo-auto-login marker to keep
proving the login form and a manual demo sign-in. Against the live
demo the old script times out and the new one passes both phases. The
policy test pins the marker to localStorage.ts so a rename fails in
source checks rather than on the live demo.
2026-10-24 15:06:41 +01:00
rcourtman 572930fded Make release Highlights name concrete changes (#3203)
Make release Highlights name concrete changes

The generator only asked for "one to three plain-text outcomes", so it
produced slogans such as "See problems, recent trends and longer
history together" that tell a user nothing about what changed. These
lines are what the update banner shows before someone installs.

The generator prompt and the release-notes template now ask for the
release's biggest specific changes and where users find them, with an
example and named anti-examples, and the release-assets test pins that
wording. Their description of the post-update modal also follows the
new plain changelog, which no longer collapses upgrade notes or puts
Highlights above the changes.
2026-10-24 14:45:36 +01:00
rcourtman cdd3022d68 Name demo Patrol findings by their unified resource (#3202)
## Problem

Mock and demo mode synthesize Patrol findings from the legacy state
snapshot (`synthesizeDemoPatrolFindings`) and stamped each one with the
snapshot's source ID: `nebula-1-mock`, `mock-cluster-1-pve1-local`,
`pmg-edge`, `atlas-4-<hex>`, `mock-cluster-2-pve12-319`. Real findings,
Inbox subjects (since #3188), the resource-scoped findings list and
resource intelligence all use the unified resource ID, and they join by
exact ID.

Seen on main (82df77f2f) on a private mock stack and a DEMO_MODE stack:

- The Inbox item "Docker host offline on Field Office Edge 01" (subject
`agent-b9070eb05b18bb77`) said "This is an alert and Patrol has not
raised a finding about it". It offered no "Browse Patrol findings for
this resource", although the demo finding "Docker host "Field Office
Edge 01" is offline" was open.
- In DEMO_MODE (the public demo's configuration, between scheduled
Patrol passes), "Storage usage on west-a-iso-library" said the same next
to the open finding "Storage "west-a-iso-library" is 88% full".
- The host finding never folded under its `docker:nebula-1-mock` alert.
The storage finding folded only because that alert's raw reference
happens to equal the legacy storage ID.
- `GET /api/ai/intelligence?resource_id=agent-b9070eb05b18bb77` (the
resource drawer's read) returned grade A with no findings.
- The LXC memory finding was typed `container`, which
`normalizeFindingResourceTypes` reads back as `node`.

## Change

- `internal/ai/demo.go`: `demoResourceResolver` resolves the reference
an alert on each record would carry, using Patrol's alert reference
resolver. That is the same resolution `AttentionSubjectResourceID` gives
Inbox subjects, so a demo finding names the resource that an Inbox item
about the same record names.
- App containers resolve through the container views by host and
container ID. Mock container IDs are too short to bind a Docker alert
reference.
- Without a read state, or before its registry has ingested anything,
the resolver derives a registry from the snapshot, as the real producers
do. That way a first cycle cannot pin source IDs for the life of the
process.
- Once the registry holds resources it is the only authority. A record
it lacks or refuses, or one that binds another type of resource, keeps
its source ID. Guests are typed `vm` or `system-container`.
- Finding IDs and keys are unchanged, because demo run history
references them.
- Contract note added in `ai-runtime.md` under the alert-mirror section.

## Verification

- `TestPatrolService_RunDemoPatrolCycle_NamesUnifiedResources` in
`internal/ai/demo_test.go` covers:
- the unified ID and type per kind, checked against the Inbox's subject
resolution;
  - lookup by unified ID (`GetFindingsForResource`);
  - both alert folds;
  - the same IDs with no read state;
  - a registry that has not ingested yet;
  - a registry that lacks a record.
- Negative controls via `go test -overlay` each fail at the expected
assertion: main's `demo.go`, no snapshot fallback, always derive, and
the legacy guest type. The whole `internal/ai` package passes.
- Live check of an OSS build from this branch on pulse-dev, mock and
DEMO_MODE:
- Both Inbox items now say "Patrol also raised … for this resource" and
offer Browse.
  - Browse lists "Patrol found 1 issue on Field Office Edge 01".
- After a Patrol run both findings fold under their alerts (lasting
decisions in the Inbox; Activity shows "3 findings mirror an active
alert").
  - The host's intelligence now reports grade C with the finding.
  - Checked at 1440 and 390 wide, with no console errors.

## Not changed

- Mock Docker container IDs are `<host>-<12 hex>`, so mock container
alerts keep their raw `docker:<host>/<id>` subject and cannot join
container findings. Real Docker IDs are 64-hex.
- Suppression rules created against legacy-ID demo findings in earlier
mock sessions no longer match.
- The findings store keeps a finding's first resource ID for the life of
the process. If a demo cycle races the registry's first ingest and a
saved operator link folds one of its records into another resource, that
finding keeps the derived ID until restart.
2026-10-24 14:38:28 +01:00
rcourtman df79b7716a Prove demo auto sign-in in the public browser smoke
Since v6.5.0 demo mode signs a fresh visitor in with the published
demo credentials, so the login form never stays on screen for a first
visit. The browser smoke still waited two minutes for that form and
failed, which blocked every stable demo convergence once the Tailscale
step worked again. It went unnoticed because the demo update had not
got past Tailscale since v6.5.0 shipped.

The smoke now proves the visitor's real path, a fresh tab reaching the
connected workspace, when the server reports demo mode. A second
context sets the frontend's own pulse-demo-auto-login marker to keep
proving the login form and a manual demo sign-in. Against the live
demo the old script times out and the new one passes both phases. The
policy test pins the marker to localStorage.ts so a rename fails in
source checks rather than on the live demo.
2026-10-24 14:31:21 +01:00
pulse-triage[bot] bf9f0ed982 Cap retained chart observations before allocating wire points
Share the existing time-nearest selection by original indices, so chart conversion materialises only selected observations. Preserve exact timestamps, values, tie breaks, degenerate spans and oldest-source metadata. Check the frozen former sampler across 1,440 cases and the exported fallback contract.

Change-source: pulse-maintainer
Contract-Neutral: Exact chart observations, wire schema, sampling policy and guest/storage lifecycle contracts are unchanged; only index selection and allocation order change.
2026-10-24 14:08:51 +01:00
rcourtman ebfee8737f Show post-update What's New as a plain changelog (#3201)
Show post-update What's New as a plain changelog

The dialog opened with three vague Highlights cards, hid the actual
changes behind a collapsed "All changes" disclosure and tucked upgrade
notes into a second one. That is not what people expect from a
changelog, and the Highlights repeat the pre-update banner's summary.

The dialog now reads like a conventional changelog: version and release
date in the header, Known issues and Breaking changes first, optional
screenshots, then every change group as headed bullet lists and the
upgrade notes last, with nothing collapsed. Highlights stay in the
pre-update banner and only stand in for the change list when a release
has no change groups.
2026-10-24 14:07:52 +01:00
courtmanr@gmail.com 842dbda6b8 Make release Highlights name concrete changes
The generator only asked for "one to three plain-text outcomes", so it
produced slogans such as "See problems, recent trends and longer
history together" that tell a user nothing about what changed. These
lines are what the update banner shows before someone installs.

The generator prompt and the release-notes template now ask for the
release's biggest specific changes and where users find them, with an
example and named anti-examples, and the release-assets test pins that
wording. Their description of the post-update modal also follows the
new plain changelog, which no longer collapses upgrade notes or puts
Highlights above the changes.
2026-10-24 14:06:27 +01:00
rcourtman b45b5562fa Name demo Patrol findings by their unified resource
Mock and demo mode synthesize Patrol findings from the legacy state
snapshot and stamped each one with the snapshot's source ID
(nebula-1-mock, mock-cluster-1-pve1-local). Everything that joins a
finding to its resource uses the unified ID: since #3188 an Inbox item
names its subject by the unified resource its alert resolves to, and the
resource-scoped findings list and resource intelligence look findings up
by that ID. On a mock or DEMO_MODE stack the Docker host offline item
therefore said "Patrol has not raised a finding about it" beside an open
finding on that host, offered no Browse button, the host's intelligence
showed no findings, and the finding never folded under its alert. The
LXC memory finding was also typed "container", which reads back as
"node".

Resolve the reference an alert on each record carries the way Inbox
subjects resolve, app containers through the container views (mock
container IDs are too short to bind a Docker alert reference), and the
snapshot's own registry when the read state has not ingested the record
yet, so a first cycle cannot pin source IDs for the life of the process.
Guests are typed vm or system-container.
2026-10-24 13:49:11 +01:00
courtmanr@gmail.com 1eb0ae5261 Merge remote-tracking branch 'origin/main' into fix/whats-new-plain-changelog 2026-10-24 13:40:17 +01:00
pulse-triage[bot] c36672b2a7 Assemble retained metric series directly by statement-local number
Avoid per-observation string resolution and nested-map flushes for interleaved filtered fleets. Bind only nonempty series after each read and bound the direct buffers, preserving the existing wide-sparse fallback, SQL snapshots, tiers and exact observations. Verify against single-resource readers on both layouts.

Change-source: pulse-maintainer
2026-10-24 13:38:25 +01:00
courtmanr@gmail.com bbdcfa95f4 Show post-update What's New as a plain changelog
The dialog opened with three vague Highlights cards, hid the actual
changes behind a collapsed "All changes" disclosure and tucked upgrade
notes into a second one. That is not what people expect from a
changelog, and the Highlights repeat the pre-update banner's summary.

The dialog now reads like a conventional changelog: version and release
date in the header, Known issues and Breaking changes first, optional
screenshots, then every change group as headed bullet lists and the
upgrade notes last, with nothing collapsed. Highlights stay in the
pre-update banner and only stand in for the change list when a release
has no change groups.
2026-10-24 13:36:26 +01:00
rcourtman 1ffa17a10c Merge remote-tracking branch 'origin/main' into fix/demo-tailnet-ci-deploy-client 2026-10-24 13:28:42 +01:00