Repository navigation
UN-4363 [FEAT] Enforce the frontend v1 rules as their own PR checks: seam, purity, bundle, separation and accessibility - #2434
Conversation
…0-T10) - ci-frontend-v1.yaml: v1 checks as their own jobs (Biome, Typecheck, Purity, Unit tests, Build/bundle/separation, Guard fixtures), moved out of the v0 typecheck job so v1 reports apart from v0. - ci-frontend-v1-seam.yaml + scripts/check-v1-seam.mjs: v1 work may change v0 (src/ outside v1, public/) only at scripts/v1-seam-allowlist.json. Change sets that touch no v1 file pass; the v0-change label turns it into a report. - scripts/check-v1-separation.mjs: no tracked plugin folder under src/v1/plugins (enterprise code stays in unstract-cloud). - scripts/check-v1-bundle.mjs: production build, then no v1 chunk or chunk it loads holds a v0 module or antd. - biome.json: a11y rules are errors under src/v1; lint:v1 fails on warnings. - 17 fixture cases proving each new guard fails and passes as specified, including two real Vite builds for the bundle guard. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
…ud findings - chmod +x on the three new shebang scripts (pre-commit check-shebang-scripts-are-executable). - Explicit compare functions for every sort. - Split the bundle guard's check() into reachable() and describe() to bring its cognitive complexity under the limit; output is unchanged. - git from PATH marked NOSONAR with the reason, as in the fixture runner. - String.raw in the glob escaper; no nested template literal. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
…ts own configs Resolves the package.json and v1 README conflicts with #2429. The v1 unit check now runs vitest.v1.config.mts and vitest.v1-plugins.config.mts with coverage, and the guard-fixtures check also runs the v1-harness fixtures (UN-4612). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
…sing under warnings-as-errors Biome's warnings now fail lint:v1 before check-v1 runs, so the radix bracket-access row checks check-v1 directly and pins Biome's own warning, and the require fixture drops a suppression Biome reports as unused. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
…its coverage Brings over UN-4612 from #2440. The v1 · Unit tests check runs vitest.v1.config.mts, the config tests/groups.yaml gives the rig's frontend-v1-unit group, so a run below v1's coverage threshold fails, and it uploads the coverage report. test-fixtures/v1-unit-gate proves the threshold fails passing tests below it, and that the CI job and the rig group name the same config. test:v1 and the Guard fixtures check run those fixtures too. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
[Medium impact] The PR appears safe to merge; no new actionable issues were found.
|
…1 checks on their config files git diff -z keeps a non-ASCII path such as src/pages/Überblick.jsx as written, so it is matched against the seam instead of slipping past both rules quoted. The v1 workflow now also runs when only ci-frontend-v1.yaml or tests/groups.yaml changes, since the unit-gate fixtures read both. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
vishnuszipstack
left a comment
There was a problem hiding this comment.
Review of PR 2434 — UN-4363 frontend v1 CI gates
Mode: INITIAL. Reviewed head 80035853f3435113749242f4f2a6cfc810cc902b, merge base ed53cfded971d51f7d1ff1096d84c10bb01360b0, base freshened (base_fetch: ok), 39 files, 1119 lines (matches GitHub). Rubric: unstract plugin v2.1.80.
Signals: lenses 11 and 13 raised (CI workflows, tests changed). facts.sh also raised its dependency and auth triggers; package.json changes only scripts, and no dependency moved.
Security deep-dive: done
boundary-sweep: 2 sinks traced, clean (guard output prints repo-relative paths and git stderr to the CI log; the coverage artifact holds source paths and counts from a public repo).
Verdict — REQUEST CHANGES
Summary — Critical: 0 · High: 2 · Medium: 6 · Low: 6 · Lenses run: 19/19 (1 not covered, 4 N/A; see checklist).
The seam, purity, Biome and unit gates behave correctly on every input tried. The problems are concentrated in the bundle guard and in what the fixtures actually prove.
Findings are inline below, numbered as in the summary counts.
Unanchored findings
- Every guard is advisory until an admin acts. Required checks on
mainareGreptile Review,SonarCloud Code Analysis,license/cla,pre-commit.ci - prandreport. The PR discloses this as a post-merge step, but it needs a named owner. Moving the v1 steps out oftypecheckis not itself a regression, becausetypecheckis not on that list either. - The PR body's testing notes are out of date: "39 vitest tests and 105 fixture tests" against 284 and 130 observed here, and "This PR's own CI run is the first real run", though the workflows have now run and passed.
Lens checklist
- Spec & intent — See findings #1, #8
- Architectural fit & precedent — See findings #1
- Correctness & edge cases — See findings #1, #4, #8, #10, #11
- Security — Clean
- Data integrity & migrations — N/A — no persisted data or schema
- Concurrency — Clean
- API & contract compatibility — Clean
- Reliability & resilience — Clean
- Performance & cost — Clean
- Observability — Clean
- Operational safety — See findings #14
- LLM/agent-specific — N/A — no model, prompt or agent path
- Testing — See findings #1, #2, #5, #6, #7, #13
- Dependencies & build — Clean
- Code quality — Clean
- Doc & comment accuracy — See findings #3, #9, #12
- Cross-document rule consistency — Not covered — merge-result sweep unavailable: git 2.34 here, the script needs 2.38
- On-prem deployment experience — N/A — no chart, values or on-prem surface touched
- Scaling & workload lifecycle — N/A — no worker or scaling config touched
Assessed by me rather than an agent: lenses 4, 5, 6, 7, 8, 11, 12, 14, 15, 17, 18, 19. The type-design agent was not dispatched because the diff adds no types or schemas.
- Lens 4: the deep-dive's find pass reported no candidates, so its filters had nothing to run on. My own read of the workflows agrees: plain
pull_request, read-only token, no secrets,persist-credentials: false, andgithub.base_refand the label check reach the shell only throughenv. - Lens 7: the changed surface is check names. The PR discloses the branch-protection step, and no workflow depends on the removed steps.
- Lens 8:
changesfails open by design, and a skipped job satisfies a required check. - Lens 15:
biome ci --error-on-warnings src/v1/andbiome cion the changed scripts and fixtures pass here. - Lens 17: base tip equals the merge base, so the branch is not behind and the merge-result question does not arise today; the branch-side sweep found no disagreement beyond the findings above.
Open questions for the author
- Do the v1 workflows run when a stacked PR is retargeted to
main?typesomitsedited, and the branch filter excludes the original base, so such a PR could reachmainwith nov1 ·run until its next push. Stacked PRs are in use on this epic. UNVERIFIED — retarget one and see whether av1 ·check appears. - Is the bundle rule "no v1 source imports v0" or "loading v1 loads no v0 byte"? That decides how finding 1 gets fixed.
Assumptions made
- The linked Confluence spec and P0-T10 plan were not read; lens 1 is judged against the PR body and the code's own comments.
- Probes used private copies with
node_moduleslinked, on the realvite.config.jswhere stated. The workflows themselves were not executed by this review; their green CI run on this head is the evidence for them. - The cloud-mirror statement in finding 9 rests on a local
unstract-cloudclone that may be slightly behind.
Test run for this head: bun run test:v1 passes with 284 vitest tests and 130 fixture tests, exit 0.
Unanchored findings
.github/workflows/ci-frontend-v1-seam.yaml:44(outside the diff hunk): [Low] [Lens 11] — Thev0-changelabel does not exist yet (finding 14) —.github/workflows/ci-frontend-v1-seam.yaml:L44. The seam failure tells authors to apply it,GET /labels/v0-changereturns 404, and the PR's post-merge steps mention only branch protection. Create it as part of rollout. Confidence: High. VERIFIED — API call.
…y CI runs it Addresses the review on #2434. - Bundle guard: walk the module graph from every src/v1 module (static and dynamic imports) instead of judging chunk placement, so a package shared with v0 no longer fails clean v1 code and a statically mounted v1 entry that imports v0 no longer passes. - Seam guard: read the allowlist from the base branch with --base, guard index.html, count top-level v1 files (vitest.v1.config.mts) as v1 work, and drop src/setupTests.js from the allowlist. - Separation guard: ls-files -z, so a non-ASCII name is read as written. - Fixtures: git-case.sh runs the seam and separation guards in a real repository rooted above frontend/ (renames, deletes, non-ASCII paths, a bad ref, an ignored overlay, a committed plugin, a widened allowlist); real-build bundle cases for a shared package, a static mount and a dynamic v0 import; seam glob near-misses; the 11 a11y rules pinned as errors; each v1 CI job's exact commands pinned; coverage cases just above and below 80%. makeTree leaves out a local cloud overlay. - Docs: the production build covers v1 only once v0 imports it (P0-T03); cloud plugins are for the cloud mirror (UN-4614). Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
|
@vishnuszipstack, thanks for the thorough review. Every finding is addressed in bfa93fb, and each inline thread has a reply. Here are the rest:
Generated by Claude Code |
…t runs on macOS BSD sed has no GNU-style `sed -i`. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
…he CodeEditor test mock The v1 lint now fails on warnings. Biome flags loads as unnecessary, but it is read per render from a mutable mock that the tests flip between renders. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
Run the new v1 icon guard (check-v1-icons) as a step of the v1 Purity check, keep it in lint:v1 next to warnings-as-errors, and split the escaped-CSS icon fixture: Biome's noUselessEscapeInString warning now stops lint:v1 first, so check-v1-icons is also asserted directly. Corrects the bundle:v1 README row to describe the module-graph check. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
Rollup reaches a CommonJS module through a virtual "\0<file>?commonjs-..." module. The guard dropped every virtual id, cutting the chain, so v1 could reach v0 or antd through a CommonJS package unnoticed. Virtual modules now stay in the graph, named after the file they wrap (edges merged); ones with no file behind them are "virtual:<id>" and never count as v1, v0 or antd. New fixture bundle-v1-cjs-v0 (v1 -> CommonJS lib -> v0) fails as it should. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HzRGGUgsEDiwJ56zKJ4ASv
Frontend Lint Report (Biome)✅ All checks passed! No linting or formatting issues found. |
|
Unstract test resultsPer-group results
Critical paths
|



Requested by Johny · project thread
What
ci-frontend-v1.yamlwith one job per guard:v1 · Biome,v1 · Typecheck,v1 · Purity,v1 · Unit tests,v1 · Build, bundle and separation,v1 · Guard fixtures.v1 · Unit testsrunsvitest.v1.config.mts, the config of the rig'sfrontend-v1-unitgroup, so a run below v1's coverage threshold fails, and uploads the coverage report.test-fixtures/v1-unit-gate/proves the threshold fails passing tests below it and that CI andtests/groups.yamlname the same config.v1 · Guard fixturesalso runs the harness and unit-gate fixtures (UN-4612, folded in from UN-4612 [DEV] Gate v1 unit tests on the frontend-v1-unit group and its coverage threshold #2440).ci-frontend-v1-seam.yaml:v1 · Seam.typecheckjob inci-frontend-lint.yaml.Why
typecheckcheck.How
scripts/check-v1-seam.mjs+scripts/v1-seam-allowlist.json):src/v1/or v1 tooling (scripts/*v1*,test-fixtures/v1-*).src/outside v1, orpublic/) not in the allowlist. The allowlist covers routes, the root mount andsrc/index.css.v0-changelabel makes the check list the files instead of failing. The seam check is in its own workflow because it re-runs on label changes.check-v1.mjs --codepluscheck-v1-styles.mjs. Adds a fixture showing v1 cannot import the antd shims.biome.jsonsets the 11 a11y rules that arewarnrepo-wide toerrorundersrc/v1.lint:v1and the CI job use--error-on-warnings, so any Biome warning under v1 fails.scripts/check-v1-bundle.mjs):src/v1/module, and fails on any v0 or antd module reached. It judges imports, not chunk placement, so a package shared with v0 is fine and an inlined v1 entry is still checked.scripts/check-v1-separation.mjs): no tracked folder undersrc/v1/plugins/. The other half, "v1 works with no overlay", is the Typecheck, Biome, Purity and Unit tests jobs, which run on a clean OSS checkout. The Build job covers v1 only once v0 imports it (P0-T03).--basethe allowlist is read from the base branch, so a PR cannot widen it and pass in the same change;index.htmlis guarded;nginx.conf/default.confare deliberately not (deployment config serving v0 and v1).boundary.fixtures.mjs.git-case.shruns the seam and separation guards inside a real git repo rooted abovefrontend/, as CI does (renames, deletes, non-ASCII paths, a bad ref, an ignored overlay, a committed plugin, a widened allowlist). Real mini Vite builds cover the bundle guard (a shared package, a lazy v0 import, a static mount, a dynamic v0 import). The 11 a11y errors and each v1 CI job's exact commands are pinned.v1-important-cssnow expects Biome'snoImportantStylesfirst, and runs the styles script directly to keep its own branch covered.Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)
src/v1/README.md.src/v1.typecheckcheck no longer covers v1. After merge, a repo admin needs to add the newv1 · …checks to branch protection (owner: Johny). Thev0-changelabel now exists.Database Migrations
Env Config
Relevant Docs
frontend/src/v1/README.md, section "Scripts".Related Issues or PRs
frontend-v1-e2erequired, after UN-4345 [FEAT] Frontend v1 E2E harness and the frontend-v1-e2e group #2355.Dependencies Versions
Notes on Testing
bun run test:v1: 284 vitest tests and 153 fixture tests pass.--relative/--no-renames/-z,return [], exit 0 on git failure, an emptyls-files, dropping static or dynamic imports from the graph,useButtonTypeaswarn) fails at least one fixture.typecheck:v1,lint:v1,biome ci src/andtsc --noEmitare unchanged and clean.node scripts/check-v1-bundle.mjson the real app: 5410 modules, 0 v1 modules, ok. On a scratch copy, a lazy@v1entry using@v1/lib/cnpasses and a static@v1mount importing a v0 file fails.Screenshots
Checklist
I have read and understood the Contribution Guidelines.
Generated by Claude Code
Generated by Claude Code