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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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
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
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
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
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
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
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
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.
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.
Preserve current Patrol setup and provider connection behavior alongside
the explicit governance completion and evidence contract. Inherited
application states retain their qualified main content.
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
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.
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
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.
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