Skip to content

Upgrade kolibri-format to 3.0.1 - #6358

Open
LianaHarris360 wants to merge 3 commits into
learningequality:unstablefrom
LianaHarris360:upgrade-kolibri-format
Open

LianaHarris360 wants to merge 3 commits into
learningequality:unstablefrom
LianaHarris360:upgrade-kolibri-format

Conversation

@LianaHarris360

Copy link
Copy Markdown
Member

Summary

Upgrades kolibri-format from 1.0.1 to 3.0.1 and replaces .eslintrc.js with eslint.config.mjs. Version 3.0.1 runs ESLint 9, which reads flat config only. Studio loaded kolibri-format/.eslintrc, which the package stopped shipping in 2.4.0.

The new config inherits kolibri-format's and re-applies what .eslintrc.js carried. Rules that 3.0.1 adds and that autofix cannot clear stay off.

  • The config strips jsdoc and vuejs-accessibility rules by name prefix. A new rule in either plugin then cannot break the build before triage.
  • kolibri-i18n moves to 1.0.1. Version 1.0.0 pins kolibri-format 1.0.1, which reads the deleted .eslintrc. Without the bump, pnpm transfercontext and the i18n-download workflow fail.
  • The config turns n/prefer-node-protocol off for bundled frontend source, because webpack cannot resolve the node: scheme for the browser. The rule stays on for specs, which run under Node.
  • engines.node becomes >=20.19.0 <21. kolibri-format 3.0.1 sets the lower bound. node-sass 9 sets the upper bound.

References

Closes #6328

Reviewer guidance

Run pnpm install with pnpm, not npm. The install links kolibri-css-variables to the Kolibri Design System.

I ran these from the committed tree:

  • pnpm run lint-frontend: 961 files, zero problems.
  • pre-commit run --all-files: passes, and a second run changes no file.
  • pnpm test: 280 suites, 4386 tests, zero failures.
  • pnpm run build: succeeds, with the pre-existing bundle-size warnings only.

To check the design-system link, turn kolibri/vue-no-theme-accessor-in-inline-styles on for one run. It must name real variables such as var(--tokens-fineLine), not report This rule cannot check theme names.

To check that the formatting commit is pure, revert the frontend to unstable, run pnpm run lint-frontend:format until it stops writing, and compare the result against the commit.

Notes:

  • The formatter needs two passes to settle, because import-x/no-useless-path-segments writes double quotes and kolibri-format runs Prettier before ESLint. This tree sits at the fixed point, so CI sees one clean pass.
  • kolibri-build has two copies in the pnpm store. Aligning them breaks every Jest suite, because 1.1.4 drops babel.config, which Studio's babel.config.js requires. The copies are development only.
  • copyToken.spec.js loses one expect call. It had no matcher, so it asserted nothing, and the component has no copyStatus.

AI usage

I used Claude Code to carry out the issue. I reviewed its output and rejected parts of it. A second Claude pass over the whole diff found the kolibri-i18n breakage, which I reproduced before fixing. I verified the result with pnpm run lint-frontend, pre-commit run --all-files twice, pnpm test, and pnpm run build, and I checked that the theming rules read real theme names and that the formatting commit is reproducible from the formatter alone.

@LianaHarris360
LianaHarris360 requested review from a team, leq-bot and rtibblesbot October 29, 2026 17:10
@rtibblesbot

rtibblesbot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

🟡 Waiting for changes

Outcome: reviewed 33996a5

Last updated: 2026-11-03 03:05 UTC

@rtibblesbot rtibblesbot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6358: the config migration is complete. Every .eslintrc.js setting carries over. The lockfile resolves only eslint 9.39.5. The code changes are behaviour-neutral.

CI pending. Manual QA covered sign-up, password reset, account settings, the storage request, channel defaults, the edit modal tabs, Community Library countries (en/ar), admin users, thumbnail generation and offline sync. No regressions. Every axe violation found is in unchanged Vuetify markup. Thumbnail upload and save went untested because the QA stack's storage was unreachable.

  • suggestion: 10 renamed import-x/* disables are now unused, plus a stale comment (inline).
  • suggestion: deferred-rule comments cite #6328, which this PR closes (inline).
  • suggestion: with the root eslint dependency removed, editor integration may break (inline).
  • nitpick: ContentDefaults.vue import path (inline).

Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.

  • User-visible files changed: contentcuration/contentcuration/frontend/accounts/pages/Create.vue, contentcuration/contentcuration/frontend/accounts/router.js, contentcuration/contentcuration/frontend/administration/pages/Users/UserPrivilegeModal.vue, contentcuration/contentcuration/frontend/channelEdit/components/edit/EditView.vue, contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue….
  • Decide whether dropping the root eslint devDependency and raising the node engine to >=20.19.0 <21 are acceptable for contributors' tooling.
  • Confirm the rules deferred in eslint.config.mjs are tracked by an open follow-up issue before #6328 closes.
QA captures (50)

Sign up for a new account — submit with required fields empty to trigger onValidationFailed (all errors shown, scroll to top), pick a country from the CountryField list (full English country names, search works), then submit valid data and reach the activation-sent page

Step Screenshot
Activation sent page Activation sent page
Activation sent Activation sent
Country chips selected Country chips selected
Country list open Country list open
Country search united Country search united
Empty submit errors Empty submit errors
Signup form initial Signup form initial

Switch the UI language to Spanish, French, Arabic and Portuguese and open the sign-up or storage-request country field — country names render in that language, not as codes or blanks

Step Screenshot
Country list ar Country list ar
Country list es Country list es
Country search ar Country search ar
Country search es es Country search es es
Country search fr fr Country search fr fr
Country search fr Country search fr
Country search pt br Country search pt br
Country selected ar Country selected ar

Request a password reset from the sign-in page and open the reset-password route — ForgotPassword, instructions-sent and ResetPassword pages load without a missing-chunk or blank-route error

Step Screenshot
Forgot password Forgot password
Instructions sent Instructions sent
Reset expired Reset expired
Reset password failed Reset password failed
Reset password Reset password

In Settings > Account, change the full name and then the password — each formMixin onSubmit fires, shows its success snackbar, and the new name persists after reload

Step Screenshot
Change password validation Change password validation
Full name persisted after reload Full name persisted after reload
Full name saved snackbar Full name saved snackbar
Password updated snackbar Password updated snackbar
4-change-password.webm
4-full-name-edit.webm

In Settings > Storage, submit the request-more-space form empty to see the error banner and scroll, then fill it including country selection and submit — the POST payload carries the countries and the success state shows

Step Screenshot
Empty submit error banner Empty submit error banner
Filled countries Filled countries
Submitted success Submitted success
5-request-form-flow.webm

Open a channel's edit-details modal and change the content defaults (license, copyright holder, auto-derive checkboxes), save, reopen — ContentDefaults renders its translated labels and the values persist

Step Screenshot
Content defaults ar license menu Content defaults ar license menu
Content defaults edited Content defaults edited
Content defaults initial Content defaults initial
Content defaults reopened Content defaults reopened
License menu open License menu open

In a channel editor, open an exercise and a document in the edit modal and switch between Details, Questions and Related tabs, including tab-bar scroll arrows in a narrow window — AssessmentTab and RelatedResourcesTab load and the Tabs prev/next arrows work

Step Screenshot
Document related tab Document related tab
Exercise details tab Exercise details tab
Exercise questions tab Exercise questions tab
Exercise related tab Exercise related tab
Narrow tabs after next Narrow tabs after next
Narrow tabs next arrow Narrow tabs next arrow
Rtl narrow tabs scrolled Rtl narrow tabs scrolled
7-tab-arrows.webm

Submit a channel to the Community Library choosing countries, then view it on the channel card, the channel details panel and the community-library list country filter — country names display and filtering by country returns the channel

Step Screenshot
Admin review panel Admin review panel
Ar details countries Ar details countries
Ar filter kenya Ar filter kenya
Community library card Community library card
Countries search Countries search
Country filter options Country filter options
Details panel countries Details panel countries

Written by rtibblesbot, an LLM-based coding agent.

Comment thread eslint.config.mjs Resolved
Comment thread package.json Resolved

@rtibblesbot rtibblesbot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6358: all 4 prior findings are resolved. No new findings. CI is still pending.

Prior-finding status

RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/comparisonKey.js — unused renamed disable directives, stale comment
RESOLVED — eslint.config.mjs — deferred-rule comments cite #6328, which this PR closes
RESOLVED — package.json:133 — dropping root eslint devDependency breaks editors / pnpm exec eslint
RESOLVED — contentcuration/contentcuration/frontend/shared/views/form/ContentDefaults.vue — relative '../../mixins' import

Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.

  • User-visible files changed: contentcuration/contentcuration/frontend/accounts/pages/Create.vue, contentcuration/contentcuration/frontend/accounts/router.js, contentcuration/contentcuration/frontend/administration/pages/Users/UserPrivilegeModal.vue, contentcuration/contentcuration/frontend/channelEdit/components/edit/EditView.vue, contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue….
  • Confirm the ESLint rules switched off in eslint.config.mjs (tracked by #6359) are acceptable to defer, since other repos will copy this flat-config setup.
QA captures (50)

Create a new account with the country picker — country list loads with English names, search and select a country, submit an invalid form to see all field errors and the scroll to top, then submit a valid form

Step Screenshot
Countries selected Countries selected
Country list open Country list open
Create form initial Create form initial
Invalid submit errors Invalid submit errors
Valid form filled Valid form filled
Valid submit activation sent Valid submit activation sent
1-invalid-submit-scroll-top.webm

Request more storage from Settings > Storage — country field lists and accepts countries, an empty submit shows the error banner and scrolls to it, a valid submit sends the request

Step Screenshot
Country chips selected Country chips selected
Empty submit error banner Empty submit error banner
Valid submit sent Valid submit sent

Filter the admin Users table by country, then open a user and change their privileges in the privilege modal — country options populate, the filter narrows rows, the modal submit applies the change

Step Screenshot
Filter afghanistan one row Filter afghanistan one row
Filter kenya zero Filter kenya zero
Location options Location options
Privilege modal wrong email Privilege modal wrong email
User c now admin User c now admin
3-add-admin-privileges.webm

Browse the Community Library list in Channels and filter by country — country options populate with names, a selection updates the URL and list, and channel cards and the details panel show country names

Step Screenshot
Country dropdown open Country dropdown open
Details panel countries Details panel countries
Filtered kenya Filtered kenya
Rtl arabic filtered Rtl arabic filtered

Switch the UI language to Spanish and then Arabic, then open a country picker (Settings > Storage or the admin Users filter) — strings translate, country names follow the locale, Arabic renders RTL

Step Screenshot
Ar admin users location filter Ar admin users location filter
Ar country picker rtl Ar country picker rtl
Change language dialog Change language dialog
Es country picker search Es country picker search

Open an exercise in channel edit and move between the Details, Questions and Related tabs — each tab renders, adding a question and a related resource saves

Step Screenshot
Details tab Details tab
New question editing New question editing
Next step picker Next step picker
Question added Question added
Questions tab Questions tab
Related step added Related step added
Related tab Related tab

Create a new channel and set its content defaults (author, license, copyright holder, thumbnail options), save, then reopen the channel settings — the defaults form renders and the values persist

Step Screenshot
Create attempt top Create attempt top
New channel defaults filled New channel defaults filled
Reopened defaults persisted Reopened defaults persisted

Use Forgot password to request a reset email, then open a reset-password link with an invalid token — the instructions-sent page shows, and the reset route renders the expired-link page rather than a blank route

Step Screenshot
Forgot password empty submit Forgot password empty submit
Instructions sent Instructions sent
Reset link expired ar Reset link expired ar
Reset link expired Reset link expired
Reset password forbidden Reset password forbidden
Reset password form Reset password form
8-forgot-to-expired-flow.webm

Change full name and password from Settings > Account — each form validates, submits, and shows its success message

Step Screenshot
Full name saved Full name saved
Full name validation Full name validation
Password empty validation Password empty validation
Password mismatch Password mismatch
Password saved Password saved

In channel edit, take the browser offline and back online — the offline indicator appears and clears, and an edit made while offline syncs after reconnecting

Step Screenshot
Back online edit modal Back online edit modal
Back online empty channel Back online empty channel
Offline indicator Offline indicator
Offline new folder modal Offline new folder modal

Written by rtibblesbot, an LLM-based coding agent.

LianaHarris360 and others added 3 commits November 2, 2026 12:29
Replace .eslintrc.js with eslint.config.mjs. Bump kolibri-i18n to 1.0.1,
which drops the ESLint 8 copy of kolibri-format that read the old file.

Co-Authored-By: Claude Opus 5 <[email protected]>

@rtibblesbot rtibblesbot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6358: 4 of 4 prior findings resolved; 2 new blocking findings (inline).

  • CI failing: Linting fails on the gapMatch files from unstable.
  • The PR head moved after these passes ran. The newest commits are unreviewed.
  • Manual QA: create-account, storage request, account forms, password reset, content defaults, exercise edit tabs, admin users and offline sync all work in en/es/ar. Not exercised: HTML5 thumbnail capture (no object storage) and Community Library country display (no submissions).
Prior-finding status

RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/comparisonKey.js — renamed disable directives unused, stale comment
RESOLVED — eslint.config.mjs — deferred-rule comments cite #6328
RESOLVED — package.json:133 — dropping root eslint devDependency
RESOLVED — contentcuration/contentcuration/frontend/shared/views/form/ContentDefaults.vue — relative '../../mixins' import

Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.

  • User-visible files changed: contentcuration/contentcuration/frontend/accounts/pages/Create.vue, contentcuration/contentcuration/frontend/accounts/router.js, contentcuration/contentcuration/frontend/administration/pages/Users/UserPrivilegeModal.vue, contentcuration/contentcuration/frontend/channelEdit/components/edit/EditView.vue, contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue….
  • Check that .git-blame-ignore-revs lists the reformat commit's hash as it lands on unstable and that the merge strategy keeps that commit.
  • Check the dependency and lint-tooling upgrade (eslint.config.mjs, pnpm-lock.yaml) before other repos copy the flat-config pattern.
  • With working object storage, generate an HTML5 thumbnail and check that the html2canvas ESM import captures a preview.
QA captures (49)

Create a new account at /accounts/#/create — country field lists, searches and selects countries (multi-select chips), validation errors appear together on a bad submit, a valid submit reaches the activation-sent page with no console errors

Step Screenshot
Activation sent Activation sent
Bad submit errors lower Bad submit errors lower
Bad submit errors Bad submit errors
Country chips selected Country chips selected
Create form initial Create form initial
1-bad-submit-validation.webm
1-country-search-select.webm
1-valid-submit-activation-sent.webm

Switch the UI language to Spanish and then Arabic from the language switcher, reload, then open the create-account and storage-request country fields — strings translate, country names render in the chosen locale, RTL layout applies, no i18n or missing-locale console errors

Step Screenshot
Ar create country list Ar create country list
Ar storage country list Ar storage country list
Es create country list Es create country list
Es storage country list Es storage country list

Request more storage from Settings > Storage — fill the form including the country field, check validation scrolls to the error banner, submit, confirm the request POST and the success state

Step Screenshot
Request submitted Request submitted
Validation error banner Validation error banner
3-request-storage-flow.webm

Change full name and change password from Settings > Account — each form validates, submits, shows its success snackbar and the new name persists after reload

Step Screenshot
Full name empty validation Full name empty validation
Full name saved snackbar Full name saved snackbar
Password validation Password validation

Go through forgot password: submit an email on the forgot-password page, reach the instructions-sent page, then open a reset-password link with an invalid token — the reset page route loads and lands on the link-expired page without a chunk or import error

Step Screenshot
Forgot password page Forgot password page
Instructions sent Instructions sent
Reset link expired Reset link expired
Reset password invalid session Reset password invalid session
5-forgot-password-flow.webm

Create a new channel and then edit its settings — set content defaults (license, copyright holder, author, provider, aggregator, the boolean defaults), save, reopen the modal and confirm the license names render translated and the values persist through /api/sync/

Step Screenshot
Ar license menu Ar license menu
Defaults filled before create Defaults filled before create
Edit special permissions Edit special permissions
License menu open License menu open
Reopened values persisted Reopened values persisted

Open an exercise in the edit modal and switch between the Details, Questions and Related tabs — the Assessment and Related resources tabs render, adding a question and a related resource saves, no console errors

Step Screenshot
Details tab Details tab
Question added Question added
Questions tab empty Questions tab empty
Related added Related added
Related tab empty Related tab empty
7-add-question.webm
7-add-related.webm

Open an HTML5 resource in the edit modal and generate its thumbnail — the screenshot iframe loads the htmlScreenshot bundle from zipcontent, a thumbnail preview appears, no html2canvas error in console (stop at the upload if storage is unavailable)

Step Screenshot
Generate stuck zip missing from storage Generate stuck zip missing from storage
Html5 edit modal thumbnail before Html5 edit modal thumbnail before
Html5 upload failed no storage Html5 upload failed no storage

Browse the Community Library list as a user and as an admin open a submission review side panel — country filters list and filter channels, channel cards and the details panel show country names, the review panel shows the submission countries

Step Screenshot
Community library empty Community library empty

As an admin, filter the Users table by country and open the user privilege modal to toggle a privilege — filter results update, the modal submits and the row reflects the change

Step Screenshot
Filtered kenya Filtered kenya
Privilege modal mismatch Privilege modal mismatch
Row after add admin Row after add admin
10-filter-and-privilege.webm

In the channel editor, emulate going offline and back online — the offline indicator appears and clears, edits made offline sync once online

Step Screenshot
Offline close modal page not found Offline close modal page not found
Offline edit title Offline edit title
Offline indicator Offline indicator
Offline new folder failed load Offline new folder failed load
Online indicator cleared Online indicator cleared
11-offline-edit-online-sync.webm

Written by rtibblesbot, an LLM-based coding agent.

Comment thread .git-blame-ignore-revs Resolved
Comment thread eslint.config.mjs Resolved

@rtibblesbot rtibblesbot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #6358: all 6 prior findings resolved; no new findings.

  • CI passing.
  • Manual QA did not run.
Prior-finding status

RESOLVED — .git-blame-ignore-revs:7 — wrong reformat commit hash
RESOLVED — eslint.config.mjs:82 — Linting job fails on gapMatch/* files from unstable
RESOLVED — contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/comparisonKey.js — unused renamed disable directives, stale comment
RESOLVED — eslint.config.mjs — deferred-rule comments cite #6328
RESOLVED — package.json:133 — dropping root eslint devDependency
RESOLVED — contentcuration/contentcuration/frontend/shared/views/form/ContentDefaults.vue — relative '../../mixins' import

Next step: Needs a full code review by a human engineer, then manual QA once that reviewer sets Needs QA.

  • User-visible files changed: contentcuration/contentcuration/frontend/accounts/pages/Create.vue, contentcuration/contentcuration/frontend/accounts/router.js, contentcuration/contentcuration/frontend/administration/pages/Users/UserPrivilegeModal.vue, contentcuration/contentcuration/frontend/channelEdit/components/edit/EditView.vue, contentcuration/contentcuration/frontend/channelEdit/views/files/thumbnails/ThumbnailGenerator.vue….
  • Confirm the pnpm-lock.yaml dependency bumps that came with kolibri-format 3.0.1 are acceptable for the frontend build.
  • Confirm the ESLint rules left disabled in eslint.config.mjs are tracked as follow-ups.

Written by rtibblesbot, an LLM-based coding agent.

@rtibblesbot
rtibblesbot dismissed their stale review November 3, 2026 03:05

Superseded by my review of 33996a5: no blocking findings remain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade kolibri-format to 3.0.1 and migrate ESLint to flat config

2 participants