The exact no-mutation watchdog failed at published 6.4.5 because the release line has pending repairs but still declares its stable VERSION. Observe that governed source and its preceding stable reference without inventing a new promotion, while keeping candidate resolver gates unchanged and watchdog artifacts out of promotion-readiness records.
Change-source: pulse-maintainer
Replace two stale schema assertions with explicit watchdog omission and ordinary candidate rollback requirements. The actual workflow admission/source-selection shell tests preserve the fail-closed distinction.
Contract-Neutral: Tests and explanatory comments reflect the already recorded watchdog admission contract; no further runtime contract change.
Change-source: pulse-maintainer
Retain the scheduled governed-source selection and no-mutation demo verdict in a separate fixed dispatch mode. Check its control SHA and candidate-free envelope before checkout, preserve ordinary rehearsal rollback and exact event-source guards, and skip candidate builds.
Change-source: pulse-maintainer
The feedback form forced screenshots into shell code fences and conflated a running container image with a non-container release asset. Preserve rendered attachments, ask for the Pulse image only on running containers, and keep failed-install evidence truthful.
Contract-Neutral: Community issue intake only; release and installation contracts unchanged.
Change-source: pulse-maintainer
The bug and v6 pre-release forms previously required reproduction steps even when a retry could cause a host outage, duplicate update, alert storm or data loss. Ask for the original sequence and safe evidence instead, and mirror the guidance in the public triage document.
Contract-Neutral: Community intake wording only; release and installation contracts unchanged.
Change-source: pulse-maintainer
Ask for the attempted release and installer provenance when Pulse never started, without forcing a false running-version attestation or a token-bearing command. Keep public triage guidance aligned and pin both forms in tests.
Contract-Neutral: Issue form provenance and wording change community intake only, not release promotion or artifact dispatch
Change-source: pulse-maintainer
Retain the verified #2321 source and its original receipt while incorporating upstream release and browser range validation.
Change-source: pulse-maintainer
Preserve upstream browser verification for the newer Relay retirement surface; earlier action recovery proof remains in reviewed ancestry. Include current CI sharding and qualification canary without rewriting accepted commits.
Change-source: pulse-maintainer
With the host-interface canary in place, v6.4.5-rc.4 passed the
schema-v7 systemd and rootful Docker lab (run 36594651903), but the
attestation step then failed with Permission denied on receipt.json,
which the privileged lab writes as root into the bind-mounted evidence
directory. Hand that directory to the runner user after a passing lab
and before attestation, without touching its content.
The immutable RC systemd lab failed before installed acceptance because
its --network none container had no non-loopback IPv4 address to prove
the helper's private network cannot reach. Add a veth canary wholly
inside that namespace and assert no default route before the lab runs.
Also check out the repository in the demo resolver before it calls
scripts/write_github_output.py, so verification-only dry runs reach
their demo checks.
Split out of #2323 so the v6.4.5 promotion is not held behind the
unrelated action-review UI work in that PR.
The weights from #2324 came from one local run and left the api shards at
4.5, 8.8, 17.1 and 12.5 minutes on CI. Most of the 17.1 was not test time.
That shard ran `-run . -skip <1231 names>`, and the test binary caches only
its last compiled pattern, so alternating the two recompiled the 62 KB skip
regex for every test and subtest (about 50 ms each under -race locally, 30s
against 1.3s for 300 trivial tests). Two runs put that shard at 887s and
875s against roughly 450s of tests. The skip path now passes -skip alone.
Every api shard now runs go test -json through
.github/scripts/record-internal-api-test-seconds.py. It prints what plain go
test would (package lines and the output of failing or unfinished tests),
exits non-zero on any failure behind pipefail, and writes each top-level
test's seconds to an internal-api-test-seconds-N artifact that is uploaded
even when the shard fails. .github/scripts/refresh-internal-api-test-seconds.py
rebuilds the weights file from those artifacts (gh run download, median
across runs, DEFAULT_WEIGHT set to the mean of the unlisted tests, which the
selector now reads from the file).
Until those artifacts exist, the weights are a local -race -json run with
each region of go test's order scaled to what CI reported for it.
Equal-count quarters averaged 107, 437, 100 and 787s over four runs, and the
weighted cut gave 131s for the first 1187 tests, 350s for the next 23 and
608s for the last 21 over two. The last quarter and the last 21 tests
disagree on how the tail splits, so the tail takes the midpoint of an exact
fit and a pooled factor.
With these weights four shards still predict a slowest shard near 10
minutes, and a 20% slower runner on the tail would take it past the 11
minutes of Frontend and rest-1. Five shards predict about 131, 325, 280-340,
330-355 and 330-365s of tests, or 4.5 to 8.5 minutes a job with about 2.3
minutes of setup, so API_SHARD_COUNT goes to 5. Every test still runs
exactly once in contiguous go test order, and all five slices passed locally
from their new starting points. The required Backend tests (api) verdict
keeps its name.
An empty form field or unrelated edit cannot prove comment-raised topics were dispositioned. Only label newly declared topics, leaving removal to whole-thread triage and respecting a completed manual disposition.
Change-source: pulse-maintainer
Ask for the failing running version and a container image only where one exists. Accept symptom-appropriate screenshots or logs without forcing irrelevant log text, and state the matching triage rule.
Change-source: pulse-maintainer
The four Backend tests (api-N) shards took equal-count quarters of go
test's list, which left them at 4.0, 10.6, 4.0 and 16.8 minutes on the
first PR run, and at 1.9, 8.0, 1.5 and 10.3 minutes of go test time on
the following main push (run 36560070496). Almost all of it sits in a
few tests. One contract mock chart test runs about six minutes on the
runner, and the 28 integration server tests at the end of the list take
about twenty seconds each, so the fourth quarter held nearly half the
package.
Shards are still contiguous runs of go test's own order, since some
tests depend on package state from their neighbours, but the cut points
now come from estimated seconds.
.github/scripts/select-internal-api-shard.sh weighs each test from
.github/scripts/internal-api-test-seconds.txt (the 199 tests at 0.5s or
more, seeded from a local -race -json run scaled to that main run's
shard totals, with a 0.05s default for anything unlisted), binary
searches the smallest per-shard budget that fits the list into four
slices, and fills up to it. The weights only move cut points. Every test
is assigned exactly one shard in a single pass, so a stale file can
unbalance shards but never drop or repeat a test, and no shard is ever
empty.
With today's list the slices hold 1187, 23, 2556 and 21 tests, estimated
at 1.9, 6.9, 6.5 and 6.7 minutes of tests, or about 9.5 minutes per job
with the roughly 2.6 minutes of setup and race compile. The 2556-test
slice would need a 124 KB -run pattern, so a shard passes -skip of the
other shards' tests whenever that is shorter, which runs the same tests
in the same order.
Across the last 25 bot PRs the median open to merge time was about 33
minutes for one PR and about 45 when three opened together. The critical
path was the required Backend tests (api) check, where one go test -race
./internal/api step took about 27 of its 31 minutes. Every other required
check finishes within about 12 minutes.
internal/api now runs as four Backend tests (api-N) shards. Each shard
lists the package's tests with go test -race -list from the commit under
test and runs one contiguous quarter of that list in go test's own order,
so every test, including ones added later, runs in exactly one shard, and
a shard that resolves no tests fails. The split is contiguous rather than
interleaved by name because some internal/api tests depend on package
state left by the tests just before them. A round-robin split by sorted
name failed dozens of tests locally (admin bypass and session store
globals), while the four contiguous slices and the full run all pass. A
Backend tests (api) verdict job keeps the required check name and fails
unless every shard succeeded. Backend tests (rest-0) and (rest-1) keep
their names and package split. Local non-race timings put the heaviest
slice at about 42 percent of the package, so the api check should drop
from about 31 minutes to roughly 14.
Core E2E no longer runs the non-gating probation tier on pull requests.
It could not gate a PR and the promotion rule counts only main runs, so
on a PR it only held each of the eight shard runners about eight minutes
longer, which fed the runner queueing seen with concurrent PRs. Push and
manual runs still execute it.
Go test steps still run for frontend-only changes. Go tests read
frontend sources directly (internal/api contract tests,
internal/unifiedresources walking frontend-modern/src, and the
internal/telemetry repository-wide wording scan), so skipping them by
path would drop real coverage.
Create the non-loopback veth canary only inside the no-network disposable systemd container before running the immutable release lab. Preserve packet authentication and fail closed when the local interface or no-default-route assertion is absent. Bind the workflow, source contract and installtests guard in one reviewed candidate.
Change-source: pulse-maintainer
The scheduled release dry run reached its reusable demo resolver before checkout, so the output helper was absent and the no-mutation demo check failed. Move the credential-free checkout ahead of resolution, guard the ordering in install tests, and record that precondition in the deployment-installability contract.
Change-source: pulse-maintainer
Dispatch the post-publication check from protected main while binding its packet to the immutable RC tag. Accept only canonical Pulse checkout origins before normalising the spelling required by the attester, and document the deployment contract and source guard together.
Change-source: pulse-maintainer
The resolver refused a stable promotion until its candidate had soaked for
72 hours, or 168 for a minor. Few installs run previews: 35 of about 7,900
active installs ran v6.4.5-rc.3 in the week to 2026-09-28, so a longer
soak saw little the first day did not, while 75 percent of installs sat on
a stable build a month old. Richard set a 24 hour soak for every release
on 2026-09-28.
The minimums drop to 24 hours for minor and patch alike, the error text
reads the constants instead of repeating numbers, and the workflow and
trigger prompts, the promotion policy and the deployment contract say the
same. The content-drift check and the hotfix exception are unchanged.
The isolated coverage-v8 5 proposal cannot install beside Vitest 4 because its peer range requires Vitest 5. Ignore only version majors for both packages until a reviewed frontend migration can update and prove the pair together; retain grouped security updates and minor/patch updates.
Change-source: pulse-maintainer
Keep ESLint 10 and lucide-solid 1.x out of automatic version updates while their lockfile and icon-import contracts fail. Preserve minor and patch updates and guard the rule in Dependabot policy tests.
Change-source: pulse-maintainer
Exercise two provider installations with the same tenant ID, unowned-network collision and cleanup isolation. Gate the release-line push before packet freeze and repeat against digest-verified candidate images during container qualification. Update the deployment-installability contract and pin both workflow gates in the release-asset verification suite.
Change-source: pulse-maintainer
action_consumer_manifests.json pins each release-consumed action to an exact SHA plus the upstream action.yml sha256, and release_promotion_policy_test.py requires every workflow step to match. Dependabot's github-actions group bumps those SHAs, so every group proposal fails the manifest contract and cannot be repaired offline. Ignore the eight governed actions for version updates and guard the policy against the manifest so pin refreshes stay explicit reviewed work. This resolves the recurring failing actions-minor-patch proposal (#2139).
Change-source: pulse-maintainer
Dependabot #2100 and #2101 propose TypeScript 5.9.3 -> 7.0.2, but the checked-in @typescript-eslint/eslint-plugin@8.70.0, @typescript-eslint/parser@8.70.0 and typescript-eslint@8.70.0 each declare a peer dependency of "typescript": ">=4.8.4 <6.1.0". The proposals therefore fail ERESOLVE and all frontend E2E shards, with no security advisory behind them.
Add a semver-major ignore for typescript in the npm ecosystem so majors stay explicit work alongside a lint-toolchain upgrade, and update the config guard test to pin both the browser-runtime and TypeScript ignores.
Change-source: pulse-maintainer
A 6.x release creates its draft release object before stage_private_pro_runtime dispatches the private Pro build, which resolves the payload by the exact frozen public commit (docs/release-source-pairs/<sha>.json). When that declaration is absent or names a different pulse_sha, the private build refuses and the run leaves an orphaned draft (v6.4.5-beta.2, v6.4.5-beta.3). Verify the declaration in prepare, before any draft exists, and fail with the exact path to create. This is an unconditional fact check independent of the opt-in harness gate in pulse-dev-infra #443/#444; the release steward still owns choosing the pair. Source issue: pulse-dev-infra #441.
Change-source: pulse-maintainer
Dependabot #2094, #2095 and #2096 bump actions/setup-go 6.4.0 -> 7.0.0, signpath/github-action-submit-signing-request 2 -> 3.0 and actions/github-script 8.0.0 -> 9.0.0. Each proposal is blocked only by the reviewed pin constants, the workflow-trust allowlist, the release-consumer action manifest and the installer governance assertions that hard-code the previous revisions. Carry all three bumps with those artifacts in one commit so the proposals can be closed as superseded.
All three actions keep the node24 runtime and their existing inputs and outputs; no consumer interface, installer behaviour or public contract changes. The deployment-installability and agent-lifecycle workflow references are pin-only.
Contract-Neutral: Reviewed action pin refresh with identical node24 consumer interfaces and unchanged inputs/outputs; no public-contract or installer-behaviour delta.
Change-source: pulse-maintainer
The npm-minor-patch group (Dependabot #2115) has been held since 17 Sep
because it bundles @playwright/test, playwright and playwright-core
1.56.1 -> 1.63.0 with 12 safe frontend updates. The offline
browser-verification runtime is pinned to Playwright 1.56.1, so a lockfile
bump breaks browser-proof parity; holding the whole group blocked the safe
updates instead.
Ignore Playwright version updates on the governed 1.56.1 line, matching the
docker governed-tag policy, so the remaining grouped updates can be reviewed
on their own. Security updates stay covered by the weekly npm-audit scan and
the frontend dependencySecurity proof. Extend the dependabot config guard to
lock the policy in.
Change-source: pulse-maintainer
Replacement PR checks were queued behind obsolete runs even after the
previous revision failed. Cancel prior validation only for pull_request
events, preserving completed verdicts for branch pushes and manual runs.
Contract-Neutral: Only PR concurrency changes. Semantic YAML comparison confirms all jobs and triggers, including frontend dependency security checks, are unchanged. No security verification change is warranted. The scheduling contract is updated.
Use an explicit status guard while requiring successful preparation and qualification. Model the beta skipped-ancestor path and adverse direct prerequisites; retain immutable identity and all release gates.
Change-source: pulse-maintainer
Persistent prerelease runners can retain state from earlier source execution
and influence later admission, build output or qualification. Use the
existing hosted stable-release path for every channel while preserving
exact-source checks, resource planning, watchdogs and release gates.
Reject historical draft reuse before PATCH when its retained target is not the exact checkout SHA, including missing targets and moving refs. Preserve same-source recovery and activation guards.
Depends on PR2056 qualification-first workflow and immutable tag checks. Executable absent-tag fixtures fail before repair and pass on PR head 9e5e18f0 plus this patch; 53 policy, 6 immutability and 42 trust tests pass. Update the deployment contract in the same commit.
Change-source: pulse-maintainer
A draft GitHub release does not hide its public Git tag or registry
images. Publishing those before qualification consumed a beta identity
when the candidate later failed.
Stage drafts without Git refs, join exact-source checks before public
tag, Docker and Helm publication, and preserve exposed tag identities.
Keep final digest verification before release activation.
The completed local study did not explain the adverse hosted root comparison. Add an exact-source root-only collector with matched builds, ten alternating samples and retained layout and host evidence, rather than repeat full qualification or relax its threshold. Eight focused mocked collector tests pass; hosted execution remains after independent review and protected landing.
Change-source: pulse-maintainer
The grouped action upgrade leaves signing, network and publication consumer assertions on superseded pins. Align those contracts and check every consumer against reviewed immutable upstream manifests, retaining exact dispatch and release trust boundaries without claiming hosted execution.
Change-source: pulse-maintainer
Keep a loopback ephemeral issuer alive for source-built managed browser runs and activate each organisation through the authenticated API. Verify installation bindings without billing-state injection or signature bypass, and retain a narrow CI provisioning proof separately from quarantine acceptance.
Change-source: pulse-maintainer
Playwright HTML reports already include screenshots, videos and traces.
Upload only the separate JUnit XML alongside each report to retain
machine-readable results without storing failure attachments twice.
Apply classification label deltas instead of replacing the stale issue-event label set. This keeps Community retest and unrelated labels untouched while retaining metadata cleanup; regressions cover newer additions, removals and API failures.
Change-source: pulse-maintainer
An older reported version does not establish a relevant released fix, and silence after generic advice does not justify closing an unresolved report. Retire both scheduled paths and retain no-write compatibility entry points. Preserve metadata classification while leaving retest state to Community's evidence-backed whole-thread review. Focused regression tests cover both entry points, label ownership and workflow retirement.
Change-source: pulse-maintainer
The default-branch schedule rejected main before any product checks. Resolve the governed branch to one commit, check its VERSION against policy and retain exact event-source checks for manual dispatches. Report workflow and tested source separately and exercise selection against local Git fixtures in governance CI.
Change-source: pulse-maintainer
Incorporate the protected release-snapshot workflow landing while preserving every reviewed maintenance commit and the additive governance correction in local history.
Change-source: pulse-maintainer
# Conflicts:
# docs/release-control/v6/internal/subsystems/deployment-installability.md
A reviewed notification correction and its required contracts and API proof were accepted as separate immutable commits, leaving the protected per-commit governance check unable to pass without rewriting reviewed history. Add a fail-closed exact-pair validator that reconstructs the completion commit in a detached worktree and runs the normal guard over the combined file set; all unregistered commits continue through the unchanged per-commit path.
Change-source: pulse-maintainer
The branch is validated by the snapshot guard, but its transfer between
workflow steps must also use the canonical GitHub command-file encoder.
Keep the source binding unchanged and satisfy the workflow trust audit.
Validation: all 41 workflow trust tests and five snapshot tests pass.
Contract-Neutral: Encode the already-validated release branch with the shared GitHub command-file helper without changing source identity or release authority
Continuous development must not change the source of an admitted release.
Allow the workflow to run at the qualified preparation PR head after its
normal merge, verifying exact source and workflow identity, canonical PR
provenance, and ancestry in the governed release line. Later branch commits
remain outside that release. Document the immutable-candidate contract and
verify source workflow compatibility before qualification.
Validation: snapshot identity and workflow contract tests passed, including
wrong-head, wrong-base, fork, unmerged and unbound dispatch rejection. The
existing release workflow promotion policy test also passed.
The exact release tree retains a failed paired UUID benchmark check, while push CI cannot repeat that comparison. Provide a reviewed-source route to collect the requested four-condition hosted layout evidence instead of repeating local samples or changing product order.
Fix source/tree/toolchain identities, isolate diagnostic controls, alternate ten rounds, and retain partial receipts without publishing binaries. Execution still needs separate operator authority; collection success does not dispose of the failed gate. Nine focused harness tests and existing benchmark contract tests pass.
Change-source: pulse-maintainer