Commit Graph

978 Commits

Author SHA1 Message Date
rcourtman 64c0a3f9df Scope browser OS acquisition to the runner's signed Ubuntu sources
An unrelated Microsoft repository returned 403 during fresh-index admission and stopped a browser shard before any test could run. Load the hosted runner's existing Ubuntu Deb822 definition for browser packages, preserving its mirrors and signature policy. Fail when that definition is missing, unreadable or empty and keep strict index and archive hash checks.

Exercise the real apt parser, exclusion of unrelated feeds, missing definitions and incomplete index failures in private acquisition directories. Register the package helper and policy with their exact verification routes, and update the fixture helper's governance assertion to its scoped proof contract.
2026-10-25 04:00:03 +00: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
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
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
rcourtman bc39aa5908 Move demo deploys to the tag:ci-deploy Tailscale client
The demo update and recovery workflows still joined the tailnet with
the July 2026 tag:infra OAuth client. That client was revoked on 30
September, when the private repositories moved to narrow clients, and
the public repository was missed. Since then every demo convergence
step has failed with an OAuth 401, so stable releases cannot converge
and the hourly reconcile keeps retrying v6.5.0.

Both workflows now use the TS_CI_DEPLOY_OAUTH_* binding that the
browser update qualification already expects, restricted to
tag:ci-deploy. The tailnet policy already grants that tag SSH to
pulse-relay, the demo host, so no policy change is needed. One narrow
client now serves all three workflows, and the broad tag:infra
identity is gone from this repository.
2026-10-24 13:25:23 +01:00
rcourtman 82df77f2f5 Treat a deleted convergence owner as terminal (#3197)
Treat a deleted convergence owner as terminal

The hourly "Reconcile release convergence debt" job has failed every run
since 13 Oct. The v6.5.0 activation marker names convergence run
37395942598 as its owner, and that run was deleted from Actions with the
rest of the 30 Sep - 8 Oct release history. The immutable marker
outlives
Actions history, so the reconciler and release-convergence.yml both
waited
forever on an owner that can no longer be read, and the permanently red
job hid real failures such as the rc.6 paid-broker miss.

GitHub only deletes a run that has completed or is older than two weeks,
which is beyond every convergence job timeout, so a definite 404 is a
terminal owner. Both the reconciler and the successor's adoption wait
now
proceed from the validated marker in that case. Any other read failure
still waits or fails.

Also remove the workflow_run retry job. Convergence runs are dispatched
with GITHUB_TOKEN, and GitHub does not deliver workflow_run for them:
the
job fired seven times ever, each for a run an operator started by hand,
and never after 29 Aug while dozens of bot-dispatched failures were
recovered by the hourly schedule. The schedule is documented as the
retry
mechanism.

v6.5.0 is served on every surface (Docker aliases at the marker digest,
Helm index entry, paid broker, demo /api/version), but no convergence
run
has proved it. The next scheduled pass dispatches a fresh v6.5.0
convergence; its demo surface will fail until the Tailscale OAuth client
behind TS_OAUTH_CLIENT_ID/TS_OAUTH_SECRET is rotated, as it returns 401.
2026-10-24 12:45:42 +01:00
rcourtman ca3812e5ed Treat a deleted convergence owner as terminal
The hourly "Reconcile release convergence debt" job has failed every run
since 13 Oct. The v6.5.0 activation marker names convergence run
37395942598 as its owner, and that run was deleted from Actions with the
rest of the 30 Sep - 8 Oct release history. The immutable marker outlives
Actions history, so the reconciler and release-convergence.yml both waited
forever on an owner that can no longer be read, and the permanently red
job hid real failures such as the rc.6 paid-broker miss.

GitHub only deletes a run that has completed or is older than two weeks,
which is beyond every convergence job timeout, so a definite 404 is a
terminal owner. Both the reconciler and the successor's adoption wait now
proceed from the validated marker in that case. Any other read failure
still waits or fails.

Also remove the workflow_run retry job. Convergence runs are dispatched
with GITHUB_TOKEN, and GitHub does not deliver workflow_run for them: the
job fired seven times ever, each for a run an operator started by hand,
and never after 29 Aug while dozens of bot-dispatched failures were
recovered by the hourly schedule. The schedule is documented as the retry
mechanism.

v6.5.0 is served on every surface (Docker aliases at the marker digest,
Helm index entry, paid broker, demo /api/version), but no convergence run
has proved it. The next scheduled pass dispatches a fresh v6.5.0
convergence; its demo surface will fail until the Tailscale OAuth client
behind TS_OAUTH_CLIENT_ID/TS_OAUTH_SECRET is rotated, as it returns 401.
2026-10-24 11:40:23 +01:00
rcourtman 2d498a35d2 Re-dispatch Pro promotion refused by a moved pulse-pro main
pulse-pro gives a promotion run credentials only while that run is
still its current main. Any pulse-pro merge that lands while the run is
queued or validating, roughly 20 minutes, makes the refusal certain.
The convergence caller treated it like any other failure, so the
release stayed off the Pro broker until the hourly reconcile happened
to retry. That race caused five of the last six Pro promotion failures
(12, 17 and 24 October); on 24 October it held v6.6.0-rc.6 back from
Pro installs on the RC channel.

The refusal happens before credentials, so nothing was mutated. The
caller now re-dispatches on the new main when every failed job failed
only the source check and pulse-pro main has moved off the run's head,
up to five attempts in the existing one-hour budget. Every other
failure stays terminal, and only the terminal failure is annotated so
reconciliation still finds exactly one private run URL.
2026-10-24 11:07:44 +01:00
rcourtman a32356ae94 Describe the Assistant surface as Pulse Mobile chat
With the web chat window and its backend routes retired (#3126,
#3137), the pulse_assistant surface only serves Pulse Mobile's chat.
Its manifest description still called it the explanation and handoff
surface for Patrol findings, and that text is public: the docs/AI.md
overview, the MCP README surface block, and the External agents
settings panel all show it. It now names the Pulse Mobile role and says
the web chat is retired.

The browser's fallback affordances for an Assistant surface with none
declared still offered interactive questions. They now match the
backend default of tools only, so no client path advertises a question
tool nobody can answer.
2026-10-23 16:10:15 +01:00
rcourtman dcbfd2d86d Remove chat backend routes only the web chat used
The in-app Assistant chat window was retired in #3126. Several backend
routes existed only for it, and Pulse Mobile, the remaining chat client,
never called them: assistant surface-tools, workflow-prompt render,
question answers, and the session summarize, fork, undo, redo, steer,
diff, revert and unrevert sub-resources. This removes them along with
the handlers, service and session-store methods, the persisted redo
stack, session compaction, mid-turn steering and the question-answer
wait behind them.

The question tool needed more than a route removal. Interactive chat
still offered pulse_question, and Pulse Mobile has no way to answer it,
so a Mobile turn that called it waited until the request ended. No
profile offers it now. The agentic loop answers any call with a refusal
that tells the model to ask in its reply text, the path Patrol runs
already took, and the chat prompt drops its clarification-tool advice.
The capabilities manifest's Assistant surface stops declaring
interactive questions, so the generated docs and fallback governance
names follow it.

/api/ai/chat and the session list, create, rename, delete, messages and
abort routes Pulse Mobile uses are unchanged, as is /api/ai/status. Old
session files load as before and drop the redo stack and steered flag
on their next write. docs/API.md lists the remaining chat routes, and
the subsystem contracts record the removal.
2026-10-23 14:07:20 +01:00
rcourtman 28172a907b Retire the Assistant chat window; alert Investigate runs Patrol
Pulse Assistant was a chat drawer beside the monitoring UI. Operators who
want to talk to their infrastructure already use Claude Code, Codex, or
another MCP client, and Pulse MCP gives those agents the same governed
tools. Keeping a second, weaker chat in the web app cost a 66 kB chunk,
a launcher on every page, hand-off buttons on alerts, findings, approvals
and drawers, and thousands of lines of OpenCode-parity drawer code, for a
feature the maintainer judged ineffective.

This removes the browser chat and everything that only fed it:

- The drawer, its launcher (desktop and phone), the command-palette
  Assistant commands, the Escape and blocking-dialog shell plumbing, and
  the chat store, client, dev stream fixture and generated SSE types.
- Every "Open in Assistant", "Explain with Assistant", "Discuss" and
  "Ask Assistant" hand-off on alerts, incident timelines, Patrol findings,
  approvals, run history, the attention workbench and resource drawers,
  with their context models and the chat-only helpers they used.
- The Assistant settings page and its session maintenance section. The
  page becomes "External agents" at /settings/pulse-intelligence/agents;
  the old /assistant path, ?tab=assistant and system-ai-assistant redirect
  there with the hash kept.

Alert Investigate now starts a targeted Patrol run (resource, alert ID and
type) and says where the findings land, and it ignores repeat clicks while
the request is in flight. The run route needs an admin with ai:execute, so
security status gains settingsCapabilities.patrolRun, derived from the same
snapshot as the other admin capabilities but following the route for
org-scoped admins, organization-bound tokens and a cookie beside a token,
and Investigate is offered only where it is true. The Patrol
tool transcript block moves to components/patrol. A small aiAvailability
store holds the session assistantEnabled fact that gates Patrol entry
points and Investigate; it now clears and refreshes on organization switch,
refreshes when organization loading settles on another org and after
provider removal, and ignores answers that arrive after a newer one.

The backend chat service stays: Patrol investigations run on it and
Pulse Mobile chat uses it until 31 March 2027, so /api/ai/chat, the
session endpoints and the stream contract are unchanged. A new contract
snapshot pins the steer_applied event that only the deleted TypeScript
projection used to cover.

highlight.js, used only by the chat's code highlighter, leaves the
dependencies, as does the DOMPurify carve-out that kept its fence hints.

Contracts, registry and readiness proofs drop the retired surfaces; the
ai-runtime contract loses about 1,600 lines of drawer rules while keeping
every backend session, stream and provider rule. The production build
ships about 100 kB less gzipped JavaScript.
2026-10-23 00:15:04 +01:00
courtmanr@gmail.com 4aa3d7aa5f Finish moving the last bespoke drawers onto the shared shape
The earlier drawer changes left a few surfaces that still looked or
behaved differently, plus code nothing used any more:

- Proxmox Mail Gateway had two drawers for one gateway; the row now
  opens the shared resource drawer with mail flow as its Mail tab. The
  Ceph cluster drawer gains the canonical header, Overview (alerts,
  Worth checking, capacity history, cards, closed Details) and Manage,
  and its dot follows the row instead of reading grey on missing health.
- The Kubernetes cluster drawer's Deployments tab repeated the Workloads
  table with dead-end rows; it is gone, and Namespaces opens the
  Workloads tab scoped to the cluster and namespace with one action.
  The Docker Swarm drawer tab could not be reached from any page; gone.
- On phones, windowed tables (Kubernetes deployments, pods) and the
  Storage tab's grouped pools stopped at 70-90% of the width: a
  colspan=100 spacer or colspan=99 group row created phantom columns
  that took the width hidden columns left. Those rows now span exactly
  the visible header cells.
- The node and Docker host drawers gain the guest drawer's Open action;
  the Docker host withholds readings while offline or stale, lists
  operator state first in Manage and shows its action history. A
  guest's physical disks open the same disk Overview as the Storage tab,
  with the guest agent's disk temperature alerts.
- One "No active alerts" line, one timestamp row and wrapping alert
  subjects replace per-drawer copies; PBS and PMG alerts match on their
  instance id so drawers find them without a metrics target.
- Removes the old disk detail and its presentation code, the Swarm and
  Kubernetes Deployments drawers and their presentation helpers, and
  drawer state nothing read.
2026-10-22 16:35:11 +01:00
rcourtman 2fc54a5a1f Merge pending maintenance repairs with current main
Preserve selected memory freshness and the VM/LXC interpretation.
Retain both native tool contracts and current API concurrency controls.
Qualify this source separately from release and installed recovery.

Contract-Neutral: Integrate already-governed parents without a new contract change. Incoming verification files already match main. Fresh integration tests and source-bound browser proof cover the combined memory and installer surfaces.
2026-10-18 15:11:28 +01:00
rcourtman 20fa477f4d Schedule the existing VM inventory CSV export (#3039)
VM inventory was available only as an on-demand download. It can now be
scheduled weekly or monthly as CSV, emailed or saved on the Pulse
server. Each attempt exports all current VMs in the organization,
including newly discovered VMs, through the existing exporter.
Historical performance-report limits and windows remain separate.

The schedule uses existing delivery configuration checks, persisted
success/failure/uncertain states, bounded retries and deliberate
recovery controls. Pricing, feature gates, retention entitlements and
existing customer grants are unchanged.

Live checks also reproduced two unattended inventory defects: reporting
retained a stopped monitor after configuration reload, and canonical
snapshot reads relied on dashboard reads to publish polled VM inventory.
Reporting now receives reload replacements through an atomic manager
reference. Canonical snapshot reads reuse the existing publication
boundary, including its freshness fast path, provider/mode fences and
nonblocking warm reads.

Validation:

- 105 focused frontend tests; full type check, lint, production build
and bundle budgets.
- Race checks for reporting, inventory, reload, publication and
organization isolation; clean private runtime build.
- Current runtime browser checks on `/settings/support/reporting` and
`/alerts/notifications` at 1440×1000, 820×844 and 390×844, with actual
pixel review. The first inventory read exports 61 normally polled VMs;
real MIME CSV matches the download; a newly discovered 62nd VM enters
the next export.
- Local SMTP acceptance, 451 retry across a real restart, permanent
rejection, uncertain acknowledgement and deliberate recovery; disk
delivery, edit/reload, disable, details and delete.
- Staged status, registry, contract, completion and exact-content
browser guards pass. Regression proof is registered against the specific
runtime paths it covers.
2026-10-17 14:59:04 +01:00
rcourtman 37454ef478 Schedule the existing VM inventory CSV export
Reuse the canonical inventory exporter and report delivery workflow so
operators can email or save a current organization-wide inventory weekly
or monthly. Keep delivery checks, bounded retries and recovery states
shared, with existing pricing and customer entitlements unchanged.

Refresh the shared inventory for unattended reads and rebind reporting
after monitor reload so schedules use the current infrastructure state.
2026-10-17 14:24:56 +01:00
rcourtman 4b8dfed771 Merge main into fix/tenant-scoped-websocket-events
Keep every completion-history entry.
2026-10-17 13:44:52 +01:00
rcourtman 471c0131d5 Merge main into fix/tenant-scoped-websocket-events
Keep every completion-history entry.
2026-10-17 12:48:16 +01:00
rcourtman 9797d26bd3 Record the contract completion for tenant event delivery
The canonical completion guard checks each commit on its own; the
delivery commit relies on the following commit for its contracts and
proof files, so record that exact pair.
2026-10-17 12:48:08 +01:00
rcourtman ae7667a6f3 Merge main into fix/assistant-read-command-arguments
Keep both completion-history entries.
2026-10-17 12:39:58 +01:00
rcourtman 1cde3b35a9 Record the contract completion for the classifier change
The canonical completion guard checks each commit on its own; the
classifier commit relies on the following commit for its ai-runtime
contract, so record that exact pair.
2026-10-17 12:38:05 +01:00
rcourtman a5bc27f50d Record the contract completion for the admin split
The canonical completion guard checks each commit on its own. The
admin split commit relies on the following commit for its dependent
agent-lifecycle and security-privacy contract updates and the route
inventory proof, so record that exact pair.
2026-10-17 10:26:26 +01:00
rcourtman 43f0a21d1a Keep reconciling preview when stable convergence evidence is gone
The hourly "Reconcile release convergence debt" job has failed every run
since 2026-10-13T03:57Z with a bare "GitHub object was not found". The
v6.5.0 activation marker names convergence run 37395942598 as its owner,
and that run (with the rest of the 30 Sep - 8 Oct release run history) was
deleted from Actions between 03:11 and 03:57Z on 13 Oct. The immutable
marker outlives the run, so the owner lookup now 404s.

Because the stable head's run sorts first and any error aborted the loop,
the failed v6.6.0-rc.2 convergence (38927798751) has never been reconciled.

Reconcile each selected channel independently and still fail the job if any
channel failed, so one channel's broken evidence cannot starve the other.
Name the deleted owner run explicitly instead of a generic 404, and do not
retry it: release-convergence.yml waits for that owner to read "completed",
so a fresh dispatch could only time out.
2026-10-16 23:16:13 +01:00
rcourtman 02ee3a2b1d fix(settings): test edited TLS with saved credentials
Send draft verification and fingerprint settings to the saved-credential
probe so Test connection reflects the edit form before saving. Preserve
saved defaults for callers without overrides and keep probe state temporary.

Keep shared footer actions visible on narrow screens so the edit and test
flow remains usable through pending, error and confirmation states.
2026-10-16 21:17:30 +01:00
rcourtman 84226ad7bc Count successful history reads beyond seven days
Measure delivered extended history before changing free and paid features.
Count only successful responses containing an older metric point and retain
only bounded daily totals. Expose the rolling sum through schema v19 and
Preview with matching privacy disclosure and explicit report coverage.
2026-10-16 19:21:03 +01:00
rcourtman 0e5b335b23 Restore collected backup and storage evidence in investigations (#2973)
Guest investigations could miss collected backup failures, and canonical
storage IDs could not retrieve metric history. Investigations now read
backup attempts through the same org-scoped recovery source as the HTTP
API and storage history through the monitor-owned source used by charts.
Responses preserve error text, timestamps, requested windows, read
failures and synthetic provenance. Dense history sampling also includes
the newest remainder observations, which the previous capped fixed-size
buckets discarded.

Regression coverage checks guest tool projection, persisted backup
attempts, resource and tenant isolation, demo-mode transitions, retained
storage history after restart, measured zero, newest observations in
dense series and API/tool coherence. Focused backend tests and both
private runtime builds passed on the validation worker. Frontend
type-check and build passed.

The separate backup inventory overview still uses legacy identifiers.
That remaining canonicalization work is recorded in the existing L6
architecture follow-up.

Browser verification exercised saved investigation summaries and
expanded tool evidence on `/patrol` at 1440×900 and 390×844, including
keyboard open/close, reopen and reload. This was a read-only view of
synthetic investigation records, not action or release qualification.
2026-10-15 16:47:34 +01:00
rcourtman 223c2d2449 fix(patrol): restore collected investigation evidence
Guest investigations could miss collected backup errors and could not read
storage history through canonical resource IDs. Share recovery point reads
with the HTTP API and monitoring history with charts, preserving tenant and
resource scope, timestamps, provenance, window bounds, and read failures.

Cover manifest projection, persisted recovery tasks, demo source parity,
retained storage history after restart, and API/tool evidence coherence.
2026-10-15 15:48:28 +01:00
rcourtman 90f819b309 Show Alert History as cards when its card is too narrow
Alerts > History chose between its table and its phone cards by the
viewport: the table from 768px. With the Alerts rail open, a 1024px to
roughly 1240px window gives the table a 600px to 800px card, where its
own CSS stacks the three row actions and resource names and messages
break mid-word ("inventory-/api") or end after two lines.

The table section now measures its card with useObservedElementWidth and
shows the cards whenever the card is narrower than 800px, the width from
which the row actions share one line; before the card is measured, the
phone breakpoint decides as before. The cards take that decision as an
`active` signal instead of their own 768px media query, so an open
timeline or resource view still moves into the cards' drawer when they
take over and back to the inline expansion when the table returns. The
decision is a memo so a resize within one layout does not re-run that
move and reopen a drawer the operator closed.
2026-10-15 13:59:11 +01:00
rcourtman 0e3e07a9d4 Merge current main into release highlights
Keep release screenshots alongside the current update API changes.
Retain both screenshot and Pro runtime capabilities in the update test helper.
2026-10-15 11:50:26 +01:00
rcourtman 150042fe98 Improve release highlights and reusable screenshot evidence
Put published highlights and optional screenshot comparisons in the
post-update dialog, with grouped details available on demand.

Reuse inspected images from merged pull requests or capture fresh release
views, then publish versioned PNG sidecars. Serve screenshots through the
authenticated release endpoint to preserve the existing image policy.
2026-10-15 11:42:25 +01:00
pulse-triage[bot] 7ee3a7f5e2 Merge commit '62ac128ffd15772c098a97de8790a6226d1f418c'
Change-source: pulse-maintainer
2026-10-14 22:03:25 +01:00
rcourtman e63da80b65 Colour Alert History frequency bars by severity
The frequency chart drew every period in one blue under a legend of
coloured severity dots that described nothing in the bars, left info
alerts out of that legend, and used a floored log scale on which a
25-alert burst looked barely three times one alert.

Each period now stacks critical, warning and info in the legend's own
colours, counted with the alerts contract's closed severity vocabulary,
and bars scale by the square root of their share of the busiest period so
a burst stands clear while quiet periods keep a readable mix. The legend
counts all three severities, and the tooltip and accessible name carry
each period's breakdown. Light-theme warnings use amber-700 because
yellow on the chart surface was under 2:1, and a selected period is
ringed instead of dimming the rest below 3:1.

The chart's two test files are registered as alerts frontend proofs.
2026-10-14 21:34:03 +01:00
pulse-triage[bot] 246646090a fix(ci): qualify the Actions patch and minor refresh
Own PR2936's stale pin and download-admission failures at b7e774d4. Refresh all current workflow consumers, including the newer pre-token issue-label job, with their exact static expectations and lifecycle/deployment contracts. Preserve Node 24, scoped lockfile caching, credential isolation and artifact identity/retention; reject old, mutable and arbitrary download pins.

Contract-Neutral: Immutable Actions pin refresh and coupled consumer/trust expectations only; workflow inputs, permissions, cache and credential controls, artifact identities and application/runtime contracts are unchanged.
Change-source: pulse-maintainer
2026-10-14 17:38:18 +01:00
pulse-triage[bot] fe3ab0985c Bind Helm recovery policy proof to packet authentication
The containing suite caught its old identity-step label assertion after the admission route changed. Require the new authenticated packet step and verify that authentication precedes OCI recovery; preserve the source-run binding and all downstream qualification checks.

Change-source: pulse-maintainer
2026-10-14 15:48:16 +01:00
pulse-triage[bot] 1a89bc8ff3 Authenticate Helm recovery from immutable release evidence
The stable source Actions record currently returns 404 even though the published release is immutable. Do not require that transient record for post-activation chart recovery: authenticate the exact consumed activation marker and its canonical hosted source provenance with the existing packet verifier, then retain release, source-run and chart bindings. OCI provenance and public package readback remain mandatory. Add executed offline admission/refusal regressions and the corresponding deployment contract.

Change-source: pulse-maintainer
2026-10-14 15:39:52 +01:00
pulse-triage[bot] 1b8adaa2dc Name the failed resource in convergence read errors
Recorded run 38566953125 at 86a244bc stops on an HTTP 404 but reports only api -H Accept because the adapter truncates its argv before the endpoint. Preserve a bounded managed-resource path in API failure diagnostics, without query filters. Keep the same requests, credential selection, error classes, retry policy and fail-closed decisions. Add exact failed-read and no-mutation regressions.

Contract-Neutral: Failure diagnostics only; no admission, identity, credential, retry, mutation or release contract delta.
Change-source: pulse-maintainer
2026-10-14 14:48:59 +01:00
pulse-triage[bot] fd0754d7c3 Keep containing recovery proof faithful to current helpers
Current exact-head CI exposes outdated PBS proof inventory, omitted bounded-download helper extraction, closed transport rejecting the production HTTPS flags, and Darwin's truncated comm column in Linux NAS fixtures. Preserve exact transport and process ownership, restoration and migration safety assertions while binding the controls to the actual producer.

Contract-Neutral: Test and offline CI-fixture alignment only; no installed runtime, trust, credentials, deadlines, source safety or public contract changes.
Change-source: pulse-maintainer
2026-10-14 07:22:52 +01:00
pulse-triage[bot] dd2dbeab8f Integrate reviewed preserved-state v6 migration help
Change-source: pulse-maintainer
2026-10-13 11:03:12 +01:00
pulse-triage[bot] 99f72ffedb Keep v6 migration on preserved-state upgrade paths
Replace unsafe generic update and historical downgrade shortcuts with the existing deployment-owned procedures. Keep configuration export distinct from full-state recovery and preserve data, keys, edition, uncertain-attempt evidence and ordinary monitoring checks.

Change-source: pulse-maintainer
2026-10-13 09:53:09 +01:00
pulse-triage[bot] a0804de6fb Keep PBS and NAS verification fixtures faithful to their source
Expect the complete reviewed PBS proof list. Collect full-width real process rows in the private NAS watchdog fixture, retaining exact ownership, deadlines and failure evidence instead of truncating long Darwin paths.

Contract-Neutral: Test fixtures only; production installers, process ownership checks, retention, registry policy and runtime behaviour are unchanged.
Change-source: pulse-maintainer
2026-10-13 09:27:51 +01:00
pulse-triage[bot] c0208f5b80 Keep Mobile compatibility explicit beside its retirement notice
The containing install-metadata gate requires the existing companion-release disclosure. Retain it alongside, not instead of, the approved retirement notice; do not relax the gate or change the served runtime. Preserve the failed first proof and verify the final notes and actual producer.

Contract-Neutral: Notes-only compatibility disclosure and its assertion; no runtime, protocol, release identity, asset, maturity, latest pointer or cadence change.
Change-source: pulse-maintainer
2026-10-13 01:27:42 +01:00
pulse-triage[bot] 01d3c4c6b8 Keep beta notes honest about recovery and Mobile retirement
Use the stable-based source comparison rather than a contradictory immutable changelog introduction. Preserve the reviewed bounded monitoring outcomes and the explicit guest-safety limitation, and include the approved Mobile retirement notice in the existing beta correction. Regression assertions bind the exact notice and comparison without changing release identity, assets or cadence.

Contract-Neutral: Published-note maintenance and its regression assertions only; no runtime, protocol, release identity, assets, maturity, latest pointer or cadence change.
Change-source: pulse-maintainer
2026-10-13 01:21:20 +01:00
pulse-triage[bot] 0f9a8dab22 Merge batch-start published governance and release-page frontier
Change-source: pulse-maintainer
2026-10-13 00:58:18 +01:00
rcourtman 421a784783 Use explicit governance qualification and evidence (#2891)
Governance now reports explicit completion, residuals, evidence and
ownership availability. It no longer computes lane grades, completion
percentages or weighted candidate priority. Release qualification,
security assertions and lease boundaries stay enforced.

The frontend contract also drops obsolete Discovery surface catalogs and
preserves the live Assistant handoff and execution contracts.

Validation: 93 focused Python tests, repository-control Go tests, and
control-plane, status, registry and contract audits. Full delivery hooks
passed, including 164 helper tests and frontend audits after integration
with current main.
2026-10-13 00:50:11 +01:00
rcourtman 0bd6e8b9d8 Point release pages at GitHub's comparison with a Source comparison section
The first beta's page listed no changes, and the full changelog file is
neither attached to nor linked from any release page, so a reader could
not look up a change the summary did not name. Add a pointer, advisory
and additive.

The renderer appends a "## Source comparison" section after Roll back: a
link to GitHub's comparison of the release tag with the stable rollback
target the workflow already passes (--rollback-target and --candidate-tag).
It is a pointer, not a list. GitHub shows at most 250 commits in a
comparison and this beta had 328 changes, so the section says larger
comparisons may omit commits and is not called a full list.

It never fails a release on its own. The helper renders nothing, and
raises nothing, for a missing or malformed tag, a base that is not a
lower stable release, a trailing newline, non-ASCII digits, or numbers
too large to convert. Bodies without the section, including every
earlier release and any frozen in-flight one, keep validating, because
the validator already permits a trailing section and is unchanged. The
post-update changelog dialog reads only recognised category headings, so
a separate heading after Roll back is ignored by it.

Every consumer of the rendered body was audited (the renderer's
validators, create-release, validate-release-assets,
recover-release-activation, the updater backend, the what's-new model and
the Go and TypeScript tests): no regression. Review of the first draft
found a crash on a 5000-digit tag, a newline that would land inside the
URL, and overclaiming contract text; all fixed and pinned by tests that
fail against the first draft. A tags/ prefix would avoid a branch that
shares a tag's name, but GitHub's web comparison URL returned 404 for it
on existing tags, so bare refs are used and the limit is recorded.

Tests run the real renderer on the v6.5.0 notes: placement after Roll
back, exact spacing, numeric ordering, ten edit and annotation cycles
with CRLF and the extra jq newline, expected-body rejection of a changed
or deleted section, and absence still validating. They fail against the
original renderer. Making the section required, and a generated
row-level inventory that proves completeness, need a declarative contract
record in the preparation snapshot and are deliberately deferred; the
contract explains why.

Contract-Neutral: Adds an advisory link to rendered release pages; no published artifact, tag, signing, install or customer contract changes.
2026-10-13 00:20:18 +01:00
rcourtman 1788288dc6 Integrate qualified main into the governance cleanup
Preserve current Patrol setup and provider connection behavior alongside
the explicit governance completion and evidence contract. Inherited
application states retain their qualified main content.
2026-10-13 00:15:47 +01:00
pulse-triage[bot] fabcda039b Merge published workload identity recovery into reviewed maintenance
Retain every reviewed starting commit and the refreshed exact published workload identity source additively. PR2888 remains unchanged pending its completed qualification defects; this unproposed composition requires exact final-source checks before the later publication batch.

Change-source: pulse-maintainer
2026-10-13 00:10:38 +01:00
rcourtman 668c5135c7 Keep workload identity stable across node moves (#2882)
A Proxmox node move changed the workload row key, reset an open drawer’s
History view and could publish new coordinates before saved guest
metadata migrated. Rows now use the stable unified resource ID,
bookmarks resolve through the registry, and the selected resource owns
its drawer tab and History range across regrouping.

Accepted publication migrates metadata before exposing the new node. A
failed write retains operator fields in memory and the last successful
disk snapshot, with recovery through the existing writer. Native
metadata and History coordinates remain separate from row identity.
Backend metrics targets take precedence over the legacy native fallback.

Route focus owns initial positioning. Viewport initialization measures
the selected row without replacing its reveal window. Local row clicks
retain their scroll position, while later scroll and resize events
follow the viewport. Operator policy, Assistant, all four Patrol modes
and paid entitlements are preserved.

The proof registry owns the focused publication and writer tests. Its
guard verifies acceptance and rejection without duplicating the catalog.
Canonical and browser guards share exact Git inheritance reads, so
updating a branch retains parent qualification for unchanged content.
New resolutions and mode changes still need current proof, and range
checks qualify the complete proposed change.

Validation:

- Regression controls reproduce publication ordering and persistence
failures. Targeted backend and race tests pass.
- Final repair checks pass: 476 tests across 15 frontend files,
type-check, production frontend build and embedded build.
- Current-source browser checks on /proxmox/overview at 1280x800,
900x800 and 390x844 cover VM and LXC, canonical and legacy links, node
regrouping, native and explicit History targets, saved links, reload,
keyboard selection, Collapse, Escape and search reselection.
- Additional desktop and phone checks cover operator policy persistence,
metadata write failure, delayed lookup cancellation and refused
references. The final browser matrix passes 196 checks.
- Merge-qualification regression reproduces inherited additions, renames
and deletions being misclassified. All 216 focused guard tests pass,
including retained mode changes, new resolutions and ordinary commits.

Browser node movement uses controlled resource updates. Publication and
metadata ordering are verified independently with filesystem barriers
and failure injection.

Refs #1669

The script-smoke fixture includes the shared repository I/O dependency.
All 23 prepush fixture tests pass.
2026-10-13 00:08:15 +01:00
pulse-triage[bot] a9bf104d3a Merge published Patrol setup into reviewed maintenance
Preserve the starting reviewed e5c1f39636 and current published Patrol setup/provider guidance additively. Existing PR2888 remains unchanged while its completed qualification defects return to their owner.

Change-source: pulse-maintainer
2026-10-13 00:08:10 +01:00
rcourtman b5086d2e00 Use explicit governance qualification and evidence
Numeric lane grades and weighted candidate rankings duplicate model
judgment without adding a qualification invariant. Keep explicit completion,
residuals, evidence, assertions and ownership availability as the current
state contract. Remove duplicated prose catalogs and stale retired-surface
obligations while retaining their canonical owners.
2026-10-12 23:48:51 +01:00
rcourtman a4d2cdc2b8 Integrate current workload evidence and merge qualification
Keep the current clock and stored-History readout alongside canonical row
selection and resource-owned drawer state.

Use one Git inheritance reader for browser and canonical qualification.
Inherited modes and objects keep their parent proof, while new resolutions
and mode changes remain subject to current contract and proof requirements.
Range checks still qualify the complete proposed change.

Refs #1669
2026-10-12 23:07:52 +01:00