DataTalksClub / DataTalksClub/website

Reconcile the one-hour local full Playwright bound with current suite runtime

Open
#252 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug infra operations P0 testing
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Product outcome

The retained full local Playwright gate reaches a complete, truthful terminal result within a documented supported wall-clock bound with measured reserve. Local and hosted budgets are derived from comparable suite/timing/resource evidence, not from partial progress or an arbitrary timeout increase. A legitimate suite-growth or environment regression becomes attributable before it blocks a release.

This issue is the full-suite capacity/runtime contract. It does not narrow ordinary release coverage (#238), redefine timeout failure evidence (#199/#205), or reopen the harness deadlock fixed by #206.

Normative authority and related work

  • _docs/PROCESS.md: terminal evidence, independent testing, source/environment identity, and no required skip.
  • _docs/ci/change-selective-ci.md: full browser selection, local verification runner, evidence envelopes, and versioned plans.
  • _docs/ci/playwright-timeouts.md: current 3,600-second local component, 60-minute push, 45-minute scheduled, and 120-second diagnostic contracts.
  • _docs/ci/playwright-flake-policy.md: complete counts, no automatic retry, and quarantine separation.
  • #199: bounds local components and records timeout failure; it does not prove capacity.
  • #205: bounds hosted jobs/per-test diagnostics and rejects partial success.
  • #206: fixed an evidenced lifecycle deadlock. A progressing suite that exhausts its outer budget is a distinct capacity problem.
  • #210: accepted/closed authority for the smoke/core/full marker and Make-target interface; current candidates recompute inventory rather than reusing its historical counts.
  • #228 Slice A: accepted authority for promote-range classification, known-owner browser-profile selection, and quality fail-fast.
  • #238: separately owns the ordinary release smoke inventory and five-minute SLO. It must neither absorb this issue nor demote full-suite coverage. It is not a model/interface dependency, but its lower-numbered P0 lane takes normal selection precedence once both issues are unblocked, and overlapping Make/workflow/Playwright files may not be edited concurrently.
  • #279: owns the one canonical offline-provider classifier/context factory and Spotify/YouTube deny/fulfill semantics. #252 may compose timing/lease hooks around that accepted factory but must not duplicate or weaken its network policy.
  • #295/#296: independent product/gate issues whose near-simultaneous engineering starts exposed a lease race. They are evidence for #252, not implementation dependencies or permission to change their scope.

Reproduction anchors

Historical diagnostic anchors, retained without rerun:

  • source base 9a491cd9baeb1e723bd05e8dacb20978fbaf9d33 plus the now-superseded #236 → #232 seven-path candidate collected 251 / selected 248; a continuously exclusive make test-playwright reached the 3,600-second bound at 61%, retained 149 explicit passes and one failure, and emitted no terminal pytest summary;
  • face8e4808d65afbf0374d1ced7a88079950d663 is the current-main-at-grooming diagnostic anchor. Its unrelated red product/quality state is not a healthy capacity sample and is not a permanent engineering base;
  • #295 and #296 performed near-simultaneous preflight censuses that each observed zero relevant processes and no ownership marker. #295 then stated ownership and launched the full tier; #296 subsequently stated ownership because no atomic claim existed, but was stopped immediately during Django database setup and never reached Chromium. No browser overlap or capacity-sample contamination occurred. The event nevertheless proves that a clean process census plus a narrative “claimed first” assertion is not mutual exclusion.

These old coordinates and logs are provenance only. Do not consume the shared browser lane merely to reproduce an obsolete red SHA, revive its product candidate, or treat partial output as a distribution row.

Required engineering anchors are:

  1. the exact accepted recovery release SHA after #261 → #253 → #279 → #223 → #270 → #232 → #236 is on remote main, its required CI/publish/deploy gates are green, and the sealed live identity is healthy;
  2. the engineer's exact clean base immediately before #252 changes;
  3. the frozen #252 candidate.

When two required identities are byte-identical for the capacity input closure, one evidenced census may satisfy both and must be recorded as such rather than duplicated. Each anchor records source SHA, dirty-state/diff digest, verification plan/graph/policy/render/source-manifest digests, browser-capacity-input digest, suite/node-manifest digest, environment fingerprint, timing-schema version, and process/resource evidence digest. No result from one fingerprint is relabelled as another.

Scope

1. Add a reproducible exclusive census

Provide one uv-backed repository command for a full Playwright capacity census. It must:

  • select exactly the blocking make test-playwright marker expression and first perform collection-only inventory;
  • record collected/selected/deselected counts, every selected parameterized node ID in deterministic order, marker classification, and a node-manifest SHA-256;
  • perform the redacted process/marker preflight, then acquire one atomic, non-split project-wide lease in a stable host-visible namespace shared by every worktree of this repository. Check-then-create, “zero processes”, marker absence, a narrative claim, and sleep/poll arbitration are not acquisition;
  • bind the atomic lock to a schema-versioned safe owner identity containing an opaque claim ID, repository identity, source/diff or plan identity, requested target/profile, owning PID plus process-start identity, and acquisition time. The full identity is written/validated while the lock is held; reports redact usernames, absolute external paths, arbitrary arguments, and secrets;
  • permit exactly one winner. A simultaneous conforming loser receives the winner's bounded redacted identity and exits or waits only within the documented bound before Django database setup, live-server creation, Playwright driver startup, or Chromium launch. It never announces ownership, mutates the winner's marker, signals a process, or enters the measured interval;
  • immediately after winning, repeat the redacted process/marker census while still holding the lease to close the preflight-to-claim race. A non-conforming/foreign owner observed then invalidates the sample and causes the winner to release safely without launching browser work;
  • hold the same claim continuously across collection, database/live-server/browser setup, the full selected run, teardown of every owned child, flake/terminal evidence finalization, and capacity-report finalization. Normal exit, assertion failure, setup failure, timeout, interrupt, and signal paths release exactly once only after owned children are reaped;
  • make crash recovery lock-based rather than PID- or marker-based: an operating-system-released lock may be reacquired atomically and stale metadata replaced only by the new lock holder. A live lock is never stolen; a process-ID match alone is never proof of ownership; cleanup uses compare-and-release semantics so an old owner cannot remove a successor's claim;
  • capture the preflight, claim, post-claim census, continuous activity record, release result, and any bounded conflict/stale-metadata reason. Foreign activity invalidates capacity statistics and is reported, never deleted or signalled;
  • bind monotonic start/end/duration, host CPU count/class, available memory/disk, load/CPU pressure, process-tree peak CPU/RSS, browser/server/worker counts, and bounded I/O/fixture lifecycle signals without usernames, arbitrary command arguments, paths outside the project identity, secrets, or production data;
  • emit machine-readable per-node setup/call/teardown durations and aggregate fixture/session/startup/teardown time, plus a terminal summary/flake-policy record when the run completes;
  • retain a schema-validated JSON report and ordinary pytest output below project-local .tmp/ for local runs and as bounded Actions artifacts for hosted runs.

The census is diagnostic evidence. It must not change test ordering, assertions, timeouts, viewport, worker count, retry, or marker selection while measuring a comparison cohort. Any deliberate execution-strategy experiment is a separate named cohort and cannot be mixed into baseline statistics.

2. Establish comparable local and hosted distributions

A valid comparison cohort has the same browser-capacity-input digest, suite node-manifest digest, browser/Python/uv/lock/controller/timing-schema versions, marker expression, worker strategy, and test configuration. The browser-capacity-input digest covers every application/render/content/harness/configuration input that can alter selected browser behavior or timing. The source SHA is always recorded, but different SHAs may share a cohort only when their changed paths are deterministically proven outside that closure. Any closure, manifest, policy, controller, or configuration change starts a new cohort. Environment fingerprint differences (hosted image, CPU/memory class, filesystem) are explicit dimensions rather than silently normalized away.

For the frozen candidate contract collect separate distributions containing:

  • at least 3 terminal-green exclusive local censuses;
  • at least 3 terminal-green natural push full-profile censuses carrying the same capacity-input/schema/node-manifest contract;
  • at least 3 terminal-green natural scheduled full-suite censuses carrying that same contract.

Push and scheduled observations are never pooled: they have distinct workflow/controller environments and supported bounds. Engineering/testing must not dispatch, rerun, or create a no-op commit to manufacture samples. If either hosted cohort lacks three comparable retained natural samples, the focused commit uses Refs #252, the issue remains open, the human label is added only after every automated engineer/tester/PM gate has passed, and on-call owns completion-driven collection of the next natural samples.

Report local, push, and scheduled minimum, median, nearest-rank p95, maximum, selected-case throughput, setup, test-body, fixture/teardown, and resource distributions. The nearest-rank p95 is the sorted observation at ceil(0.95 × n); no interpolation or exclusion of a slow valid green run.

A sample is invalid for capacity statistics on foreign contention, missing/changed fingerprint, partial/timeout/cancelled output, nonterminal summary, incomplete flake record, resource-sampling gap, clock reversal, malformed/oversized artifact, or any retry/quarantine. Invalid samples remain visible with a safe reason.

3. Attribute the runtime and local/hosted difference

The report must rank:

  • per-node and per-phase duration contributors;
  • session/module/function fixture setup and teardown contributors;
  • Django live-server/database/browser/context/page lifecycle time;
  • CPU saturation/pressure, memory pressure, disk/I/O wait, browser-process growth, and idle/wait time;
  • local versus hosted deltas for the same nodes/phases.

Compare local separately with push and scheduled cohorts. For each hosted cohort, let delta_seconds = local_median - hosted_median. Attribution is required when delta_seconds > max(0.25 × hosted_median, 600). Named node/phase/resource contributions must account for at least 0.80 × delta_seconds, without double counting, or a focused fix must remove the unexplained portion. “Local machine slower” or a timeout increase is not attribution.

Fix only evidenced harness/fixture/resource inefficiencies needed for the supported full suite. Preserve isolation, database lifecycle, accessibility/visual behavior, deterministic screenshots, and existing safe remote/live exclusions. Parallel execution may be adopted only if tests prove database/server/browser isolation, deterministic node results/artifacts, bounded worker count from available resources, clean teardown, and no higher flake/resource-failure rate; ambient/manual -n runs are not acceptance evidence.

4. Derive supported bounds and headroom

For each supported environment (local verification runner, push Actions full profile, scheduled Actions full profile), derive the bound from that environment's own comparable terminal-green cohort:

raw_required_seconds = max(
    nearest_rank_p95_seconds × 1.25,
    observed_maximum_seconds + 600,
    observed_maximum_seconds / 0.80,
)
supported_bound_seconds = ceil(raw_required_seconds / 300) × 300

The third term is normative: it makes the stated “every valid green observation uses at most 80% of the supported bound” rule true rather than leaving it as an extra, potentially contradictory condition. The p95 reserve, ten-minute maximum-run reserve, and maximum-run 20% headroom are all mandatory; the largest controls. Exact integer/decimal and five-minute-rounding boundary behavior is schema-tested.

  • If the current 3,600/3,600/2,700-second local/push/scheduled bounds satisfy their own distributions under the complete formula, keep them.
  • If an evidence-backed optimized suite still requires another value, update the relevant constant/Make target, workflow job timeout, documentation, validation ceiling, and contract tests together. Local, push, and scheduled values may differ only because their separately reported distributions support the difference.
  • A diagnostic override remains non-acceptance evidence and cannot alter the default supported path.
  • Any derived bound change invalidates earlier plan/evidence whose policy/controller fingerprint included the old bound.
5. Coherent implementation and terminal evidence

The smallest accepted implementation may change the census/timing support, Playwright lease/runner/Make targets, workflow artifact capture/job budgets, CI schemas/validators, docs, and focused tests. It must keep all layers coherent:

  • the local component bound still terminates the process group and records exit 124/timed_out failure under #199;
  • hosted job timeouts still produce non-success terminal evidence under #205;
  • make test-playwright remains the exact blocking full suite and scheduled backstop;
  • #238's smoke inventory, 600-second smoke bound, and five-minute ordinary-release SLO are unchanged;
  • evidence schemas reject partial, mixed-cohort, foreign-contention, missing-resource, nonterminal, missing/mismatched lease identity, ownership-gap, unreleased-claim, or dual-winner capacity claims.

Dependencies and readiness

Groomed but blocked; do not dispatch engineering or a browser census yet.

The accepted #210 tier interface and #228 Slice A selection interface remain closed foundations, not dependencies to reopen. The actual start gate is one remote-main recovery release completed in order #261 → #253 → #279 → #223 → #270 → #232 → #236, including #253's external-source prerequisite, separate tester/PM gates, focused commits, exact-SHA green CI/publish/deploy, and healthy sealed live identity. All seven issues are currently open; #253 is again needs grooming. A local-only branch, stale worktree, focused test, partial full run, or red/undeployed SHA does not satisfy this gate.

#279 must land before #252 because it owns the shared context/network boundary that capacity instrumentation will measure. #252 may add a repository-wide lease, timing hooks, and resource observation around the accepted central context factory; it must preserve the single helper/classifier owner, exact provider response constants, direct/no-JavaScript adoption census, fail-closed external denial, and redaction contracts.

#238 is an independent sibling, not a valid model/interface dependency. Once the common release baseline is green, normal P0 issue selection chooses lower-numbered unblocked #238 first unless the product owner directs otherwise. #252 and #238 must not run concurrently when their frozen path sets overlap; the later lane rebases and regenerates its plan. #252 never changes #238's smoke inventory or five-minute SLO.

Immediately before starting any local census, the engineer records a redacted host activity preflight. Any conforming website Playwright owner must hold the new repository lease; any pre-existing non-conforming or foreign pytest/Playwright/browser activity makes the census ineligible until it ends naturally. Never signal, steal, or kill another owner. At this audit, multiple foreign Playwright processes are active on the shared host, so no capacity sample is dispatchable.

The human label is not appropriate while implementation and automated independent verification are incomplete. Add it only if every automated engineer/tester/PM gate passes and the sole remaining work is collection of the natural hosted cohorts. Natural hosted samples are owned by on-call and do not authorize manual workflow dispatch.

Acceptance criteria

  • One uv-backed census command and schema produce deterministic collection/node manifests, source/plan/environment identity, terminal output, per-node/per-phase/fixture timings, bounded resource/process evidence, and safe invalid-sample reasons.
  • Every repository Playwright Make target (test-playwright-smoke, test-playwright-core, test-playwright, test-playwright-quarantined, test-accessibility, and test-browser, including runner/verification entry points and nested target composition) participates in one atomic lease namespace shared across repository worktrees. Exactly one contender can bind a schema-valid owner identity; a loser cannot claim ownership or cross the Django/live-server/driver/Chromium launch boundary; foreign activity invalidates capacity evidence; no owner process is killed or mutated.
  • Historical 9a491cd/face8e4 diagnostics remain provenance-only, while the exact accepted recovery release, clean engineering base, and frozen candidate characterizations are recorded without reviving an old product candidate or treating unrelated failures as success.
  • At least three terminal-green exclusive local samples, three comparable natural push full-profile samples, and three comparable natural scheduled full-suite samples form three separate distributions; invalid/red/timeout/contention samples remain diagnostic only.
  • Local/hosted min/median/nearest-rank-p95/max, throughput, setup/body/teardown, fixture, process, and resource distributions are deterministic, schema-validated, and aggregate-safe.
  • Every material local/hosted delta meets the 25%/600-second trigger rule and has at least 80% evidenced attribution or is removed by a focused fix.
  • Each supported bound is derived by the complete three-term formula, all green observations use at most 80% of it, and runner/workflow/docs/schema/tests agree exactly. No ad hoc override is acceptance evidence.
  • Full collection and blocking coverage are unchanged: no removed/demoted/xfail/quarantine/retry/weak assertion and no unsafe remote/live test enters the suite.
  • Focused census/schema/lease/resource/timing/bound/workflow/evidence tests cover malformed, mixed-fingerprint, partial, timeout, contention, simultaneous atomic acquisition, winner/loser identity, preflight-to-claim and claim-to-launch races, nested invocation, setup failure, normal/error/interrupt/timeout release, crash-stale metadata, PID reuse, compare-and-release protection, sampling gap, resource limit, terminal green/red, and exact formula boundaries.
  • make test-ci, lint, format-check, typecheck, security/workflow contracts, migration drift, and the versioned graph-selected verification plan pass; all dispositions are explicit and screenshots are not_applicable only if the computed graph confirms no render impact.
  • Engineer and independent tester each obtain a terminal full Playwright summary on the exact frozen candidate within the derived local bound, with complete flake record, zero failed/rerun/quarantined cases, and valid capacity evidence. A timeout or partial summary is failure.
  • [ON-CALL/HUMAN if needed] Three natural exact-contract push green samples and three natural exact-contract scheduled green samples separately satisfy their derived bounds; on-call records terminal Actions evidence without manual rerun/dispatch. Until both cohorts pass, use Refs #252 and keep the issue open.

Required scenarios

  1. Collect twice on unchanged input: ordered parameterized node list and digest match; marker or parameterization change changes the digest and cohort.
  2. Deterministic barrier race: two distinct-worktree contenders complete the same zero-process/no-marker preflight and attempt acquisition simultaneously. Exactly one atomic claim succeeds and may cross a launch sentinel; the loser records a bounded redacted conflict and performs zero Django database, live-server, Playwright-driver, or Chromium setup. Repeat with a synthetic non-conforming owner inserted between preflight and claim/post-claim census; the sample is invalidated without signalling it. Exercise nested Make composition, setup failure, interrupt/timeout, crash-released lock with stale metadata, PID reuse, and a delayed old-owner cleanup; the live/new claim survives and every acquired lease is released exactly once.
  3. Synthetic timing/resource report: odd/even distributions, nearest-rank p95, exact delta > max(25% × hosted median, 600) trigger, 80% attribution boundary without double counting, all three bound terms, five-minute rounding, exact 80% headroom, and malformed/non-finite/negative/oversized values.
  4. Fixture/resource attribution: known slow setup/call/teardown and controlled CPU/memory/I/O/browser-process signals appear in the correct bounded fields without raw commands/usernames/secrets.
  5. Historical and current anchors: preserve each source/product verdict and safe timing evidence; never rerun an obsolete red SHA merely for census or relabel a red/timeout as healthy capacity.
  6. Three local, three natural push, and three natural scheduled runs: comparable capacity-input/node manifests produce separate distributions; a change outside the proved capacity closure may retain the cohort, while foreign contention, retry, partial output, or closure/fingerprint drift is excluded with a safe reason and retained diagnostically.
  7. Bound change: local/hosted runner, workflow, docs, schema, and tests either retain justified current values or move together; old-bound evidence is rejected.
  8. Full gate: complete summary and flake record with all selected tests accounted for; timeout, SIGTERM, missing tail, earlier summary followed by interruption, retry, or quarantine cannot pass.

Strict non-goals

  • No partial-pass interpretation, progress extrapolation, ad hoc timeout override, unexplained bound increase, or acceptance from a standalone rerun.
  • No retry, quarantine, xfail, test deletion, marker demotion, assertion weakening, reordered omission, unsafe-marker inclusion, or smoke-tier substitution.
  • No product/template/CSS/JavaScript/heading change, #232/#236 fix, revival/acceptance of the invalid 9a491cd candidate, or folding into #238.
  • No arbitrary worker-count increase, ambient PYTEST_ADDOPTS, unproven xdist adoption, machine tuning outside checked repository contracts, process killing, or interference with other agents/users.
  • No check-then-touch marker, PID-only ownership, narrative/manual claim, sleep-based race avoidance, deletion of a live/stale marker without holding the atomic lock, lease stealing, or release before all owned setup/run/teardown/evidence work is complete.
  • No workflow dispatch/rerun/no-op commit merely to obtain timing evidence; natural hosted samples are observed only by on-call.
  • No production/AWS/provider/data mutation and no secrets, usernames, full foreign commands, absolute external paths, or production data in reports.

Lifecycle handoff

After the exact start gate is satisfied and the shared host is free of foreign browser activity, the engineer works in a fresh isolated worktree, records the accepted-base/current/candidate cohorts, implements the smallest evidenced fix and coherent bound contract, runs the required terminal local gates, posts an engineer report, and freezes uncommitted. Independent tester recomputes the plan/census, validates distributions/formula and a fresh terminal full run, then PM accepts. If either three-sample hosted cohort is still pending, the focused commit uses Refs #252; orchestrator merges/pushes only after normal gates, the issue gains human only at that point, and on-call alone observes natural push and scheduled samples until final PM/HUMAN closure.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with _docs/PROCESS.md, _docs/ci/change-selective-ci.md, and _docs/ci/playwright-timeouts.md, then inspect the existing make test-playwright entry point and related workflow configuration. Establish the collection, lease, reporting, and comparison boundaries before changing code. Done means exclusive terminal-green local and hosted evidence, schema-validated reports, and attributable runtime distributions under the stated contract.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, github-actions, playwright, python
Domain
ci-cd, devops, performance, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.