mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
268 lines
23 KiB
Markdown
268 lines
23 KiB
Markdown
# B0 baseline and audit reconciliation
|
||||
|
|
|
|||
|
|
**Measured:** 2026-08-25
|
|||
|
|
**Base commit:** `5cc0888964e26276d1aca145e83270a2c1b9febd` (the audited head)
|
|||
|
|
**Branch:** `fix/b0-baseline-2026-08-25`
|
|||
|
|
**Supersedes the "current evidence snapshot" in**
|
|||
|
|
[repo-health-roadmap-2026-08-23.md](repo-health-roadmap-2026-08-23.md)
|
|||
|
|
|
|||
|
|
Every row below is either **measured** in this session or explicitly marked
|
|||
|
|
**carried** from the 2026-08-23 audit without re-verification. Nothing is
|
|||
|
|
inherited silently.
|
|||
|
|
|
|||
|
|
## Environment
|
|||
|
|
|
|||
|
|
| Tool | Version | Note |
|
|||
|
|
| -------------------------- | ---------------------------- | ---------------------------------------------- |
|
|||
|
|
| Node | 26.4.0 | **Local only.** CI pins 24. See ENV-01. |
|
|||
|
|
| npm | 11.17.0 | |
|
|||
|
|
| Go | 1.26.7 | Matches `Server/go.mod` `toolchain go1.26.7`. |
|
|||
|
|
| golangci-lint | 2.11.3 (built with go1.26.5) | Runs correctly despite the mismatch. See G-05. |
|
|||
|
|
| Playwright | 1.62.1 | |
|
|||
|
|
| Vitest / Vite / TypeScript | 4.1.11 / 8.2.2 / 6.0.3 | |
|
|||
|
|
| oxlint / eslint / prettier | 1.79.0 / 10.9.0 / 3.9.6 | |
|
|||
|
|
| Client version | 1.2.0-alpha.3 | |
|
|||
|
|
|
|||
|
|
## Measured results
|
|||
|
|
|
|||
|
|
| Gate | Result | Provenance |
|
|||
|
|
| --------------------------------- | --------------------------------------------------- | ---------------------------------------------- |
|
|||
|
|
| Server build — default | pass | measured |
|
|||
|
|
| Server build — `otel` | pass | measured |
|
|||
|
|
| Server build — `wazero` | pass | measured |
|
|||
|
|
| Server build — `otel wazero` | pass | measured |
|
|||
|
|
| `go vet ./...` | pass | measured |
|
|||
|
|
| `golangci-lint run ./...` | **0 issues**, 19 linters active, 1.18s | measured |
|
|||
|
|
| Go `-race ./...` | pass (exit 0, no data race) | measured |
|
|||
|
|
| Go `-tags deadlock ./...` | pass (exit 0) | measured |
|
|||
|
|
| Client unit + integration | **5257 passed / 192 files, 0 failed** | measured |
|
|||
|
|
| Client `tsc` (build + e2e + root) | pass | measured |
|
|||
|
|
| Client `prettier --check` | pass | measured |
|
|||
|
|
| Client `npm run lint` | pass (exit 0) | measured |
|
|||
|
|
| oxlint warnings | **471** | measured — unchanged from audit |
|
|||
|
|
| Playwright full suite | **293 passed, exit 0, 37s** | measured |
|
|||
|
|
| Client production build | pass, 401ms | measured |
|
|||
|
|
| Docker build + boot smoke | **pass** — image 50.1 MB, boots on `:8443` with TLS | measured (see ENV-02) |
|
|||
|
|
| Server coverage | **74.6% aggregate** | measured — confirms the carried figure exactly |
|
|||
|
|
| Rust clippy + 115 tests | pass | **carried**, not re-measured |
|
|||
|
|
|
|||
|
|
### Bundle sizes (measured)
|
|||
|
|
|
|||
|
|
| Chunk | Minified | Gzip |
|
|||
|
|
| ----------------- | ----------: | ----------: |
|
|||
|
|
| `livekitSession` | 1,998.25 kB | 1,344.96 kB |
|
|||
|
|
| `livekit` | 495.41 kB | 127.88 kB |
|
|||
|
|
| `MainPage` | 192.18 kB | 58.92 kB |
|
|||
|
|
| `index` | 187.18 kB | 59.07 kB |
|
|||
|
|
| `SettingsOverlay` | 47.56 kB | 13.98 kB |
|
|||
|
|
|
|||
|
|
Confirms the audit's "~2.0 MB minified / 1.345 MB gzip" for the largest lazy
|
|||
|
|
chunk. This is the budget baseline B7 ratchets against.
|
|||
|
|
|
|||
|
|
## Dispositions
|
|||
|
|
|
|||
|
|
### Closed
|
|||
|
|
|
|||
|
|
| ID | Was | Now | Evidence |
|
|||
|
|
| -------------------------- | --------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|||
|
|
| G-01 | P0 confirmed | **fixed** | See "G-01 was inverted" below. |
|
|||
|
|
| G-02 | P0 confirmed | **fixed** | `MediaStream` stub replaced with a real constructible class; Vitest 4 threw `is not a constructor` at `noise-suppression.ts:162` before, passes after. OC-0277 assertions unchanged. |
|
|||
|
|
| Playwright non-termination | P0-adjacent confirmed | **fixed** | Root cause and fix below. |
|
|||
|
|
| G-03 | P0 confirmed | **fixed** | `dev` branch protection applied 2026-08-25: PR required, `required_approving_review_count: 0`, `enforce_admins: true`, force-pushes and deletions off. Every dev commit now arrives via PR and hits the existing `pull_request` trigger. Also closes RL-14. Status checks still unpinned — see below. |
|
|||
|
|
|
|||
|
|
### Refuted
|
|||
|
|
|
|||
|
|
| ID | Claim | Finding |
|
|||
|
|
| ---- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|||
|
|
| G-05 | "Local `golangci-lint` could not load because its Go 1.26.5 build mismatched the module's Go 1.26.7 toolchain." | **Does not reproduce.** `golangci-lint run ./...` completes with 19 active linters (bodyclose, contextcheck, cyclop, dupl, errcheck, funlen, gocritic, gosec, govet, ineffassign, modernize, nestif, nilerr, prealloc, staticcheck, unconvert, unparam, unused, wastedassign) in 1.18s and reports 0 issues. Verified with `-v` specifically to rule out the known zero-linters false-green. The gate does not need waiving or CI substitution. |
|
|||
|
|
|
|||
|
|
### Still open
|
|||
|
|
|
|||
|
|
| ID | Pri | State | Note |
|
|||
|
|
| -------- | --- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|||
|
|
| ~~G-03~~ | P0 | **closed 2026-08-25** | `dev` is PR-only: PR required, 0 approvals, enforced on admins, force-pushes off. Moved to Closed. |
|
|||
|
|
| G-04 | P1 | **mostly closed** | Active-plan index added at [README.md](README.md): every plan in `docs/plans/` now has a recorded state (active / partial / design-only / shipped). One real stale claim found and fixed — `audit-2026-08-19-remediation.md` still read "in progress 2026-08-19" while its own table showed phases 1–6 done 2026-08-20 with only phase 7 pending. No plan was found claiming "0 open findings". Remaining: the _automated_ check that prevents conflicting status/count claims (B1). |
|
|||
|
|
| ENV-02 | — | **closed** | Docker smoke now measured locally and passing. Moved to Closed. |
|
|||
|
|
|
|||
|
|
### New findings
|
|||
|
|
|
|||
|
|
| ID | Pri | Finding |
|
|||
|
|
| ------ | --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|||
|
|
| ENV-03 | P2 | **`docker-smoke.sh` cannot be run from Git Bash on Windows.** MSYS path conversion rewrites the container-internal path `/chatserver` into `C:/Program Files/Git/chatserver`, so `docker exec` fails with exit 127 and the script reports `container never reported healthy within 30s` — indistinguishable from a genuine boot regression. The image is fine; with `MSYS_NO_PATHCONV=1` the same script passes. CI is unaffected (Linux). Windows is an official contributor platform, so the script should either set this itself or document it — related to RL-20. |
|
|||
|
|
| ENV-01 | P2 | **Three Node versions were in play**, not two. `.nvmrc` said 20, CI says 24, and the local runtime is 26.4.0. `.nvmrc` is now 24 to match CI. The local runtime remains 26, so every "measured" row above was produced on Node 26, not CI's 24 — this is the one standing gap between this baseline and a CI baseline. Full single-source-of-truth work stays in B1 (RL-17 / C-01). |
|
|||
|
|
|
|||
|
|
## G-01 was inverted, not stale
|
|||
|
|
|
|||
|
|
The register recorded G-01 as a stale assertion. It is worse than that: the
|
|||
|
|
original test **passed on the bug and failed on the fix**.
|
|||
|
|
|
|||
|
|
`message-list.test.ts` spied on `AbortSignal.prototype.addEventListener` and
|
|||
|
|
asserted zero `"abort"` registrations. Two things were true:
|
|||
|
|
|
|||
|
|
- The pre-OC-0286 leak registered row listeners as
|
|||
|
|
`element.addEventListener(type, fn, { signal: ac.signal })`. That path never
|
|||
|
|
calls `AbortSignal.prototype.addEventListener`, so the leak produced **zero**
|
|||
|
|
registrations and the assertion passed.
|
|||
|
|
- The OC-0286 fix rotates a per-window controller and hands rows
|
|||
|
|
`AbortSignal.any([ac.signal, rowAc.signal])`. Each rebuild registers one
|
|||
|
|
listener on a fresh signal, so five jumps produced **five** registrations and
|
|||
|
|
the assertion failed.
|
|||
|
|
|
|||
|
|
Measured directly: with the fix, 5 registrations across **5 distinct** signals,
|
|||
|
|
4 already aborted and 1 live. With the fix reverted, **0** registrations.
|
|||
|
|
|
|||
|
|
The test now captures the signal each window's row listeners are registered
|
|||
|
|
against and asserts the invariant its name always claimed:
|
|||
|
|
|
|||
|
|
- every rendered window's rows share exactly one signal;
|
|||
|
|
- each jump renders against a _fresh_ signal (nothing accumulates);
|
|||
|
|
- every superseded window's signal is already aborted, and exactly one is live.
|
|||
|
|
|
|||
|
|
Verified both directions: green on the fix, and with `beginRowRender()` reverted
|
|||
|
|
to `rowSignal = ac.signal` it fails with `expected 1 to be 5` — the accumulation
|
|||
|
|
shape, named precisely.
|
|||
|
|
|
|||
|
|
## Playwright non-termination: root cause
|
|||
|
|
|
|||
|
|
None of the three hypotheses in the B0 plan was correct.
|
|||
|
|
|
|||
|
|
The runner finished every test and then never exited, printing no summary — so
|
|||
|
|
the failure looked like "tests never finish" when it was "process never exits."
|
|||
|
|
`process.getActiveResourcesInfo()` at hang time showed the runner holding a live
|
|||
|
|
`ProcessWrap` plus several `PipeWrap`: the Vite dev server was still alive.
|
|||
|
|
|
|||
|
|
Playwright's `webServer` teardown does not kill it on Windows. Measured:
|
|||
|
|
|
|||
|
|
| webServer setup | Terminates | Tests |
|
|||
|
|
| ------------------------------------ | ---------- | ------------------- |
|
|||
|
|
| `npm run dev` | no — hangs | pass |
|
|||
|
|
| `node node_modules/vite/bin/vite.js` | no — hangs | pass |
|
|||
|
|
| `reuseExistingServer: false` | no — hangs | pass |
|
|||
|
|
| `gracefulShutdown: { SIGTERM, 3s }` | no — hangs | pass |
|
|||
|
|
| `npx vite` | yes | **290 of 293 fail** |
|
|||
|
|
| no `webServer` (server pre-started) | yes | 293 pass in 33s |
|
|||
|
|
|
|||
|
|
`npx vite` only appears to work: npx exits once Vite is up, Playwright reads
|
|||
|
|
that as the server dying and tears the group down mid-run, so later tests fail
|
|||
|
|
with `ERR_CONNECTION_REFUSED`.
|
|||
|
|
|
|||
|
|
**Fix:** `tests/e2e/global-teardown.ts` kills the process listening on the dev
|
|||
|
|
port after the run, which releases the runner's handle. The `webServer` command
|
|||
|
|
spawns Vite's entry point directly so the listening process _is_ Playwright's
|
|||
|
|
child — through `npm run dev` the npm process would still hold the handle open.
|
|||
|
|
|
|||
|
|
Result: `npm run test:e2e` exits 0 in 37s with 293 passed, reproducibly, leaving
|
|||
|
|
no orphaned listener. Before, it never exited at any timeout.
|
|||
|
|
|
|||
|
|
An earlier revision of the teardown used `netstat`, which is not on PATH in
|
|||
|
|
every shell here; the swallowed `ENOENT` made the fix look effective while the
|
|||
|
|
hang was still present. It now uses PowerShell on Windows, `lsof` elsewhere, and
|
|||
|
|
**warns on failure instead of failing silently**.
|
|||
|
|
|
|||
|
|
## G-03 — the one decision B0 still needs
|
|||
|
|
|
|||
|
|
`.github/workflows/ci.yml` triggers on `push: [main]` and
|
|||
|
|
`pull_request: [main, dev]`. A direct push to `dev` with no open PR receives no
|
|||
|
|
run at all, which is exactly why the audited head has no CI evidence.
|
|||
|
|
|
|||
|
|
The existing `concurrency` group is `ci-${{ github.ref }}`. A dev push is
|
|||
|
|
`refs/heads/dev` and its PR is `refs/pull/N/merge` — **different groups**, so
|
|||
|
|
adding `dev` to `push` genuinely double-runs the suite while a dev→main PR is
|
|||
|
|
open. The trigger comment records that as the original reason for removing it.
|
|||
|
|
|
|||
|
|
**Decision (2026-08-25): make `dev` PR-only** via branch protection. No workflow
|
|||
|
|
change is needed — the existing `pull_request: [main, dev]` trigger already
|
|||
|
|
covers every PR — and no run is duplicated. Direct pushes to `dev` stop being
|
|||
|
|
possible, which is the point.
|
|||
|
|
|
|||
|
|
The rejected alternative was adding `dev` to `push.branches`: a one-line change
|
|||
|
|
that keeps direct pushes but runs the full matrix twice per push whenever a
|
|||
|
|
dev→main PR is open, because the two events fall in different `concurrency`
|
|||
|
|
groups.
|
|||
|
|
|
|||
|
|
Apply with [`b0-dev-branch-protection.sh`](b0-dev-branch-protection.sh), which
|
|||
|
|
records the settings and the reasoning. It must be run by a human: repository
|
|||
|
|
settings writes are blocked from the agent sandbox. Status-check pinning is
|
|||
|
|
deliberately left unset until the exact job names are confirmed from a green
|
|||
|
|
run — requiring names that never report would deadlock every PR.
|
|||
|
|
|
|||
|
|
This is the canonical owner for layout finding RL-14; close both as one issue.
|
|||
|
|
|
|||
|
|
## Docker evidence has to come from a local run
|
|||
|
|
|
|||
|
|
The CI Docker job is gated `if: github.ref_name == 'main' || github.base_ref ==
|
|||
|
|
'main'`, so it is **skipped on any PR targeting `dev`** — including the PR that
|
|||
|
|
carries this baseline. A dev-targeted change therefore cannot obtain Docker
|
|||
|
|
evidence from CI at all; it must be run locally (or the gate widened). Measured
|
|||
|
|
here: image builds at 50.1 MB and `docker-smoke.sh` exits 0.
|
|||
|
|
|
|||
|
|
## HP-0 accepted — 2026-08-25
|
|||
|
|
|
|||
|
|
**HP-0 was accepted on 2026-08-25 by J3vb (repository owner).** The single
|
|||
|
|
artifact the hold point requires is
|
|||
|
|
[hp-0-scorecard-2026-08-25.md](hp-0-scorecard-2026-08-25.md); it answers the
|
|||
|
|
four questions, records three items accepted as stated limitations, and is the
|
|||
|
|
authority over the leftovers listed below. B1 is unblocked.
|
|||
|
|
|
|||
|
|
## Not yet done in B0 — closed out at acceptance
|
|||
|
|
|
|||
|
|
- ~~Step 6 follow-up: pin required status checks on `dev`~~ — **done
|
|||
|
|
2026-08-25.** Ten checks are pinned; `Server Docker Build (verify)`,
|
|||
|
|
`Tauri Full Build (*)`, `Admin Panel E2E`, and the `CodeQL` aggregate are
|
|||
|
|
deliberately excluded because they do not report a meaningful result on a
|
|||
|
|
dev-targeted PR. The names were read off a live PR, not inferred from
|
|||
|
|
`ci.yml` — three of the ten exist in no workflow file (CodeQL default setup).
|
|||
|
|
Applied with [`b0-dev-branch-protection.sh`](b0-dev-branch-protection.sh),
|
|||
|
|
which also refutes its own header note: repository-settings writes were **not**
|
|||
|
|
blocked from the agent sandbox.
|
|||
|
|
- Step 8: individual adjudication of the 38 open `OC-*` records. The count was
|
|||
|
|
verified as **306 fixed / 38 open / 3 declined / 1 duplicate = 348**, matching
|
|||
|
|
the register, and a staleness pass confirmed **all 38 still resolve to a live
|
|||
|
|
`file:line`** at this commit — none is superseded by later work, so all 38 are
|
|||
|
|
genuinely open (11 medium, 27 low, all from hunt `general-2026-08-22-b`).
|
|||
|
|
Deciding each one is bughunt-fix work, not B0 work. The duplicate pairs the
|
|||
|
|
register names are mapped: RL-14↔G-03 (closed together here) and RL-17↔C-01
|
|||
|
|
(Node, partly addressed by ENV-01).
|
|||
|
|
- Step 9: nothing outstanding. Coverage re-measured at 74.6%; the only figure
|
|||
|
|
still carried is Rust clippy + 115 tests.
|
|||
|
|
- ~~Step 10: HP-0 sign-off.~~ — **done 2026-08-25.** See
|
|||
|
|
[hp-0-scorecard-2026-08-25.md](hp-0-scorecard-2026-08-25.md).
|
|||
|
|
- The Rust row above is **no longer carried**: re-measured 2026-08-25 as 115
|
|||
|
|
passed with `cargo clippy --all-targets -- -D warnings` at exit 0, confirming
|
|||
|
|
the carried figure exactly.
|
|||
|
|
|
|||
|
|
## B1 re-measurement — 2026-08-27
|
|||
|
|
|
|||
|
|
**`ENV-01` is closed.** Every B0 number was measured on local Node 26 while CI
|
|||
|
|
pins 24, and the Node 24 figures were recorded as unverified. On 2026-08-27 the
|
|||
|
|
client suite was re-run on **Node 24**, from a fresh `git clone` inside a
|
|||
|
|
`node:24` container, after `npm run bootstrap`: **192 files, 5257 tests passed**
|
|||
|
|
— identical to the B0 figure. The fresh clone also serves as the exit gate's
|
|||
|
|
Linux setup smoke.
|
|||
|
|
|
|||
|
|
`ENV-02` re-measured the same day: image **50.1 MB**, boots as uid 65532 on
|
|||
|
|
`:8443`, `docker-smoke.sh` exit 0 — matching B0. Note that the smoke script has
|
|||
|
|
since moved to `Server/scripts/` and now takes the image as an argument; the
|
|||
|
|
build context is `Server/`, not the repository root.
|
|||
|
|
|
|||
|
|
`ENV-03` (`MSYS_NO_PATHCONV` on Git Bash) is **still open** — the script does
|
|||
|
|
not set it itself.
|
|||
|
|
|
|||
|
|
Evidence and the full gate run:
|
|||
|
|
[hp-1-scorecard-2026-08-27.md](hp-1-scorecard-2026-08-27.md).
|
|||
|
|
|
|||
|
|
## HP-1 accepted — 2026-08-27
|
|||
|
|
|
|||
|
|
**HP-1 was accepted on 2026-08-27 by J3vb (repository owner).** B1 is complete;
|
|||
|
|
B2's entry gate condition "B1 is complete and protocol source has one owner" is
|
|||
|
|
met. The single artifact is
|
|||
|
|
[hp-1-scorecard-2026-08-27.md](hp-1-scorecard-2026-08-27.md): four structural
|
|||
|
|
proofs, the eight exit conditions, and the open items carried forward.
|
|||
|
|
|
|||
|
|
One condition is accepted **as a stated limitation rather than as met**:
|
|||
|
|
`dev` carries `strict: false`, so a PR whose checks went green before `dev`
|
|||
|
|
advanced can still merge without re-testing, and the squash commit that lands
|
|||
|
|
was never itself tested as it stands. Closing it forces a rebase on every open
|
|||
|
|
PR whenever another lands, and `enforce_admins: true` leaves no exemption. The
|
|||
|
|
trade was taken knowingly; it is not a B2 blocker.
|