[DO NOT MERGE]: unstable to hotfixes, Q1 major release#5750
[DO NOT MERGE]: unstable to hotfixes, Q1 major release#5750marcellamaki wants to merge 737 commits intohotfixesfrom
Conversation
…o Vue Testing Library
* first steps for create_channel_versions command * improving on tests - building proper channelversion object (mostly) * cleanup - set Audited license fields correctly I tried just assigning it in the create() call but got a complaint about the direction of my assignment wrt the m2m relationship * (claude): generate more tests to account for the Audited license logic * lint * set version_info when pub_data ver = channel ver * include missing fields * add unit tests for validate_published_data, remove misleading tests - Add TestValidatePublishedData class with direct unit tests for the validate function covering: return type, included_licenses, included_languages, included_categories, kind_counts, non_distributable_licenses, and special_permissions - Remove test_command_skips_channels_with_existing_version_info (didn't actually test idempotency) - Remove test_channel_with_existing_special_permissions_in_published_data (wasn't testing meaningful behavior) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * use ChannelVersion.objects.update_or_create in create_channel_versions * try/catch w/ errors logged; remove None from cats/langs * only validate the pub_data for the latest version * move anti-None code to run on all pub_datas * include date_published & license_notes in update_or_create * cast version to int before comparing; fix license -> version_notes * cast pub_data_version to int toooooo * safer key access when filtering Nones, remove moot test --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* removed ActionLink and replaced them with KExternalLink or KRouterLink in privacyModals --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Updates to the CW scenarios
Bumps [webpack](https://github.com/webpack/webpack) from 5.99.9 to 5.104.1. - [Release notes](https://github.com/webpack/webpack/releases) - [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md) - [Commits](webpack/webpack@v5.99.9...v5.104.1) --- updated-dependencies: - dependency-name: webpack dependency-version: 5.104.1 dependency-type: direct:development ... Signed-off-by: dependabot[bot] <support@github.com>
…ed questions page
Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.0.0 to 12.1.1. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](python-pillow/Pillow@12.0.0...12.1.1) --- updated-dependencies: - dependency-name: pillow dependency-version: 12.1.1 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [axios](https://github.com/axios/axios) from 1.12.2 to 1.13.5. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.12.2...v1.13.5) --- updated-dependencies: - dependency-name: axios dependency-version: 1.13.5 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
…ersioned-content Add migration command for channel versioned content databases
* Set distributable Special Permissions Licenses * [pre-commit.ci lite] apply automatic fixes * fix code --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
…n/mathlive-0.108.2 chore(deps): bump mathlive from 0.105.3 to 0.108.2
…n/axios-1.13.5 chore(deps): bump axios from 1.12.2 to 1.13.5
…12.1.1 chore(deps): bump pillow from 12.0.0 to 12.1.1
…n/webpack-5.104.1 chore(deps-dev): bump webpack from 5.99.9 to 5.104.1
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.21 to 4.17.23. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](lodash/lodash@4.17.21...4.17.23) --- updated-dependencies: - dependency-name: lodash dependency-version: 4.17.23 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [qs](https://github.com/ljharb/qs) from 6.14.0 to 6.14.2. - [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md) - [Commits](ljharb/qs@v6.14.0...v6.14.2) --- updated-dependencies: - dependency-name: qs dependency-version: 6.14.2 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
…n/lodash-4.17.23 chore(deps): bump lodash from 4.17.21 to 4.17.23
….46.2 chore(deps): bump wheel from 0.38.1 to 0.46.2
…k-3.20.3 chore(deps): bump filelock from 3.20.1 to 3.20.3
…env-20.36.1 chore(deps): bump virtualenv from 20.26.6 to 20.36.1
…-1.10.0 chore(deps-dev): bump nodeenv from 1.9.1 to 1.10.0
…n/qs-6.14.2 chore(deps): bump qs from 6.14.0 to 6.14.2
Bumps [workbox-webpack-plugin](https://github.com/googlechrome/workbox) from 7.3.0 to 7.4.0. - [Release notes](https://github.com/googlechrome/workbox/releases) - [Commits](GoogleChrome/workbox@v7.3.0...v7.4.0) --- updated-dependencies: - dependency-name: workbox-webpack-plugin dependency-version: 7.4.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix add to community library change making channel publishable
feat: add library field to v1 and v2 public channel APIs, gate v1 ChannelVersion lookup
Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.1.1 to 12.2.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst) - [Commits](python-pillow/Pillow@12.1.1...12.2.0) --- updated-dependencies: - dependency-name: pillow dependency-version: 12.2.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Jest 30 removed deprecated matcher aliases (toThrowError, toBeCalled, toBeCalledWith, toBeCalledTimes) and changed how toThrow compares error objects. jsdom 26 makes window.location non-configurable per the HTML spec, breaking the common delete-and-replace mocking pattern. - Replace removed matcher aliases with canonical names - Use string messages instead of error objects in toThrow assertions - Extract window.location.assign into shared/utils/navigation module so tests can jest.mock it instead of fighting jsdom's unforgeable Location properties Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…n/jest-1ecd9637f0 chore(deps-dev): bump the jest group across 1 directory with 4 updates
…raphy-46.0.7 chore(deps): bump cryptography from 46.0.6 to 46.0.7
Bumps [pycountry](https://github.com/pycountry/pycountry) from 24.6.1 to 26.2.16. - [Release notes](https://github.com/pycountry/pycountry/releases) - [Changelog](https://github.com/pycountry/pycountry/blob/main/HISTORY.txt) - [Commits](pycountry/pycountry@24.6.1...26.2.16) --- updated-dependencies: - dependency-name: pycountry dependency-version: 26.2.16 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
…9.0.3 chore(deps-dev): bump pytest from 9.0.2 to 9.0.3
…12.2.0 chore(deps): bump pillow from 12.1.1 to 12.2.0
…y-26.2.16 chore(deps): bump pycountry from 24.6.1 to 26.2.16
Update ESoCC strings after UX writing review
…n/lodash-4.18.1 chore(deps): bump lodash from 4.17.23 to 4.18.1
Replace the custom Python crowdin API script with the official crowdin-cli tool. Add crowdin.yml config with language mappings and GitHub Actions workflows for upload/download. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace kolibri-tools with kolibri-build (webpack/babel config) and kolibri-i18n (message extraction, code-gen). Update package scripts, dependabot config, and workspace settings accordingly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Make i18nSetup async with dynamic imports for locale data, matching Kolibri's pattern. Switch from vue-jest to @vue/vue2-jest for proper Vue 2.7 <script setup> support. Update LoadingText.vue to use shared translator strings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When ChannelVersion.version is None, skip the numeric comparison and include all entries from channel.published_data, matching the intent described in the Sentry issue STUDIO-J6Z. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: guard against None version in _get_version_notes
Migrate i18n to crowdin-cli and kolibri-build/kolibri-i18n
| name: Download translations and update files | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| python-version: '3.10' | ||
| activate-environment: "true" | ||
| enable-cache: "true" | ||
|
|
||
| - name: Install Python dependencies | ||
| run: uv pip sync requirements.txt | ||
|
|
||
| - name: Use pnpm | ||
| uses: pnpm/action-setup@v5 | ||
|
|
||
| - name: Use Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: '20.x' | ||
| cache: 'pnpm' | ||
|
|
||
| - name: Setup Java for crowdin-cli | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: '17' | ||
|
|
||
| - name: Install gettext | ||
| run: sudo apt-get update && sudo apt-get install -y gettext | ||
|
|
||
| - name: Install JavaScript dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Download translations | ||
| env: | ||
| CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_KEY }} | ||
| run: make i18n-download | ||
|
|
||
| - name: Generate App Token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@v3 | ||
| with: | ||
| app-id: ${{ secrets.LE_BOT_APP_ID }} | ||
| private-key: ${{ secrets.LE_BOT_PRIVATE_KEY }} | ||
|
|
||
| - name: Create Pull Request | ||
| uses: peter-evans/create-pull-request@v8 | ||
| with: | ||
| token: ${{ steps.generate-token.outputs.token }} | ||
| commit-message: | | ||
| Update translations from Crowdin | ||
|
|
||
| This includes: | ||
| - Updated translation files (.po and .json) | ||
| - Compiled Django messages (.mo files) | ||
| - Updated frontend i18n files | ||
| branch: i18n-update-${{ github.ref_name }} | ||
| base: ${{ github.ref_name }} | ||
| delete-branch: true | ||
| title: 'Update translations from Crowdin for ${{ github.ref_name }}' | ||
| body: | | ||
| ## Summary of changes | ||
|
|
||
| This PR updates translations downloaded from Crowdin. | ||
|
|
||
| ### Changes included: | ||
| - Updated translation files (`.po` and `.json`) | ||
| - Compiled Django messages (`.mo` files) | ||
| - Updated frontend i18n files | ||
|
|
||
| ### Testing checklist: | ||
| - [ ] Verify that translations are not obviously empty or untranslated in the message files | ||
| - [ ] Switch to a few different languages and navigate the app | ||
| labels: | | ||
| i18n | ||
| TAG: user strings |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 16 hours ago
Add an explicit permissions block at the workflow root in .github/workflows/i18n-download.yml so the default token is constrained for all jobs.
Best minimal fix without changing current behavior:
- Add:
contents: read(recommended minimum baseline)
- Because this workflow creates a pull request and may push/update a branch through the PR action, include:
pull-requests: writecontents: write
Placing this at the top-level applies to the existing download job and keeps the workflow behavior intact while removing implicit permission defaults.
| @@ -3,6 +3,10 @@ | ||
| on: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| download: | ||
| name: Download translations and update files |
| name: Extract and upload strings to Crowdin | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@v6 | ||
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| with: | ||
| python-version: '3.10' | ||
| activate-environment: "true" | ||
| enable-cache: "true" | ||
|
|
||
| - name: Install Python dependencies | ||
| run: uv pip sync requirements.txt | ||
|
|
||
| - name: Use pnpm | ||
| uses: pnpm/action-setup@v5 | ||
|
|
||
| - name: Use Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: '20.x' | ||
| cache: 'pnpm' | ||
|
|
||
| - name: Setup Java for crowdin-cli | ||
| uses: actions/setup-java@v5 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: '17' | ||
|
|
||
| - name: Install gettext | ||
| run: sudo apt-get update && sudo apt-get install -y gettext | ||
|
|
||
| - name: Install JavaScript dependencies | ||
| run: pnpm install --frozen-lockfile | ||
|
|
||
| - name: Extract and upload strings to Crowdin | ||
| env: | ||
| CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_KEY }} | ||
| run: | | ||
| make i18n-upload | ||
| make i18n-pretranslate-approve-all |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 16 hours ago
Add an explicit permissions block to the workflow, ideally at the root so it applies to all jobs unless overridden. For this workflow, the minimal safe baseline is contents: read, which is sufficient for actions/checkout and does not grant unnecessary write access.
In .github/workflows/i18n-upload.yml, insert the following directly under the on: section (before jobs:), keeping existing logic unchanged:
permissions:contents: read
No additional imports, methods, or definitions are needed (YAML workflow config only).
| @@ -3,6 +3,9 @@ | ||
| on: | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| upload: | ||
| name: Extract and upload strings to Crowdin |
Bumps [celery](https://github.com/celery/celery) from 5.6.0 to 5.6.3. - [Release notes](https://github.com/celery/celery/releases) - [Changelog](https://github.com/celery/celery/blob/v5.6.3/Changelog.rst) - [Commits](celery/celery@v5.6.0...v5.6.3) --- updated-dependencies: - dependency-name: celery dependency-version: 5.6.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4. - [Release notes](https://github.com/docker/setup-qemu-action/releases) - [Commits](docker/setup-qemu-action@v3...v4) --- updated-dependencies: - dependency-name: docker/setup-qemu-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps the babel group with 1 update: [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env). Updates `@babel/preset-env` from 7.29.0 to 7.29.2 - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.2/packages/babel-preset-env) --- updated-dependencies: - dependency-name: "@babel/preset-env" dependency-version: 7.29.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: babel ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [axios](https://github.com/axios/axios) from 1.13.5 to 1.15.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.13.5...v1.15.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.15.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [workbox-precaching](https://github.com/googlechrome/workbox) from 7.3.0 to 7.4.0. - [Release notes](https://github.com/googlechrome/workbox/releases) - [Commits](GoogleChrome/workbox@v7.3.0...v7.4.0) --- updated-dependencies: - dependency-name: workbox-precaching dependency-version: 7.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
….6.3 chore(deps): bump celery from 5.6.0 to 5.6.3
…ons/docker/setup-qemu-action-4 chore(deps): bump docker/setup-qemu-action from 3 to 4
…n/babel-cf72c556cb chore(deps-dev): bump @babel/preset-env from 7.29.0 to 7.29.2 in the babel group
…n/axios-1.15.0 chore(deps): bump axios from 1.13.5 to 1.15.0
…n/workbox-precaching-7.4.0 chore(deps): bump workbox-precaching from 7.3.0 to 7.4.0
!IMPORTANT!
ensure_versioned_databases_existandcreate_channel_versionsmigration commands should be added to Makefile's deploy-migrate command just before merging this PR.Summary
…
Vuetify → KDS Migration
Tracking issue: #5060
This overview sets the scope of regression testing needed before release. The refactoring work replaces Vuetify components with Kolibri Design System (KDS) components across Studio. For each workflow, we're primarily focused on interactions and functionality — making sure nothing broke in the migration. Some minor visual differences are expected and noted below.
For detailed context on any specific change, issue links are included per section. When in doubt about whether something is a regression or an intentional change, check the linked issues.
General notes:
unstable/settings)We're regression testing all 3 tabs. The priority is interactions and functionality.
What changed: Page layout, offline alert bar, and several components across the Account and Storage tabs were migrated from Vuetify to KDS.
Account tab:
Storage tab:
General:
Visual differences: Modals (e.g., "About licenses", "Request more space") will look slightly different from production due to KDS styling. Functionality is the priority.
Related issues: #5061, #5062, #5063, #5064, #5080, #5081, #5082, #5092, #5095, #5123, #5127, #5132
/channels)Several distinct sub-areas were touched here. Test each sub-area as a workflow.
What changed: Channel cards across all channel listing views, channel detail pages, channel collections, the Content Library, error pages, and several modals were all migrated.
2a. Channel listing views (My Channels, Starred, View-only)
Related issues: #5218, #5219, #5227, #5524, #5525
2b. Channel detail page
Visual differences: Modals on the channel detail page (e.g., unsaved changes) will look slightly different.
Related issues: #5217, #5474, #5484, #5485, #5529, #5530
2c. New collection / Unsaved changes
Visual differences: "Unsaved changes" modal will look slightly different from production.
Related issues: #5243, #5244, #5298, #5299
2d. Content Library
Visual differences: "About collections" modal will look slightly different.
Related issues: #5234, #5471, #5502, #5526, #5528
2e. Error pages
Related issues: #5235, #5295, #5296, #5297
The channel editor had the most changes across this migration — many dialogs and action buttons throughout the editing workflow were updated. Test these as you would a normal editing session, but make a point to trigger each dialog.
What changed: Buttons and dialogs throughout the editing workflow — move, upload, questions, import, and several confirmation dialogs.
Organize / Move:
Upload:
Questions:
Content actions:
Related tab:
File preview:
Import from channels:
Navigation / errors:
Visual differences: All dialogs/modals in the channel editor (move, upload, confirm delete, change question type, etc.) will look slightly different from production.
Related issues: #5355, #5375, #5376, #5377, #5378, #5379, #5420, #5421, #5422, #5423, #5442, #5443, #5444, #5470, #5472, #5473
These are the pre-login and account lifecycle pages. Testing is straightforward — confirm all interactive elements function correctly.
What changed: Buttons and links on the sign-in, account created, and account deleted pages; various informative pages.
Related issues: #5352, #5353, #5534, #5631, #5632, #5633, #5636, #5637
/administration)Admin-only pages. Confirm all management actions and their confirmation dialogs work end-to-end.
What changed: Buttons and confirmation dialogs for user and channel management actions; the send email dialog.
Users:
Channels:
Email:
Visual differences: All confirmation dialogs and the send email dialog will look slightly different from production.
Related issues: #5354, #5410, #5411, #5425, #5441
Policy modals
Visual differences: Policy modals will look slightly different from production.
Related issues: #5651
Easy Sharing of Community Channels (ESoCC)
Tracking issue: learningequality/kolibri-ecosystem#42
Overview
This document sets the scope of QA testing for the Easy Sharing of Community Channels feature — a set of new workflows that allow channel editors to submit channels for inclusion in a Community Library, and admins to review and approve those submissions.
The four primary workflows are:
General notes:
unstabletest_dev_featurefeature flag — confirm it is enabled before testing that workflowThis feature focuses on two user types — channel editors (regular Studio users who create and manage channels) and Studio admins (internal Learning Equality staff who review submissions). Since aspects of the workflows are interdependent, setting up two accounts to start may make testing more efficient.
(I tried to test the UX with just one admin account and definitely confused myself 😓 )
You can test draft channel publishing workflow separately (Section 1), since it's pretty self-contained.
Community channels (suggested) testing flow:
(This will probably have to be repeated for several different scenarios such as publishing a channel while a submission is still under review, approving vs. not, etc.)
1. Draft channel publishing
Channel editors can now publish a new version of a channel as a "draft" — this allows the new version to be tested in Kolibri without publishing it as the live version for users. Draft versions get their own token for import into Kolibri.
Note: This workflow requires the
test_dev_featurefeature flag to be enabled.Publishing a draft:
Version history in publish side panel:
After publishing a channel that already has a Community Library submission:
Related issues: #4471, #5172, #5192, #5209, #5460, #5461, #5463, #5567, #5617, #5629
2. Submitting a channel to the Community Library
Channel editors can submit a published channel for inclusion in the Community Library. The submission includes metadata (country, subject), and the system runs a license audit to flag any content that may not be distributable.
Accessing the submission panel:
To test the license audit warning states, you'll need a published channel that contains at least one resource with an "All Rights Reserved" license. Add such a resource, publish the channel, then open the submission panel — the audit should flag it.
Filling out the submission form:
Subsequent submissions and state messaging:
After publishing a channel that already has a Community Library submission:
Deleting a channel that is live in the Community Library:
Related issues: #5159, #5145, #5157, #5158, #5169, #5262, #5448, #5449, #5450, #5451, #5452, #5453, #5459, #5568
3. Admin review and approval workflows
What this is: The admin channels table has been updated to surface Community Library submission status, and a new review flow allows admins to approve, flag, or add notes to submissions.
Admin channels table (
/administration/channels):Community Library details page:
Review side panel:
Related issues: #5173, #5170, #5171, #5191, #5208, #5250, #5251, #5263, #5301, #5302, #5455, #5580, #5581, #5627
4. Channel editor notifications
What this is: When an admin approves or flags a submission, the submitting channel editor receives a notification. A red dot appears on their username and in the sidebar, and a notifications page shows the submission status and any feedback from the admin.
Setup — use separate accounts: This workflow requires actions from two different roles. We recommend testing with two separate browser sessions (or one normal + one incognito window) to avoid confusion:
Trying to do both from the same account makes the UX difficult to follow and can mask issues.
Note: The notifications page shows all submissions across all channels the user is an editor of, and all resolutions (approvals/rejections) for those submissions.
Red dot / notification indicator:
Notification recipients:
Notifications page:
Related issues: #5174, #5456, #5457, #5458
AI usage
Significant Claude help in drafting QA team guidance