From 0d3734cc11709f15315cf62fd048ef24f2e2ab66 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 25 Jun 2026 08:57:23 -0600 Subject: [PATCH 01/10] feat: add OpenSpec change for GitHub-based JIRA YAML workflow Proposes a system for managing JIRA tickets as versioned YAML files in .jira/, applied to JIRA automatically on PR merge via the existing build workflow. Includes specs and tasks for apply.mjs, fetch.mjs, /jira-propose skill, and build workflow integration. --- .../github-jira-yaml-workflow/.openspec.yaml | 2 + .../github-jira-yaml-workflow/design.md | 93 +++++++++++++++ .../github-jira-yaml-workflow/proposal.md | 38 +++++++ .../specs/jira-apply-workflow/spec.md | 106 ++++++++++++++++++ .../specs/jira-fetch-script/spec.md | 68 +++++++++++ .../specs/jira-propose-action/spec.md | 75 +++++++++++++ .../specs/jira-yaml-schema/spec.md | 63 +++++++++++ .../github-jira-yaml-workflow/tasks.md | 45 ++++++++ 8 files changed, 490 insertions(+) create mode 100644 openspec/changes/github-jira-yaml-workflow/.openspec.yaml create mode 100644 openspec/changes/github-jira-yaml-workflow/design.md create mode 100644 openspec/changes/github-jira-yaml-workflow/proposal.md create mode 100644 openspec/changes/github-jira-yaml-workflow/specs/jira-apply-workflow/spec.md create mode 100644 openspec/changes/github-jira-yaml-workflow/specs/jira-fetch-script/spec.md create mode 100644 openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md create mode 100644 openspec/changes/github-jira-yaml-workflow/specs/jira-yaml-schema/spec.md create mode 100644 openspec/changes/github-jira-yaml-workflow/tasks.md diff --git a/openspec/changes/github-jira-yaml-workflow/.openspec.yaml b/openspec/changes/github-jira-yaml-workflow/.openspec.yaml new file mode 100644 index 000000000..fab62b414 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-06-24 diff --git a/openspec/changes/github-jira-yaml-workflow/design.md b/openspec/changes/github-jira-yaml-workflow/design.md new file mode 100644 index 000000000..52a614527 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/design.md @@ -0,0 +1,93 @@ +## Context + +The team manages JIRA tickets for the AEP Web SDK (project `PDCL` at `jira.corp.adobe.com`) manually through the browser. Existing scripts in `scripts/createJiraTicket.js` and `scripts/team/` (api.js, config.js, token.js) were written to automate ticket creation but have never been adopted team-wide because they require individual token setup and don't integrate with the PR review process. + +The new system treats `.jira/*.yml` files as the source of truth for pending JIRA changes. A GitHub Actions workflow applies them on merge. A Claude Code action creates/updates these files locally during development. + +Custom field IDs used in the PDCL project: +- `components`: `[{ id: "155901" }]` (AEP Web SDK) +- `customfield_23300`: `{ id: "116005" }` (product) +- Documentation component: `{ id: "157512" }` +- Issue types: bug `1`, story `7`, documentation `14801` +- Base URL: `https://jira.corp.adobe.com` + +## Goals / Non-Goals + +**Goals:** +- All JIRA changes made via PR are auditable, reviewable, and version-controlled +- Apply step is idempotent — re-running the workflow never creates duplicate tickets or duplicate updates +- Local authoring (propose) makes zero JIRA API calls +- YAML files are human-readable and support inline comments for custom field documentation +- Remote link to the merged PR is always created in JIRA as part of apply + +**Non-Goals:** +- Real-time JIRA → repo sync (the `details` snapshot is a one-time capture, not kept live) +- Automated backfill of historical tickets +- Support for JIRA projects other than PDCL (config is project-key-aware but multi-project support is not in scope) +- Replacing the JIRA UI for complex ticket authoring (descriptions, attachments, etc.) + +## Decisions + +### YAML over JSON for ticket files +**Decision**: Use YAML with inline comments. +**Rationale**: Custom field IDs like `customfield_23300` are opaque. YAML lets authors add `# AEP Web SDK product field` next to each custom field so the file is self-documenting. The apply script converts YAML bodies to JSON before sending to the REST API. +**Alternative**: JSON with a separate field-map file — rejected because it separates documentation from the data. + +### REST call array (`updates`) rather than a declarative diff +**Decision**: `updates` is an ordered array of `{ path, method, body }` objects. +**Rationale**: JIRA's REST API is operation-based (edit fields via PUT/POST with specific payloads). A declarative diff would require a JIRA-specific diff engine. The array approach maps directly to the API and keeps the schema simple. +**Idempotency**: All `body.update` payloads use `set` operations, never `add`/`remove`. The apply script skips updates when the remote link already exists (checked before applying). + +### Remote link as idempotency key for new tickets +**Decision**: Before creating a new ticket (`PDCL-XXXX-*.yml`), the apply script searches JIRA for any issue in the project with a remote link whose URL matches the PR URL. If found, the ticket already exists and creation is skipped. +**Rationale**: `PDCL-XXXX` files have no real ticket key yet, so we need an external signal. GitHub PR URLs are stable and unique — a perfect idempotency key. + +### `details` section is read-only metadata +**Decision**: The `details` section is a snapshot captured at propose time (or manually). The apply script ignores it entirely. +**Rationale**: Prevents accidental JIRA drift if `details` gets stale. Updates are always expressed explicitly in `updates`. + +### New ticket file naming with `XXXX` sentinel +**Decision**: Unsubmitted tickets use `PDCL-XXXX-short-description.yml`. After the apply workflow creates the ticket, the file is NOT automatically renamed (the real key appears in the JIRA remote link and in the workflow output log). +**Rationale**: Renaming requires a follow-up commit; accepting a slightly stale filename is simpler and avoids merge conflicts. Teams can manually rename as a housekeeping step. + +### Local `/jira-propose` makes zero JIRA calls +**Decision**: The propose action only reads `.jira/` files and git state. It never calls the JIRA API. +**Rationale**: Developers may not have a JIRA PAT configured; the action should work offline and in CI lint passes. JIRA reads are deferred to the `details` snapshot (which can be populated manually or by a separate fetch script in future). + +### Apply and fetch script location +**Decision**: `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` — standalone Node.js ES modules. +**Rationale**: Keeps CI logic in the same `scripts/` tree as the existing JIRA helpers, enabling code reuse from `scripts/team/config.js`. + +### Fetch script design +**Decision**: `fetch.mjs` accepts a ticket key (e.g. `PDCL-1234`) or a `.jira/` filename, calls JIRA's `GET /rest/api/2/issue/{key}` endpoint, and writes (or updates) a `.jira/{key}-{slug}.yml` file. The slug is derived from the ticket summary. If the file already exists, only the `details` section is replaced; any `updates` array is preserved. +**Rationale**: Lets developers bootstrap the `details` snapshot from a real ticket without copy-pasting from the JIRA UI. Can also be run in CI before apply to capture a before-snapshot for audit logs. + +### No separate JIRA workflow file +**Decision**: Integrate the `apply-jira` job into the existing `.github/workflows/version-and-publish.yml`. +**Rationale**: Avoids proliferating workflow files. The apply job is a pure side-effect on merge to `main` — it belongs alongside other post-merge steps (publish, deploy, release notes). It runs independently of the changeset gate so it fires on every push to `main`, not just release pushes. + +## Risks / Trade-offs + +- **Stale `details` snapshot** → Mitigation: `details` is advisory only; apply ignores it. Document this clearly in schema comments. +- **XXXX files never renamed** → Mitigation: Workflow output logs the real ticket key. A future housekeeping script can rename files post-merge. +- **JIRA API pagination on remote-link search** → Mitigation: Apply script iterates all pages when searching for an existing remote link before creating a new ticket. +- **PAT expiry breaks apply workflow** → Mitigation: Workflow fails loudly with a clear error; no partial state written. Token rotation is an ops concern (existing pattern for `JIRA_API_TOKEN` secret). +- **Concurrent PRs both creating the same PDCL-XXXX ticket** → Mitigation: Remote-link idempotency check handles this — whichever workflow runs second finds the link and skips creation. +- **Large JIRA body fields (description)** → Mitigation: `details` snapshot truncates long string fields (> 500 chars) with a `...` suffix; full content lives in JIRA. + +## Migration Plan + +1. Add `.jira/` directory with a `.gitkeep` +2. Add `scripts/jira/fetch.mjs` — test locally against a real PDCL ticket with `--dry-run` +3. Add `scripts/jira/apply.mjs` — test locally with `--dry-run` +4. Add `apply-jira` job to `version-and-publish.yml` referencing `JIRA_API_TOKEN` secret +5. Add `.claude/commands/jira-propose.md` skill +6. Remove (or archive to `scripts/legacy/`) `scripts/createJiraTicket.js` — the `scripts/team/` helpers are retained as shared utilities +7. Update `CLAUDE.md` / team docs with the new workflow + +Rollback: Remove the `apply-jira` job from the workflow. YAML files in `.jira/` are inert without the job. + +## Open Questions + +- Should the apply workflow post a PR comment with JIRA links after applying? (Nice-to-have; out of scope for v1) +- Should `details` be populated automatically by a fetch script when `/jira-propose` is run against an existing ticket key? (Deferred; requires JIRA auth locally) diff --git a/openspec/changes/github-jira-yaml-workflow/proposal.md b/openspec/changes/github-jira-yaml-workflow/proposal.md new file mode 100644 index 000000000..7af2881d1 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/proposal.md @@ -0,0 +1,38 @@ +## Why + +The team's JIRA backlog management is disconnected from the codebase — ticket updates happen in the browser, making them invisible to code review, hard to audit, and impossible to automate. By representing JIRA changes as YAML files in the repo, every ticket update becomes a reviewable, version-controlled artifact that is applied deterministically when a PR merges, eliminating manual JIRA work and keeping the backlog in sync with shipped code. + +## What Changes + +- New `.jira/` directory at the repo root holds one YAML file per ticket (existing or new) +- YAML files follow the schema `{PROJECT}-{TICKET#}-short-title.yml` (e.g. `PDCL-1234-support-for-adcloud.yml`); new unsubmitted tickets use `PDCL-XXXX-short-description.yml` +- Each file has two optional top-level sections: + - `details` — snapshot of the ticket's current non-null fields (read-only reference; not applied to JIRA) + - `updates` — ordered array of idempotent REST calls (`path`, `method`, `body`) to apply when the PR merges +- YAML is used (not JSON) so inline comments can document custom field IDs (e.g. `customfield_23300`) +- The existing build workflow (`version-and-publish.yml`) gains a new `apply-jira` job that runs on every push to `main`; it detects which `.jira/*.yml` files changed in the merge, then for each file runs `apply.mjs` → captures the returned ticket key → runs `fetch.mjs` to refresh `details` → commits the updated files back to `main` +- `scripts/jira/apply.mjs ` applies that file's `updates` to JIRA, creates a remote link to the PR, and prints the resolved ticket key (e.g. `PDCL-1234`) to stdout; the remote link doubles as the idempotency key for new ticket creation +- New tickets use `PDCL-XXXX-...` sentinel names; the apply script searches for an existing remote link matching the PR URL before creating, ensuring idempotency if the job re-runs +- `scripts/jira/fetch.mjs ` fetches the current JIRA state for `` and writes it into the `details` section of ``, preserving any existing `updates` array; both arguments are required +- A new `/jira-propose` Claude Code action inspects current git changes and chat context, searches `.jira/` for a matching ticket file, and creates one locally if none exists — **no JIRA API calls are made locally** +- Existing `scripts/createJiraTicket.js` and related scripts are superseded and will be removed; their field/template knowledge (project key, component IDs, custom fields) is migrated into the YAML schema and helper scripts + +## Capabilities + +### New Capabilities + +- `jira-yaml-schema`: YAML file format and directory conventions for representing JIRA ticket state and pending updates +- `jira-apply-workflow`: Job added to the existing build workflow that applies `.jira/` YAML files to JIRA on every push to `main`, including remote-link creation and idempotency logic +- `jira-fetch-script`: `scripts/jira/fetch.mjs` that generates or updates a `.jira/` YAML file's `details` section from a live JIRA ticket, preserving any existing `updates` +- `jira-propose-action`: Claude Code `/jira-propose` slash command that creates or updates `.jira/` YAML files locally based on current changes — no JIRA API calls + +### Modified Capabilities + +## Impact + +- New `.jira/` directory and files added to all PRs that touch JIRA tickets +- `.github/workflows/version-and-publish.yml` gains a new `apply-jira` job; no new workflow file is created +- New `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` Node.js scripts; both reuse `scripts/team/config.js` for base URL and project key +- Existing `scripts/createJiraTicket.js`, `scripts/openPr.js` JIRA fetch logic, and `scripts/team/` helpers referenced but some superseded +- New `.claude/commands/jira-propose.md` skill definition +- `JIRA_API_TOKEN` secret must be available in the GitHub Actions `Production` environment (already used by existing workflows) diff --git a/openspec/changes/github-jira-yaml-workflow/specs/jira-apply-workflow/spec.md b/openspec/changes/github-jira-yaml-workflow/specs/jira-apply-workflow/spec.md new file mode 100644 index 000000000..dee0c2d57 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/specs/jira-apply-workflow/spec.md @@ -0,0 +1,106 @@ +## ADDED Requirements + +### Requirement: The existing build workflow gains an `apply-jira` job that runs on every push to `main` +`.github/workflows/version-and-publish.yml` SHALL include a new `apply-jira` job. The job SHALL run on every `push` to `main` (independently of the changeset gate used by the `publish` job). No separate workflow file is created. + +#### Scenario: Job runs on every push to `main`, not only release pushes +- **WHEN** a PR with `.jira/*.yml` changes is merged and there is no pending changeset +- **THEN** the `apply-jira` job still runs + +#### Scenario: Job exits early when no `.jira/*.yml` files changed in the push +- **WHEN** the merge commit contains no changes to `.jira/*.yml` files +- **THEN** the `apply-jira` job exits without making any JIRA API calls + +### Requirement: The workflow discovers changed `.jira/` files from the merge and runs apply then fetch on each +The `apply-jira` job SHALL detect which `.jira/*.yml` files changed in the merge commit using `git diff HEAD^1 HEAD --name-only`. For each changed file it SHALL: +1. Run `node scripts/jira/apply.mjs ` and capture the ticket key printed to stdout +2. Run `node scripts/jira/fetch.mjs ` to refresh `details` with post-apply JIRA state +3. After all files are processed, commit any changes to `.jira/` files back to `main` with `[skip ci]` + +#### Scenario: apply then fetch run for each changed file +- **WHEN** a PR merges that changed `PDCL-1234-my-feature.yml` and `PDCL-XXXX-new-ticket.yml` +- **THEN** the job runs `apply.mjs` then `fetch.mjs` on each file independently + +#### Scenario: Ticket key from apply is passed to fetch +- **WHEN** `apply.mjs PDCL-XXXX-new-ticket.yml` prints `PDCL-5678` to stdout (the newly created ticket key) +- **THEN** the job calls `fetch.mjs PDCL-5678 PDCL-XXXX-new-ticket.yml` + +#### Scenario: Updated details are committed back to main +- **WHEN** fetch refreshes one or more `.jira/` files with new `details` content +- **THEN** the job commits those changes to `main` with a `chore: refresh JIRA details [skip ci]` message + +### Requirement: Apply script takes a single filename argument and prints the resolved ticket key to stdout +`scripts/jira/apply.mjs` SHALL accept one required positional argument: the path to a `.jira/*.yml` file. It SHALL print the resolved JIRA ticket key (e.g. `PDCL-1234`) to stdout as the final line of output, so the calling script can capture it. + +For existing ticket files, the key is parsed from the filename. For `XXXX` files, the key is the real ticket key obtained after creation (or discovered via idempotency check). + +If the file has no `updates` key or an empty array, the script SHALL still print the ticket key and exit 0 without making any API calls. + +#### Scenario: Ticket key printed to stdout for existing ticket +- **WHEN** `node scripts/jira/apply.mjs .jira/PDCL-1234-my-feature.yml` runs +- **THEN** `PDCL-1234` is the last line printed to stdout + +#### Scenario: Real ticket key printed for new ticket +- **WHEN** `node scripts/jira/apply.mjs .jira/PDCL-XXXX-new-ticket.yml` runs and creates ticket `PDCL-5678` +- **THEN** `PDCL-5678` is the last line printed to stdout + +#### Scenario: No-update file prints key without API calls +- **WHEN** a file has no `updates` array and `apply.mjs` is called on it +- **THEN** the script prints the ticket key and exits 0 with no JIRA API calls made + +### Requirement: Apply script is idempotent for new ticket creation +Before creating a new ticket (file with `XXXX` in the name), the apply script SHALL search JIRA for any issue in the project with a remote link whose URL exactly matches `GITHUB_PR_URL`. If found, that ticket's key is used for all subsequent steps. The search SHALL handle JIRA API pagination. + +#### Scenario: Second run finds existing remote link and skips creation +- **WHEN** `apply.mjs` is called a second time for the same `PDCL-XXXX-*.yml` and the PR's remote link already exists +- **THEN** the script uses the found ticket key, skips the create call, and prints the key to stdout + +#### Scenario: No existing remote link — ticket is created +- **WHEN** no remote link matching `GITHUB_PR_URL` exists in the project +- **THEN** the apply script executes the create-ticket REST call and uses the returned key + +### Requirement: Apply script creates a JIRA remote link for every processed ticket that has updates +After applying all `updates` for a ticket, the apply script SHALL POST to `/rest/api/2/issue/{key}/remotelink` with: +- `url`: the value of `GITHUB_PR_URL` +- `title`: the value of `GITHUB_PR_TITLE` +- `relationship`: `"mentioned in"` + +If a remote link with the same URL already exists on the ticket, the script SHALL skip link creation. + +Files with no `updates` array SHALL NOT have a remote link created. + +#### Scenario: Remote link created after updates applied +- **WHEN** a `.jira/` file with a non-empty `updates` array is processed +- **THEN** a remote link pointing to the merged PR is added to the JIRA ticket + +#### Scenario: Remote link skipped for no-update files +- **WHEN** a `.jira/` file has no `updates` key +- **THEN** no remote link is created + +### Requirement: Apply script accepts PR context via environment variables +The apply script SHALL read `GITHUB_PR_URL` and `GITHUB_PR_TITLE` from the environment. Both are required when the file has an `updates` array. If either is missing when updates are present, the script SHALL exit with a clear error message and code 1. + +#### Scenario: Missing PR URL causes exit when updates present +- **WHEN** `GITHUB_PR_URL` is not set and the file has updates +- **THEN** the script exits with code 1 and an error message + +### Requirement: Apply script supports a `--dry-run` flag +When `--dry-run` is passed, the script SHALL print all planned API calls (method, path, JSON body) and the ticket key to stdout without making any HTTP requests. + +#### Scenario: Dry run prints planned calls and key +- **WHEN** `node scripts/jira/apply.mjs --dry-run .jira/PDCL-1234-foo.yml` is run +- **THEN** all planned JIRA calls are printed and `PDCL-1234` is the last line, with no HTTP requests made + +### Requirement: Apply script exits with a non-zero code on any API failure +If any JIRA REST call returns a non-2xx response, the apply script SHALL log the error and exit with code 1, causing the workflow job to fail. + +#### Scenario: API error causes job failure +- **WHEN** a JIRA API call returns 4xx or 5xx +- **THEN** the script logs the status and response body, then exits with code 1 + +### Requirement: Apply script uses `JIRA_API_TOKEN` from the environment +The apply script SHALL read the bearer token from `JIRA_API_TOKEN`. If absent, it SHALL print `"JIRA_API_TOKEN is required"` and exit with code 1. + +#### Scenario: Missing token causes early exit +- **WHEN** `JIRA_API_TOKEN` is not set +- **THEN** the script exits with code 1 before making any HTTP requests diff --git a/openspec/changes/github-jira-yaml-workflow/specs/jira-fetch-script/spec.md b/openspec/changes/github-jira-yaml-workflow/specs/jira-fetch-script/spec.md new file mode 100644 index 000000000..65aabcdf1 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/specs/jira-fetch-script/spec.md @@ -0,0 +1,68 @@ +## ADDED Requirements + +### Requirement: Fetch script requires both a ticket key and a filename as positional arguments +`scripts/jira/fetch.mjs` SHALL accept exactly two required positional arguments: +1. `` — a JIRA issue key (e.g. `PDCL-1234`) +2. `` — the `.jira/` file to write (e.g. `.jira/PDCL-1234-my-feature.yml` or `PDCL-XXXX-new-ticket.yml`) + +If either argument is missing, the script SHALL print usage and exit with code 1. + +The ticket key and filename are treated independently — the key is used to fetch from JIRA, and the filename determines where to write. This allows the caller to pass the real key alongside an `XXXX` filename (e.g. after `apply.mjs` creates a new ticket). + +#### Scenario: Both arguments required +- **WHEN** the script is called with only one argument +- **THEN** it prints usage (`Usage: fetch.mjs `) and exits with code 1 + +#### Scenario: Key and filename provided independently +- **WHEN** called as `node scripts/jira/fetch.mjs PDCL-1234 .jira/PDCL-XXXX-new-ticket.yml` +- **THEN** it fetches JIRA data for `PDCL-1234` and writes to `.jira/PDCL-XXXX-new-ticket.yml` + +#### Scenario: Normal call for existing ticket +- **WHEN** called as `node scripts/jira/fetch.mjs PDCL-1234 .jira/PDCL-1234-my-feature.yml` +- **THEN** it fetches `PDCL-1234` from JIRA and updates `.jira/PDCL-1234-my-feature.yml` + +### Requirement: Fetch script populates the `details` section from live JIRA data +The fetch script SHALL call `GET /rest/api/2/issue/{key}` and extract all non-null fields from the response. It SHALL write these fields under the `details` key in the output YAML file. + +Long string values (over 500 characters) SHALL be truncated to 500 characters with a `...` suffix. The `details` section SHALL be annotated with a YAML comment (`# fetched from JIRA `) on the first line. + +Fields with null or empty-array values SHALL be omitted from `details`. + +#### Scenario: Non-null fields appear in `details` +- **WHEN** the fetch script runs against `PDCL-1234` which has a summary, status, assignee, and two components +- **THEN** all four fields appear under `details` in the output YAML + +#### Scenario: Null fields are omitted +- **WHEN** a field in the JIRA response is null or an empty array +- **THEN** that field does not appear in the `details` section + +#### Scenario: Long description is truncated +- **WHEN** the JIRA issue has a description longer than 500 characters +- **THEN** the `details.description` value is truncated to 500 characters followed by `...` + +### Requirement: Fetch script preserves an existing `updates` section +If the target file already exists and contains an `updates` array, the fetch script SHALL overwrite only the `details` section and leave `updates` unchanged. + +If the file does not exist, the script creates it with only a `details` section (no `updates` key). + +#### Scenario: Existing `updates` are not clobbered +- **WHEN** `.jira/PDCL-1234-my-feature.yml` already exists with two entries in `updates` +- **THEN** after running fetch, the file still has those two `updates` entries unchanged, with a refreshed `details` section + +#### Scenario: New file created with only `details` +- **WHEN** no file exists at the given filename path +- **THEN** the script creates the file containing only a `details` section + +### Requirement: Fetch script supports a `--dry-run` flag +When `--dry-run` is passed, the script SHALL print the computed JIRA API URL and the YAML that would be written, without writing any files or making HTTP requests. + +#### Scenario: Dry run prints planned output +- **WHEN** `node scripts/jira/fetch.mjs --dry-run PDCL-1234 .jira/PDCL-1234-foo.yml` is run +- **THEN** the target path and YAML content are printed to stdout and nothing is written + +### Requirement: Fetch script requires `JIRA_API_TOKEN` from the environment +The fetch script SHALL read the bearer token from `JIRA_API_TOKEN`. If absent, it SHALL print `"JIRA_API_TOKEN is required"` and exit with code 1. + +#### Scenario: Missing token causes early exit +- **WHEN** `JIRA_API_TOKEN` is not set +- **THEN** the script exits with code 1 before making any HTTP request diff --git a/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md b/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md new file mode 100644 index 000000000..c9f4cc380 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md @@ -0,0 +1,75 @@ +## ADDED Requirements + +### Requirement: `/jira-propose` creates or updates a `.jira/` YAML file locally without calling JIRA +The `/jira-propose` Claude Code slash command SHALL operate entirely locally. It SHALL NOT make any calls to the JIRA REST API. All information used to populate a new ticket file comes from git state, chat context, and existing `.jira/` files. + +#### Scenario: Propose runs without JIRA credentials +- **WHEN** a developer runs `/jira-propose` with no `JIRA_API_TOKEN` set +- **THEN** the command completes successfully and writes a `.jira/` YAML file + +### Requirement: `/jira-propose` searches existing `.jira/` files for a matching ticket +When invoked, `/jira-propose` SHALL scan all `.jira/*.yml` files and compare their content (filename slug, `details.summary` if present) against the current git changes and chat context. If a suitable match is found, the command SHALL update the existing file. If no match is found, the command SHALL create a new `PDCL-XXXX-.yml` file. + +#### Scenario: Matching ticket found +- **WHEN** an existing `.jira/PDCL-1234-my-feature.yml` matches the current changes +- **THEN** `/jira-propose` updates that file's `updates` section rather than creating a new file + +#### Scenario: No matching ticket found +- **WHEN** no existing `.jira/` file matches the current changes +- **THEN** `/jira-propose` creates a new `PDCL-XXXX-.yml` with an `updates` array containing a create-ticket REST call + +### Requirement: `/jira-propose` uses current git changes and chat context to populate the ticket +`/jira-propose` SHALL inspect: +- The current git diff (staged and unstaged changes) to infer what changed +- Recent commit messages on the branch +- Chat context provided by the user in the invocation or recent conversation + +From this context it SHALL populate: +- `summary` (required): a concise one-line ticket title +- `description` (optional): a paragraph describing the change and motivation +- `issuetype`: defaulting to `story` (id `7`) unless the change is clearly a bug fix +- `components`: `[{ id: "155901" }]` (AEP Web SDK, matching existing defaults) +- `customfield_23300`: `{ id: "116005" }` (product field, matching existing defaults) + +#### Scenario: Summary derived from commit messages +- **WHEN** the branch has commit messages describing a feature +- **THEN** the proposed ticket's `summary` reflects those commit messages + +#### Scenario: Issue type defaults to story +- **WHEN** the change does not appear to be a bug fix +- **THEN** the proposed ticket uses `issuetype: { id: "7" }` (story) + +#### Scenario: Issue type set to bug for fix changes +- **WHEN** commit messages or diff context indicate a bug fix +- **THEN** the proposed ticket uses `issuetype: { id: "1" }` (bug) + +### Requirement: New ticket `updates` array contains an idempotent create-ticket call as the first entry +For new tickets, the first entry in `updates` SHALL be a `POST /rest/api/2/issue` call whose body uses `fields` (not `update`) to set all initial field values. This follows JIRA's create-issue API shape. + +The `summary`, `issuetype`, `project`, `components`, and `customfield_23300` fields SHALL always be present in the create body. The `description` field SHALL be included if non-empty. + +#### Scenario: Create call is first in updates array +- **WHEN** `/jira-propose` creates a new `PDCL-XXXX-*.yml` file +- **THEN** `updates[0]` is `{ path: "/rest/api/2/issue", method: "POST", body: { fields: { ... } } }` + +#### Scenario: Create body includes required fields +- **WHEN** the created file's first update is inspected +- **THEN** it contains `project`, `issuetype`, `summary`, `components`, and `customfield_23300` + +### Requirement: YAML output includes inline comments for custom field IDs +The YAML files written by `/jira-propose` SHALL include inline comments explaining custom field IDs, matching the pattern used in `scripts/team/api.js`. + +Specifically: +- `customfield_23300` SHALL have the comment `# AEP Web SDK product field` +- Component IDs SHALL have comments identifying the component name (e.g. `# AEP Web SDK`, `# Documentation`) + +#### Scenario: Custom field comment present in output +- **WHEN** `/jira-propose` writes a new ticket file +- **THEN** `customfield_23300` has an adjacent YAML comment identifying it + +### Requirement: `/jira-propose` is implemented as a Claude Code skill in `.claude/commands/` +The action SHALL be implemented as a markdown skill file at `.claude/commands/jira-propose.md`, following the same pattern as other skills in the project (e.g. `pr-sync`, `jira-propose`). + +#### Scenario: Skill is available in Claude Code +- **WHEN** a developer types `/jira-propose` in a Claude Code session +- **THEN** Claude Code loads and executes the skill from `.claude/commands/jira-propose.md` diff --git a/openspec/changes/github-jira-yaml-workflow/specs/jira-yaml-schema/spec.md b/openspec/changes/github-jira-yaml-workflow/specs/jira-yaml-schema/spec.md new file mode 100644 index 000000000..e5516e6a6 --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/specs/jira-yaml-schema/spec.md @@ -0,0 +1,63 @@ +## ADDED Requirements + +### Requirement: Ticket files live in `.jira/` with a defined naming convention +All JIRA ticket files SHALL be stored in a `.jira/` directory at the repository root. + +Existing ticket files SHALL be named `{PROJECT}-{TICKET#}-{short-title}.yml` (e.g. `PDCL-1234-support-for-adcloud.yml`). + +New tickets not yet created in JIRA SHALL be named `{PROJECT}-XXXX-{short-description}.yml` (e.g. `PDCL-XXXX-add-identity-map-support.yml`). The `XXXX` sentinel signals that no real ticket key has been assigned yet. + +Short titles and descriptions SHALL use kebab-case and be 3–6 words. + +#### Scenario: Existing ticket file naming +- **WHEN** a developer creates a `.jira/` file for an existing JIRA ticket `PDCL-1234` +- **THEN** the file is named `PDCL-1234-.yml` and resides at `.jira/PDCL-1234-.yml` + +#### Scenario: New ticket file naming +- **WHEN** a developer creates a `.jira/` file for a ticket not yet in JIRA +- **THEN** the file is named `PDCL-XXXX-.yml` with the `XXXX` sentinel + +### Requirement: YAML file structure with `details` and `updates` sections +Each ticket file SHALL be valid YAML. The file MAY contain two top-level keys: `details` and `updates`. + +`details` SHALL contain a snapshot of the ticket's current non-null fields as they appear in JIRA, with long string values truncated to 500 characters followed by `...`. The `details` section is for human reference only and SHALL NOT be applied to JIRA by the apply script. + +`updates` SHALL be an ordered array of REST call objects. Each object SHALL have the fields: +- `path` (string): JIRA REST API path, e.g. `/rest/api/2/issue/PDCL-1234` +- `method` (string): HTTP method, e.g. `PUT`, `POST` +- `body` (object): Request body; YAML object converted to JSON before sending + +For new tickets (XXXX), the `details` key SHALL be absent. +For existing tickets with no pending changes, the `updates` key SHALL be absent. + +YAML comments (`#`) SHALL be used freely to document custom field IDs and their meanings. + +#### Scenario: File for existing ticket with updates +- **WHEN** a file `PDCL-1234-my-feature.yml` is opened +- **THEN** it contains a `details` map with current ticket fields and an `updates` array with REST call objects + +#### Scenario: File for new ticket +- **WHEN** a file `PDCL-XXXX-new-feature.yml` is opened +- **THEN** it contains only an `updates` array (no `details` key); the first update is a POST to create the ticket + +#### Scenario: File for existing ticket with no changes +- **WHEN** a file `PDCL-5678-reference-only.yml` is opened +- **THEN** it contains only a `details` map and no `updates` key + +### Requirement: `updates` entries use idempotent `set` operations +All field updates within `updates[*].body` SHALL use the JIRA `update` object with `set` operations, never `add` or `remove`, so that re-applying the same file produces the same JIRA state. + +#### Scenario: Field update is idempotent +- **WHEN** the apply script sends the same `updates` array twice to JIRA +- **THEN** the JIRA ticket state after both runs is identical and no duplicate data is created + +#### Scenario: Correct update body structure +- **WHEN** a developer writes an update to change the `status` field +- **THEN** the body uses `{ "update": { "fieldName": [{ "set": }] } }` or the equivalent direct PUT payload — never `add`/`remove` operations + +### Requirement: YAML bodies are converted to JSON before sending to JIRA +The apply script SHALL parse each `updates[*].body` as a YAML object and serialize it to JSON before including it in the HTTP request body. + +#### Scenario: YAML comments do not appear in JSON output +- **WHEN** a YAML body contains inline comments (e.g. `# AEP Web SDK product field`) +- **THEN** the JSON payload sent to JIRA contains no comment text diff --git a/openspec/changes/github-jira-yaml-workflow/tasks.md b/openspec/changes/github-jira-yaml-workflow/tasks.md new file mode 100644 index 000000000..56a66f86f --- /dev/null +++ b/openspec/changes/github-jira-yaml-workflow/tasks.md @@ -0,0 +1,45 @@ +## 1. Scaffold `.jira/` Directory and Schema + +- [ ] 1.1 Create `.jira/` directory with a `.gitkeep` file +- [ ] 1.2 Write a `.jira/README.md` documenting the file naming convention, YAML schema (`details` / `updates`), and custom field reference (component IDs, issue type IDs, `customfield_23300`) +- [ ] 1.3 Add `.jira/*.yml` to `.gitignore` exclusions if needed (confirm it should be tracked) + +## 2. Fetch Script (`scripts/jira/fetch.mjs`) + +- [ ] 2.1 Create `scripts/jira/fetch.mjs` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard +- [ ] 2.2 Implement `GET /rest/api/2/issue/{key}` call; extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` +- [ ] 2.3 Implement file write logic: if file exists, replace only the `details` section and preserve `updates`; if new, create file with only `details` plus `# fetched from JIRA ` comment +- [ ] 2.4 Add `--dry-run` output: print target path and YAML content without writing or fetching + +## 3. Apply Script (`scripts/jira/apply.mjs`) + +- [ ] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE` env-var validation (required only when `updates` is non-empty) +- [ ] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, run the idempotency check (search all issues for a remote link matching `GITHUB_PR_URL`, handle pagination) to get the real key +- [ ] 3.3 If the file has no `updates` or an empty array: print the resolved ticket key to stdout and exit 0 with no API calls +- [ ] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx +- [ ] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `GITHUB_PR_URL` and `GITHUB_PR_TITLE`; skip if the URL is already linked +- [ ] 3.6 Print the resolved ticket key as the final stdout line (e.g. `PDCL-1234`) +- [ ] 3.7 Add `--dry-run` output: print planned API calls and the resolved key without making HTTP requests +- [ ] 3.8 Test locally against a real PDCL ticket using `--dry-run` + +## 4. Build Workflow Integration (`.github/workflows/version-and-publish.yml`) + +- [ ] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main` with no `needs` dependency on the changeset gate; use `Production` environment for `JIRA_API_TOKEN` access +- [ ] 4.2 Add step to extract `GITHUB_PR_URL` and `GITHUB_PR_TITLE` from the push event's associated PR via `GITHUB_EVENT_PATH` (the `head_commit` or via `gh pr list --merged`) +- [ ] 4.3 Add step to detect changed `.jira/*.yml` files via `git diff HEAD^1 HEAD --name-only -- '.jira/*.yml'`; skip remaining steps if none +- [ ] 4.4 Add loop step: for each changed file, run `node scripts/jira/apply.mjs `, capture the printed ticket key, then run `node scripts/jira/fetch.mjs ` +- [ ] 4.5 Add step to commit any updated `.jira/` files back to `main` with message `chore: refresh JIRA details [skip ci]` (skip commit if no changes) + +## 5. `/jira-propose` Claude Code Skill + +- [ ] 5.1 Create `.claude/commands/jira-propose.md` skill file with instructions for the propose action +- [ ] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages +- [ ] 5.3 Implement new-ticket YAML generation: populate `summary`, `description`, `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields +- [ ] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file +- [ ] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix + +## 6. Cleanup and Documentation + +- [ ] 6.1 Move `scripts/createJiraTicket.js` to `scripts/legacy/createJiraTicket.js` (or delete if team confirms it was never used) +- [ ] 6.2 Update `CLAUDE.md` (or project README) with the new `.jira/` workflow: how to propose, fetch, and apply; how the build integration works +- [ ] 6.3 Verify the `JIRA_API_TOKEN` secret is available in the `Production` GitHub Actions environment From 64ab057f289a5951f6938652e08e4344ff6043f1 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 10:58:08 -0600 Subject: [PATCH 02/10] feat: address PR review feedback on github-jira-yaml-workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Workflow: loop runs apply→delete→fetch per changed file (not update-in-place) - Use repo-{PR#} as remote link global ID for reliable JIRA indexing; no pagination needed - XXXX files deleted and replaced by real-key files after apply succeeds - fetch.mjs requires both key AND filename as required args - Apply script exits 0 for no-updates files (triggering delete+fetch) - Details section refreshed by build workflow via fetch, not read-only - JIRA/changeset changes land in a single skip-ci commit - Skill path: .claude/skills/jira-propose/SKILL.md (not commands/) - Add quality gate: PRs must have a .jira/ YAML file - Add PR comment step after apply listing updated tickets - Propose description includes business value (customer names, elevator pitch) - fetch can read any JIRA project; PDCL creation only restriction - Resolved open questions; removed stale risks --- .../github-jira-yaml-workflow/design.md | 45 +++++++++---------- .../github-jira-yaml-workflow/proposal.md | 11 ++--- .../specs/jira-propose-action/spec.md | 12 +++-- .../github-jira-yaml-workflow/tasks.md | 45 ++++++++++--------- 4 files changed, 60 insertions(+), 53 deletions(-) diff --git a/openspec/changes/github-jira-yaml-workflow/design.md b/openspec/changes/github-jira-yaml-workflow/design.md index 52a614527..9d3d3ff54 100644 --- a/openspec/changes/github-jira-yaml-workflow/design.md +++ b/openspec/changes/github-jira-yaml-workflow/design.md @@ -19,11 +19,12 @@ Custom field IDs used in the PDCL project: - Local authoring (propose) makes zero JIRA API calls - YAML files are human-readable and support inline comments for custom field documentation - Remote link to the merged PR is always created in JIRA as part of apply +- PR review is the approval mechanism for JIRA changes — `/jira-propose` writes files locally with no external effect, so developers can write ticket files freely without prior sign-off **Non-Goals:** - Real-time JIRA → repo sync (the `details` snapshot is a one-time capture, not kept live) - Automated backfill of historical tickets -- Support for JIRA projects other than PDCL (config is project-key-aware but multi-project support is not in scope) +- Creating tickets in JIRA projects other than PDCL (fetch can read any project key; only PDCL ticket creation is supported by apply) - Replacing the JIRA UI for complex ticket authoring (descriptions, attachments, etc.) ## Decisions @@ -39,16 +40,16 @@ Custom field IDs used in the PDCL project: **Idempotency**: All `body.update` payloads use `set` operations, never `add`/`remove`. The apply script skips updates when the remote link already exists (checked before applying). ### Remote link as idempotency key for new tickets -**Decision**: Before creating a new ticket (`PDCL-XXXX-*.yml`), the apply script searches JIRA for any issue in the project with a remote link whose URL matches the PR URL. If found, the ticket already exists and creation is skipped. -**Rationale**: `PDCL-XXXX` files have no real ticket key yet, so we need an external signal. GitHub PR URLs are stable and unique — a perfect idempotency key. +**Decision**: Before creating a new ticket (`PDCL-XXXX-*.yml`), the apply script searches JIRA for any issue in the project whose remote links include one with global ID `repo-{PR#}` (e.g. `repo-1553`). No pagination is needed — a single search suffices. If any match is found, creation is skipped and the found ticket key is returned. Apply exits 0 in either case, so the workflow continues with the delete-and-fetch step. +**Rationale**: Using `repo-{PR#}` as the global ID gives JIRA a stable, indexed identifier that is more reliably searchable than a full URL. If the build fails mid-step and re-runs, apply again finds the link and returns the key; the XXXX file is re-deleted and fetch re-creates the real-key file — fully idempotent. -### `details` section is read-only metadata -**Decision**: The `details` section is a snapshot captured at propose time (or manually). The apply script ignores it entirely. -**Rationale**: Prevents accidental JIRA drift if `details` gets stale. Updates are always expressed explicitly in `updates`. +### `details` section is read-only metadata; refreshed by the build workflow +**Decision**: The `details` section is a read-only snapshot — the apply script ignores it entirely. After apply runs successfully, the build workflow deletes the file and calls fetch to regenerate `details` from live JIRA state, producing a fresh file with the real ticket key in the filename. +**Rationale**: Prevents accidental JIRA drift from a stale snapshot. The post-apply fetch ensures `details` always reflects the true JIRA state after the updates have landed. ### New ticket file naming with `XXXX` sentinel -**Decision**: Unsubmitted tickets use `PDCL-XXXX-short-description.yml`. After the apply workflow creates the ticket, the file is NOT automatically renamed (the real key appears in the JIRA remote link and in the workflow output log). -**Rationale**: Renaming requires a follow-up commit; accepting a slightly stale filename is simpler and avoids merge conflicts. Teams can manually rename as a housekeeping step. +**Decision**: Unsubmitted tickets use `PDCL-XXXX-short-description.yml`. After apply creates the ticket (or finds an existing one via the remote-link check), the build workflow deletes the XXXX file and calls `fetch.mjs ` to create a properly-named file (e.g. `PDCL-1234-short-description.yml`) with populated `details`. +**Rationale**: Deleting the XXXX file and creating a named file in a single skip-ci commit is idempotent: if the build fails and re-runs, apply finds the remote link, exits 0, and the delete+fetch sequence completes cleanly. ### Local `/jira-propose` makes zero JIRA calls **Decision**: The propose action only reads `.jira/` files and git state. It never calls the JIRA API. @@ -59,8 +60,8 @@ Custom field IDs used in the PDCL project: **Rationale**: Keeps CI logic in the same `scripts/` tree as the existing JIRA helpers, enabling code reuse from `scripts/team/config.js`. ### Fetch script design -**Decision**: `fetch.mjs` accepts a ticket key (e.g. `PDCL-1234`) or a `.jira/` filename, calls JIRA's `GET /rest/api/2/issue/{key}` endpoint, and writes (or updates) a `.jira/{key}-{slug}.yml` file. The slug is derived from the ticket summary. If the file already exists, only the `details` section is replaced; any `updates` array is preserved. -**Rationale**: Lets developers bootstrap the `details` snapshot from a real ticket without copy-pasting from the JIRA UI. Can also be run in CI before apply to capture a before-snapshot for audit logs. +**Decision**: `fetch.mjs` requires exactly two arguments: `` and ``. Both are required. It calls JIRA's `GET /rest/api/2/issue/{key}` endpoint and writes (or overwrites) the file at the given path with a fresh `details` section; any existing `updates` array is preserved. +**Rationale**: Keeping key and filename independent lets the build workflow substitute the real ticket number for XXXX in the filename, and lets LLMs or developers control naming. The script stays deterministic given the same inputs. Fetch can read any JIRA project (not limited to PDCL) since it is read-only. ### No separate JIRA workflow file **Decision**: Integrate the `apply-jira` job into the existing `.github/workflows/version-and-publish.yml`. @@ -68,26 +69,24 @@ Custom field IDs used in the PDCL project: ## Risks / Trade-offs -- **Stale `details` snapshot** → Mitigation: `details` is advisory only; apply ignores it. Document this clearly in schema comments. -- **XXXX files never renamed** → Mitigation: Workflow output logs the real ticket key. A future housekeeping script can rename files post-merge. -- **JIRA API pagination on remote-link search** → Mitigation: Apply script iterates all pages when searching for an existing remote link before creating a new ticket. -- **PAT expiry breaks apply workflow** → Mitigation: Workflow fails loudly with a clear error; no partial state written. Token rotation is an ops concern (existing pattern for `JIRA_API_TOKEN` secret). -- **Concurrent PRs both creating the same PDCL-XXXX ticket** → Mitigation: Remote-link idempotency check handles this — whichever workflow runs second finds the link and skips creation. +- **Build dies between apply and commit** → Mitigation: Idempotent by design — re-run finds the remote link, deletes the XXXX file again (or finds it already gone), and re-creates the real-key file via fetch. Git commit is a no-op if files haven't changed. +- **PAT expiry breaks apply workflow** → Mitigation: Workflow fails loudly with a clear error; no partial JIRA state written. Token rotation follows the existing `JIRA_API_TOKEN` ops pattern. - **Large JIRA body fields (description)** → Mitigation: `details` snapshot truncates long string fields (> 500 chars) with a `...` suffix; full content lives in JIRA. +- **XXXX files from different PRs collide** → Each PR that creates a new ticket produces a distinct JIRA ticket with a distinct key. Concurrent XXXX files on concurrent PRs are fine — they will each create their own ticket once merged. ## Migration Plan -1. Add `.jira/` directory with a `.gitkeep` +1. Add `.jira/` directory with a `.gitkeep` and README 2. Add `scripts/jira/fetch.mjs` — test locally against a real PDCL ticket with `--dry-run` 3. Add `scripts/jira/apply.mjs` — test locally with `--dry-run` -4. Add `apply-jira` job to `version-and-publish.yml` referencing `JIRA_API_TOKEN` secret -5. Add `.claude/commands/jira-propose.md` skill -6. Remove (or archive to `scripts/legacy/`) `scripts/createJiraTicket.js` — the `scripts/team/` helpers are retained as shared utilities -7. Update `CLAUDE.md` / team docs with the new workflow +4. Add `apply-jira` job to `version-and-publish.yml`; coordinate its file additions/deletions with the existing changeset skip-ci commit so a single commit covers both; add `JIRA_API_TOKEN` secret to the `Production` environment +5. Add quality gate to `quality-checks.yml` verifying each PR has at least one `.jira/` YAML file +6. Add `.claude/skills/jira-propose/SKILL.md` +7. Create or update `CLAUDE.md` and the project README with the full workflow Rollback: Remove the `apply-jira` job from the workflow. YAML files in `.jira/` are inert without the job. -## Open Questions +## Resolved Questions -- Should the apply workflow post a PR comment with JIRA links after applying? (Nice-to-have; out of scope for v1) -- Should `details` be populated automatically by a fetch script when `/jira-propose` is run against an existing ticket key? (Deferred; requires JIRA auth locally) +- **Should the apply workflow post a PR comment with JIRA links after applying?** Yes — add a step that posts a PR comment listing the JIRA tickets that were created or updated. +- **Should `details` be populated automatically by a fetch script when `/jira-propose` is run?** No — `/jira-propose` works locally only and assumes local ticket files are up-to-date. Developers run fetch manually if they need to refresh `details`. diff --git a/openspec/changes/github-jira-yaml-workflow/proposal.md b/openspec/changes/github-jira-yaml-workflow/proposal.md index 7af2881d1..876b03e0e 100644 --- a/openspec/changes/github-jira-yaml-workflow/proposal.md +++ b/openspec/changes/github-jira-yaml-workflow/proposal.md @@ -10,9 +10,9 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - `details` — snapshot of the ticket's current non-null fields (read-only reference; not applied to JIRA) - `updates` — ordered array of idempotent REST calls (`path`, `method`, `body`) to apply when the PR merges - YAML is used (not JSON) so inline comments can document custom field IDs (e.g. `customfield_23300`) -- The existing build workflow (`version-and-publish.yml`) gains a new `apply-jira` job that runs on every push to `main`; it detects which `.jira/*.yml` files changed in the merge, then for each file runs `apply.mjs` → captures the returned ticket key → runs `fetch.mjs` to refresh `details` → commits the updated files back to `main` -- `scripts/jira/apply.mjs ` applies that file's `updates` to JIRA, creates a remote link to the PR, and prints the resolved ticket key (e.g. `PDCL-1234`) to stdout; the remote link doubles as the idempotency key for new ticket creation -- New tickets use `PDCL-XXXX-...` sentinel names; the apply script searches for an existing remote link matching the PR URL before creating, ensuring idempotency if the job re-runs +- The existing build workflow (`version-and-publish.yml`) gains a new `apply-jira` job: for each changed `.jira/*.yml` file that has an `updates` section, it runs `apply.mjs` → on success, deletes the file → runs `fetch.mjs` to create a fresh file at the real-key filename; all `.jira/` additions/deletions are committed in a single skip-ci commit alongside any changeset version bump +- `scripts/jira/apply.mjs ` applies that file's `updates` to JIRA, creates a remote link to the PR (using `repo-{PR#}` as the remote link's global ID for reliable JIRA indexing), and prints the resolved ticket key (e.g. `PDCL-1234`) to stdout +- New tickets use `PDCL-XXXX-...` sentinel names; before creating, apply checks whether any JIRA issue already has a remote link with global ID `repo-{PR#}`; if found, the existing key is returned (no new ticket created); in either case the XXXX file is deleted and replaced by a real-key file via fetch - `scripts/jira/fetch.mjs ` fetches the current JIRA state for `` and writes it into the `details` section of ``, preserving any existing `updates` array; both arguments are required - A new `/jira-propose` Claude Code action inspects current git changes and chat context, searches `.jira/` for a matching ticket file, and creates one locally if none exists — **no JIRA API calls are made locally** - Existing `scripts/createJiraTicket.js` and related scripts are superseded and will be removed; their field/template knowledge (project key, component IDs, custom fields) is migrated into the YAML schema and helper scripts @@ -34,5 +34,6 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - `.github/workflows/version-and-publish.yml` gains a new `apply-jira` job; no new workflow file is created - New `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` Node.js scripts; both reuse `scripts/team/config.js` for base URL and project key - Existing `scripts/createJiraTicket.js`, `scripts/openPr.js` JIRA fetch logic, and `scripts/team/` helpers referenced but some superseded -- New `.claude/commands/jira-propose.md` skill definition -- `JIRA_API_TOKEN` secret must be available in the GitHub Actions `Production` environment (already used by existing workflows) +- New `.claude/skills/jira-propose/SKILL.md` skill definition (skills can be invoked by the agent automatically; commands cannot) +- A new quality gate in `.github/workflows/quality-checks.yml` verifies that every open PR has at least one `.jira/` YAML file, ensuring JIRA traceability for all changes +- `JIRA_API_TOKEN` secret will be added to the GitHub Actions `Production` environment diff --git a/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md b/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md index c9f4cc380..5cebc1c7c 100644 --- a/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md +++ b/openspec/changes/github-jira-yaml-workflow/specs/jira-propose-action/spec.md @@ -26,7 +26,7 @@ When invoked, `/jira-propose` SHALL scan all `.jira/*.yml` files and compare the From this context it SHALL populate: - `summary` (required): a concise one-line ticket title -- `description` (optional): a paragraph describing the change and motivation +- `description` (optional): a paragraph describing the change and motivation, including business value — customer names, who benefits, why it matters, and the elevator-pitch value statement - `issuetype`: defaulting to `story` (id `7`) unless the change is clearly a bug fix - `components`: `[{ id: "155901" }]` (AEP Web SDK, matching existing defaults) - `customfield_23300`: `{ id: "116005" }` (product field, matching existing defaults) @@ -67,9 +67,13 @@ Specifically: - **WHEN** `/jira-propose` writes a new ticket file - **THEN** `customfield_23300` has an adjacent YAML comment identifying it -### Requirement: `/jira-propose` is implemented as a Claude Code skill in `.claude/commands/` -The action SHALL be implemented as a markdown skill file at `.claude/commands/jira-propose.md`, following the same pattern as other skills in the project (e.g. `pr-sync`, `jira-propose`). +### Requirement: `/jira-propose` is implemented as a Claude Code skill in `.claude/skills/jira-propose/` +The action SHALL be implemented as a markdown skill file at `.claude/skills/jira-propose/SKILL.md`. Skills (unlike commands) can be invoked automatically by the agent in addition to being invoked manually by the developer. #### Scenario: Skill is available in Claude Code - **WHEN** a developer types `/jira-propose` in a Claude Code session -- **THEN** Claude Code loads and executes the skill from `.claude/commands/jira-propose.md` +- **THEN** Claude Code loads and executes the skill from `.claude/skills/jira-propose/SKILL.md` + +#### Scenario: Skill can be invoked automatically by the agent +- **WHEN** the Claude Code agent determines that a JIRA ticket file should be created or updated +- **THEN** the agent can invoke the skill without explicit developer input diff --git a/openspec/changes/github-jira-yaml-workflow/tasks.md b/openspec/changes/github-jira-yaml-workflow/tasks.md index 56a66f86f..99db14d4b 100644 --- a/openspec/changes/github-jira-yaml-workflow/tasks.md +++ b/openspec/changes/github-jira-yaml-workflow/tasks.md @@ -1,45 +1,48 @@ ## 1. Scaffold `.jira/` Directory and Schema -- [ ] 1.1 Create `.jira/` directory with a `.gitkeep` file -- [ ] 1.2 Write a `.jira/README.md` documenting the file naming convention, YAML schema (`details` / `updates`), and custom field reference (component IDs, issue type IDs, `customfield_23300`) -- [ ] 1.3 Add `.jira/*.yml` to `.gitignore` exclusions if needed (confirm it should be tracked) +- [ ] 1.1 Create `.jira/` directory with a `.gitkeep` file; JIRA YAML files are tracked in version control +- [ ] 1.2 Write a `.jira/README.md` documenting: file naming convention, YAML schema (`details` / `updates`), custom field reference (component IDs, issue type IDs, `customfield_23300`), and the expected end-to-end flow (propose skill → PR review → apply script → fetch script → build workflow commit) ## 2. Fetch Script (`scripts/jira/fetch.mjs`) - [ ] 2.1 Create `scripts/jira/fetch.mjs` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard -- [ ] 2.2 Implement `GET /rest/api/2/issue/{key}` call; extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` +- [ ] 2.2 Implement `GET /rest/api/2/issue/{key}` call (supports any JIRA project, not limited to PDCL); extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` - [ ] 2.3 Implement file write logic: if file exists, replace only the `details` section and preserve `updates`; if new, create file with only `details` plus `# fetched from JIRA ` comment - [ ] 2.4 Add `--dry-run` output: print target path and YAML content without writing or fetching ## 3. Apply Script (`scripts/jira/apply.mjs`) -- [ ] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE` env-var validation (required only when `updates` is non-empty) -- [ ] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, run the idempotency check (search all issues for a remote link matching `GITHUB_PR_URL`, handle pagination) to get the real key +- [ ] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE`/`GITHUB_PR_NUMBER` env-var validation (required only when `updates` is non-empty) +- [ ] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, search JIRA for any issue with a remote link whose global ID is `repo-{PR#}` (no pagination — a single search hit is sufficient); if found, use that ticket key and exit 0; if not found, proceed to create - [ ] 3.3 If the file has no `updates` or an empty array: print the resolved ticket key to stdout and exit 0 with no API calls - [ ] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx -- [ ] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `GITHUB_PR_URL` and `GITHUB_PR_TITLE`; skip if the URL is already linked +- [ ] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `url`, `title`, and `globalId: "repo-{PR#}"`; skip if global ID is already linked - [ ] 3.6 Print the resolved ticket key as the final stdout line (e.g. `PDCL-1234`) - [ ] 3.7 Add `--dry-run` output: print planned API calls and the resolved key without making HTTP requests - [ ] 3.8 Test locally against a real PDCL ticket using `--dry-run` ## 4. Build Workflow Integration (`.github/workflows/version-and-publish.yml`) -- [ ] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main` with no `needs` dependency on the changeset gate; use `Production` environment for `JIRA_API_TOKEN` access -- [ ] 4.2 Add step to extract `GITHUB_PR_URL` and `GITHUB_PR_TITLE` from the push event's associated PR via `GITHUB_EVENT_PATH` (the `head_commit` or via `gh pr list --merged`) +- [ ] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main`; use `Production` environment for `JIRA_API_TOKEN` access +- [ ] 4.2 Add step to extract `GITHUB_PR_NUMBER`, `GITHUB_PR_URL`, and `GITHUB_PR_TITLE` from the push event's associated PR via `gh pr list --merged` - [ ] 4.3 Add step to detect changed `.jira/*.yml` files via `git diff HEAD^1 HEAD --name-only -- '.jira/*.yml'`; skip remaining steps if none -- [ ] 4.4 Add loop step: for each changed file, run `node scripts/jira/apply.mjs `, capture the printed ticket key, then run `node scripts/jira/fetch.mjs ` -- [ ] 4.5 Add step to commit any updated `.jira/` files back to `main` with message `chore: refresh JIRA details [skip ci]` (skip commit if no changes) +- [ ] 4.4 Add loop step: for each changed file that has an `updates` section, run `node scripts/jira/apply.mjs `, capture the printed ticket key; on success, delete the file, derive the new real-key filename (replace `XXXX` with the ticket number), and run `node scripts/jira/fetch.mjs ` +- [ ] 4.5 Add a step after apply-jira that posts a PR comment listing all JIRA tickets created or updated (using `gh pr comment`) +- [ ] 4.6 Combine the `.jira/` file additions/deletions with any changeset version-bump changes into a single skip-ci commit; add this as a job step with appropriate `needs` dependencies so JIRA and changeset changes land together -## 5. `/jira-propose` Claude Code Skill +## 5. Quality Gate (`.github/workflows/quality-checks.yml`) -- [ ] 5.1 Create `.claude/commands/jira-propose.md` skill file with instructions for the propose action -- [ ] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages -- [ ] 5.3 Implement new-ticket YAML generation: populate `summary`, `description`, `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields -- [ ] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file -- [ ] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix +- [ ] 5.1 Add a check to `quality-checks.yml` that verifies every open PR has at least one `.jira/*.yml` file; fail the check if none are present -## 6. Cleanup and Documentation +## 6. `/jira-propose` Claude Code Skill -- [ ] 6.1 Move `scripts/createJiraTicket.js` to `scripts/legacy/createJiraTicket.js` (or delete if team confirms it was never used) -- [ ] 6.2 Update `CLAUDE.md` (or project README) with the new `.jira/` workflow: how to propose, fetch, and apply; how the build integration works -- [ ] 6.3 Verify the `JIRA_API_TOKEN` secret is available in the `Production` GitHub Actions environment +- [ ] 6.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) +- [ ] 6.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages +- [ ] 6.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields +- [ ] 6.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file +- [ ] 6.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix + +## 7. Cleanup and Documentation + +- [ ] 7.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes +- [ ] 7.2 Add `JIRA_API_TOKEN` secret to the `Production` GitHub Actions environment From 31c4ac9f19a91678f00d3fd7dbbbe425b8141694 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 11:08:05 -0600 Subject: [PATCH 03/10] chore: remove PR JIRA ticket requirement (separate change) --- .../github-jira-yaml-workflow/design.md | 5 ++--- .../github-jira-yaml-workflow/proposal.md | 1 - .../github-jira-yaml-workflow/tasks.md | 22 ++++++++----------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/openspec/changes/github-jira-yaml-workflow/design.md b/openspec/changes/github-jira-yaml-workflow/design.md index 9d3d3ff54..e35840300 100644 --- a/openspec/changes/github-jira-yaml-workflow/design.md +++ b/openspec/changes/github-jira-yaml-workflow/design.md @@ -80,9 +80,8 @@ Custom field IDs used in the PDCL project: 2. Add `scripts/jira/fetch.mjs` — test locally against a real PDCL ticket with `--dry-run` 3. Add `scripts/jira/apply.mjs` — test locally with `--dry-run` 4. Add `apply-jira` job to `version-and-publish.yml`; coordinate its file additions/deletions with the existing changeset skip-ci commit so a single commit covers both; add `JIRA_API_TOKEN` secret to the `Production` environment -5. Add quality gate to `quality-checks.yml` verifying each PR has at least one `.jira/` YAML file -6. Add `.claude/skills/jira-propose/SKILL.md` -7. Create or update `CLAUDE.md` and the project README with the full workflow +5. Add `.claude/skills/jira-propose/SKILL.md` +6. Create or update `CLAUDE.md` and the project README with the full workflow Rollback: Remove the `apply-jira` job from the workflow. YAML files in `.jira/` are inert without the job. diff --git a/openspec/changes/github-jira-yaml-workflow/proposal.md b/openspec/changes/github-jira-yaml-workflow/proposal.md index 876b03e0e..6eb3a6535 100644 --- a/openspec/changes/github-jira-yaml-workflow/proposal.md +++ b/openspec/changes/github-jira-yaml-workflow/proposal.md @@ -35,5 +35,4 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - New `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` Node.js scripts; both reuse `scripts/team/config.js` for base URL and project key - Existing `scripts/createJiraTicket.js`, `scripts/openPr.js` JIRA fetch logic, and `scripts/team/` helpers referenced but some superseded - New `.claude/skills/jira-propose/SKILL.md` skill definition (skills can be invoked by the agent automatically; commands cannot) -- A new quality gate in `.github/workflows/quality-checks.yml` verifies that every open PR has at least one `.jira/` YAML file, ensuring JIRA traceability for all changes - `JIRA_API_TOKEN` secret will be added to the GitHub Actions `Production` environment diff --git a/openspec/changes/github-jira-yaml-workflow/tasks.md b/openspec/changes/github-jira-yaml-workflow/tasks.md index 99db14d4b..e61024b08 100644 --- a/openspec/changes/github-jira-yaml-workflow/tasks.md +++ b/openspec/changes/github-jira-yaml-workflow/tasks.md @@ -30,19 +30,15 @@ - [ ] 4.5 Add a step after apply-jira that posts a PR comment listing all JIRA tickets created or updated (using `gh pr comment`) - [ ] 4.6 Combine the `.jira/` file additions/deletions with any changeset version-bump changes into a single skip-ci commit; add this as a job step with appropriate `needs` dependencies so JIRA and changeset changes land together -## 5. Quality Gate (`.github/workflows/quality-checks.yml`) +## 5. `/jira-propose` Claude Code Skill -- [ ] 5.1 Add a check to `quality-checks.yml` that verifies every open PR has at least one `.jira/*.yml` file; fail the check if none are present +- [ ] 5.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) +- [ ] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages +- [ ] 5.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields +- [ ] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file +- [ ] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix -## 6. `/jira-propose` Claude Code Skill +## 6. Cleanup and Documentation -- [ ] 6.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) -- [ ] 6.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages -- [ ] 6.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields -- [ ] 6.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file -- [ ] 6.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix - -## 7. Cleanup and Documentation - -- [ ] 7.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes -- [ ] 7.2 Add `JIRA_API_TOKEN` secret to the `Production` GitHub Actions environment +- [ ] 6.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes +- [ ] 6.2 Add `JIRA_API_TOKEN` secret to the `Production` GitHub Actions environment From c3596d8dde23a4208abc5eb2ba792a245cbd1d06 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 11:20:07 -0600 Subject: [PATCH 04/10] feat: implement GitHub-based JIRA YAML workflow Adds the full system for version-controlling JIRA changes as YAML files in .jira/ and applying them automatically on merge to main. - .jira/.gitkeep + README.md with schema docs, custom field reference, and end-to-end workflow description - scripts/jira/fetch.mjs: fetches JIRA issue state into details section (two required args: ticket-key and filename; --dry-run supported) - scripts/jira/apply.mjs: executes updates[] array against JIRA REST API, creates remote link with globalId repo-{PR#} for idempotency, prints resolved ticket key to stdout (--dry-run supported) - .github/workflows/version-and-publish.yml: new apply-jira job runs on every push to main; detects changed .jira/*.yml files, runs apply then fetch on each, commits refreshed details, posts PR comment with ticket links; publish job now depends on apply-jira with git pull --rebase - .claude/skills/jira-propose/SKILL.md: skill for proposing ticket changes locally from git context, no JIRA API calls - CLAUDE.md: project guide with workflow, scripts, and custom field ref - README.md: added JIRA workflow section Task 6.2 (add JIRA_API_TOKEN to Production environment) requires manual action in GitHub repository settings. --- .claude/skills/jira-propose/SKILL.md | 126 ++++++++++ .github/workflows/version-and-publish.yml | 125 +++++++++- .jira/.gitkeep | 0 .jira/README.md | 98 ++++++++ CLAUDE.md | 45 ++++ README.md | 9 + .../github-jira-yaml-workflow/tasks.md | 52 ++-- scripts/jira/apply.mjs | 223 ++++++++++++++++++ scripts/jira/fetch.mjs | 140 +++++++++++ 9 files changed, 791 insertions(+), 27 deletions(-) create mode 100644 .claude/skills/jira-propose/SKILL.md create mode 100644 .jira/.gitkeep create mode 100644 .jira/README.md create mode 100644 CLAUDE.md create mode 100644 scripts/jira/apply.mjs create mode 100644 scripts/jira/fetch.mjs diff --git a/.claude/skills/jira-propose/SKILL.md b/.claude/skills/jira-propose/SKILL.md new file mode 100644 index 000000000..cd02ce6c3 --- /dev/null +++ b/.claude/skills/jira-propose/SKILL.md @@ -0,0 +1,126 @@ +# /jira-propose — Propose JIRA ticket changes locally + +Create or update a `.jira/*.yml` file to represent a JIRA ticket change. This skill operates **entirely locally** — no JIRA API calls are made. The resulting file is committed as part of a PR and applied to JIRA automatically when the PR merges. + +## When to invoke + +Invoke `/jira-propose` when: +- A feature, bug fix, or improvement is being built and should be tracked in JIRA +- An existing JIRA ticket needs updates (status, components, description, etc.) +- The user explicitly asks to propose a JIRA ticket for the current work + +## Steps + +### 1. Gather context + +Run these commands in parallel to understand the current work: + +```bash +git diff --stat HEAD +git log --oneline -10 +git branch --show-current +ls .jira/*.yml 2>/dev/null || echo "(no existing jira files)" +``` + +Also read any `.jira/*.yml` files that exist, to check for matches. + +### 2. Determine issue type + +Default to **story** (`id: "7"`). Use **bug** (`id: "1"`) when: +- Branch name contains `fix`, `bug`, `hotfix`, or `patch` +- Commit messages contain `fix:`, `bug:`, `fixes`, `closes`, or `regression` +- The diff clearly addresses a defect rather than adding capability + +### 3. Search for a matching existing ticket + +Check each `.jira/*.yml` file: +- Compare the filename slug against the branch name and commit messages +- Compare `details.summary` (if present) against the likely ticket title +- If a file matches the current work, **update it** (append to `updates` array) +- If no file matches, **create a new one** + +### 4a. New ticket — write `PDCL-XXXX-.yml` + +Generate a kebab-case short description (3–6 words) from the branch name and commits. + +Write `.jira/PDCL-XXXX-.yml` with this structure: + +```yaml +updates: + - path: /rest/api/2/issue + method: POST + body: + fields: + project: + key: PDCL + issuetype: + id: "7" # Story (use "1" for Bug, "14801" for Documentation) + summary: + description: | + + components: + - id: "155901" # AEP Web SDK + customfield_23300: # AEP Web SDK product field + id: "116005" +``` + +**Description guidelines:** +- Lead with who benefits (e.g., "Analytics customers using the Web SDK...") +- Explain the problem being solved +- State the business value / outcome (e.g., "This eliminates the need for manual re-configuration after...") +- Keep to 2–4 sentences + +### 4b. Existing ticket — update `updates` array + +When a matching file is found, append (or replace if same operation exists) to the `updates` array: + +```yaml +updates: + - path: /rest/api/2/issue/{key} + method: PUT + body: + update: + summary: + - set: + # Add other fields as needed; always use "set", never "add"/"remove" +``` + +Use `PUT /rest/api/2/issue/{key}` with `update.field[].set` for field changes. +Use `POST /rest/api/2/issue/{key}/transitions` for status transitions. + +### 5. Write the file + +- Place it in `.jira/` at the repo root +- Use YAML comments (`#`) to document custom field IDs inline +- Verify the YAML is valid before finishing + +### 6. Report back + +After writing the file, tell the user: +- The filename created or updated +- The ticket key (PDCL-XXXX for new, PDCL-NNNN for existing) +- The proposed summary +- What will happen when the PR merges (apply.mjs will execute the updates) + +## Reference: PDCL custom fields + +| Field | ID / value | +|-------|-----------| +| Project key | `PDCL` | +| AEP Web SDK component | `components[].id: "155901"` | +| Documentation component | `components[].id: "157512"` | +| Product field (`customfield_23300`) | `id: "116005"` | +| Story issue type | `issuetype.id: "7"` | +| Bug issue type | `issuetype.id: "1"` | +| Documentation issue type | `issuetype.id: "14801"` | +| JIRA base URL | `https://jira.corp.adobe.com` | + +## Constraints + +- **No JIRA API calls** — all information comes from git state, context, and existing `.jira/` files +- All `update` operations must use `set` (never `add`/`remove`) to ensure idempotency +- New tickets must have a `POST /rest/api/2/issue` as the first entry in `updates` +- File must be valid YAML +- Do not populate the `details` section — that is written by `fetch.mjs` after apply diff --git a/.github/workflows/version-and-publish.yml b/.github/workflows/version-and-publish.yml index 7d0640400..8eae9d409 100644 --- a/.github/workflows/version-and-publish.yml +++ b/.github/workflows/version-and-publish.yml @@ -10,6 +10,127 @@ concurrency: cancel-in-progress: false jobs: + # Applies any pending .jira/*.yml changes to JIRA on every push to main. + apply-jira: + runs-on: ubuntu-latest + environment: Production + permissions: + contents: write + pull-requests: write + env: + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 2 + ssh-key: ${{ secrets.ALLOY_BOT_GITHUB_SSH_PRIVATE_KEY }} + - uses: pnpm/action-setup@v6 + - uses: actions/setup-node@v5 + with: + node-version-file: .nvmrc + cache: pnpm + - run: pnpm install --frozen-lockfile + + - name: Detect changed .jira files + id: jira-files + run: | + changed=$(git diff HEAD^1 HEAD --name-only -- '.jira/*.yml' | tr '\n' ' ') + echo "files=$changed" >> "$GITHUB_OUTPUT" + if [ -n "$changed" ]; then + echo "has_changes=true" >> "$GITHUB_OUTPUT" + else + echo "has_changes=false" >> "$GITHUB_OUTPUT" + fi + + - name: Get PR context + id: pr-context + if: steps.jira-files.outputs.has_changes == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pr_info=$(gh pr list --state merged --base main --limit 5 --json number,url,title \ + --jq 'map(select(.number != null)) | first') + pr_number=$(echo "$pr_info" | jq -r '.number // ""') + pr_url=$(echo "$pr_info" | jq -r '.url // ""') + pr_title=$(echo "$pr_info" | jq -r '.title // ""') + echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT" + echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT" + echo "pr_title=$pr_title" >> "$GITHUB_OUTPUT" + + - name: Apply JIRA changes and fetch updated state + id: apply-jira + if: steps.jira-files.outputs.has_changes == 'true' + env: + GITHUB_PR_NUMBER: ${{ steps.pr-context.outputs.pr_number }} + GITHUB_PR_URL: ${{ steps.pr-context.outputs.pr_url }} + GITHUB_PR_TITLE: ${{ steps.pr-context.outputs.pr_title }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + applied_tickets="" + for file in ${{ steps.jira-files.outputs.files }}; do + [ -f "$file" ] || continue + + # Only process files with an updates section + has_updates=$(node -e " + import yaml from 'js-yaml'; + import { readFileSync } from 'fs'; + const doc = yaml.load(readFileSync('$file','utf8')) ?? {}; + const u = doc.updates; + process.stdout.write(Array.isArray(u) && u.length > 0 ? 'true' : 'false'); + " 2>/dev/null || echo 'false') + + if [ "$has_updates" != "true" ]; then + echo "Skipping $file (no updates)" + continue + fi + + echo "Applying $file" + ticket_key=$(node scripts/jira/apply.mjs "$file") + echo "Applied: $ticket_key" + + # Derive the new filename with the real ticket key + dir=$(dirname "$file") + base=$(basename "$file") + new_base=$(echo "$base" | sed "s/XXXX/${ticket_key##*-}/") + new_file="$dir/$new_base" + + # Replace the XXXX file with a real-key file via fetch + if [ "$file" != "$new_file" ]; then + rm -f "$file" + fi + node scripts/jira/fetch.mjs "$ticket_key" "$new_file" + + applied_tickets="$applied_tickets $ticket_key" + done + echo "tickets=$applied_tickets" >> "$GITHUB_OUTPUT" + + - name: Commit refreshed .jira files + if: steps.jira-files.outputs.has_changes == 'true' + run: | + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A -- '.jira/' + if ! git diff --cached --quiet; then + git commit -m "chore: refresh JIRA details [skip ci]" + git push origin HEAD:main + fi + + - name: Post PR comment with JIRA tickets + if: > + steps.jira-files.outputs.has_changes == 'true' && + steps.apply-jira.outputs.tickets != '' && + steps.pr-context.outputs.pr_number != '' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + tickets="${{ steps.apply-jira.outputs.tickets }}" + base_url="https://jira.corp.adobe.com/browse" + body="**JIRA tickets updated by this PR:**"$'\n' + for key in $tickets; do + body="$body"$'\n'"- [$key]($base_url/$key)" + done + gh pr comment ${{ steps.pr-context.outputs.pr_number }} --body "$body" + # Cheap gate so the Production approval is only requested when there's # actual release work (changesets exist) or the operator forced a run. detect: @@ -32,7 +153,7 @@ jobs: fi publish: - needs: detect + needs: [detect, apply-jira] if: needs.detect.outputs.proceed == 'true' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest environment: Production @@ -66,6 +187,8 @@ jobs: pnpm changeset version git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + # Pull any commits made by apply-jira before pushing (e.g. JIRA detail refresh) + git pull --rebase origin main git add -A if ! git diff --cached --quiet; then git commit -m "chore: publish [skip ci]" diff --git a/.jira/.gitkeep b/.jira/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/.jira/README.md b/.jira/README.md new file mode 100644 index 000000000..873d07b45 --- /dev/null +++ b/.jira/README.md @@ -0,0 +1,98 @@ +# .jira/ — Version-controlled JIRA ticket management + +YAML files in this directory represent pending JIRA changes. When a PR merges, the build workflow applies each file to JIRA and replaces it with a refreshed snapshot. + +## File naming convention + +| File type | Name format | Example | +|-----------|-------------|---------| +| Existing ticket | `{PROJECT}-{TICKET#}-{short-title}.yml` | `PDCL-1234-support-for-adcloud.yml` | +| New ticket (not yet in JIRA) | `{PROJECT}-XXXX-{short-description}.yml` | `PDCL-XXXX-add-identity-map-support.yml` | + +Short titles and descriptions use kebab-case, 3–6 words. + +## YAML schema + +```yaml +# Optional read-only snapshot of the ticket's current JIRA state. +# Populated by fetch.mjs; ignored by apply.mjs. +details: + key: PDCL-1234 + summary: Support for AdCloud + status: { name: "In Progress" } + # ... other non-null fields from JIRA + +# Optional ordered array of idempotent REST calls to apply on merge. +# Omit if there are no pending changes. +updates: + - path: /rest/api/2/issue/PDCL-1234 + method: PUT + body: + update: + summary: + - set: "Updated title" + customfield_23300: # AEP Web SDK product field + - set: { id: "116005" } +``` + +### `details` section + +- Written by `fetch.mjs`; never modified manually +- Read-only snapshot; apply.mjs ignores it entirely +- Null and empty-array fields are omitted +- String fields longer than 500 chars are truncated with `...` + +### `updates` section + +- Ordered array of `{ path, method, body }` REST call objects +- `body` is YAML and is serialized to JSON before sending to JIRA +- All field updates must use `set` operations (never `add`/`remove`) to ensure idempotency +- For new tickets: first entry is a `POST /rest/api/2/issue` with `fields` (not `update`) +- Absent or empty `updates` → apply.mjs prints the key and exits 0 without any API calls + +## Custom field reference (PDCL project) + +| Field | ID | Value | +|-------|----|-------| +| AEP Web SDK component | `components[].id` | `"155901"` | +| Documentation component | `components[].id` | `"157512"` | +| AEP Web SDK product (`customfield_23300`) | `id` | `"116005"` | +| Issue type: Story | `issuetype.id` | `"7"` | +| Issue type: Bug | `issuetype.id` | `"1"` | +| Issue type: Documentation | `issuetype.id` | `"14801"` | + +## End-to-end flow + +``` +Developer CI (on merge to main) +───────── ───────────────────── +/jira-propose → apply.mjs + ↓ writes .jira/*.yml ↓ calls JIRA REST API +PR review ↓ creates remote link (repo-{PR#}) + ↓ approves JIRA changes delete file +Merge PR fetch.mjs + ↓ writes refreshed details + skip-ci commit +``` + +1. **Propose** — Run `/jira-propose` in Claude Code. Reads git diff and context, creates or updates a `.jira/*.yml` file locally. No JIRA API calls. +2. **Review** — The `.jira/` file diff appears in the PR. Reviewers can inspect and amend JIRA changes before they land. +3. **Apply** — On merge, `apply.mjs` executes each `updates` entry in order. For new (`XXXX`) tickets it creates the ticket first (idempotent: checks whether a remote link with `globalId: repo-{PR#}` already exists). +4. **Fetch** — After apply succeeds, the XXXX file is deleted and `fetch.mjs` writes a fresh file named with the real ticket key. A `[skip ci]` commit lands both JIRA and changeset changes. + +## Scripts + +```bash +# Apply a ticket file's updates to JIRA (CI usage) +JIRA_API_TOKEN=... GITHUB_PR_URL=... GITHUB_PR_TITLE=... \ + node scripts/jira/apply.mjs .jira/PDCL-1234-my-feature.yml + +# Dry-run: see planned API calls without making them +node scripts/jira/apply.mjs --dry-run .jira/PDCL-1234-my-feature.yml + +# Fetch current JIRA state into a file +JIRA_API_TOKEN=... node scripts/jira/fetch.mjs PDCL-1234 .jira/PDCL-1234-my-feature.yml + +# Dry-run: see what would be written +node scripts/jira/fetch.mjs --dry-run PDCL-1234 .jira/PDCL-1234-my-feature.yml +``` diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..703472800 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,45 @@ +# Alloy — Claude Code guide + +## JIRA ticket management + +JIRA changes are version-controlled as YAML files in `.jira/`. No JIRA API calls are made locally. + +### Workflow + +1. **Propose** — Run `/jira-propose` to create or update a `.jira/*.yml` file based on current git changes and context. +2. **Review** — The `.jira/` diff appears in the PR. Reviewers approve JIRA changes alongside code changes. +3. **Apply** — On merge to `main`, the `apply-jira` CI job executes each file's `updates` array against the JIRA REST API, creates a remote link back to the PR, and posts a PR comment listing updated tickets. +4. **Fetch** — After apply, the XXXX file is deleted and `fetch.mjs` writes a fresh file with the real ticket key and current JIRA state. A `[skip ci]` commit lands these changes. + +### File naming + +- Existing ticket: `PDCL-1234-short-title.yml` +- New ticket (not yet in JIRA): `PDCL-XXXX-short-description.yml` + +### Scripts + +```bash +# See planned JIRA calls without making them (safe for local use) +node scripts/jira/apply.mjs --dry-run .jira/PDCL-1234-my-feature.yml + +# Fetch current JIRA state into a file +JIRA_API_TOKEN= node scripts/jira/fetch.mjs PDCL-1234 .jira/PDCL-1234-my-feature.yml +``` + +### CI environment variables (Production GitHub Actions environment) + +| Variable | Required for | +|----------|-------------| +| `JIRA_API_TOKEN` | apply.mjs and fetch.mjs API calls | +| `ALLOY_BOT_GITHUB_SSH_PRIVATE_KEY` | Pushing skip-ci commits to main | + +### Custom fields (PDCL project) + +| Field | Value | +|-------|-------| +| AEP Web SDK component | `components[].id: "155901"` | +| Product (`customfield_23300`) | `id: "116005"` | +| Story `issuetype.id` | `"7"` | +| Bug `issuetype.id` | `"1"` | + +See [`.jira/README.md`](./.jira/README.md) for the full schema reference. diff --git a/README.md b/README.md index f7a3d5a55..4b6cf1d7c 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,12 @@ This repo contains multiple projects. Each one is in a subdirectory and has its ## Contribution Check out the [contribution guidelines](CONTRIBUTING.md) for quick start information, and head over to the [developer documentation](https://github.com/adobe/alloy/wiki) to understand the architecture and structure of the library. + +## JIRA ticket management + +JIRA changes are version-controlled as YAML files in [`.jira/`](./.jira/). See [`.jira/README.md`](./.jira/README.md) for the full workflow. + +**Quick start:** +1. Run `/jira-propose` in Claude Code to create or update a `.jira/` ticket file +2. The file appears in your PR diff for review +3. On merge, the build workflow applies it to JIRA automatically diff --git a/openspec/changes/github-jira-yaml-workflow/tasks.md b/openspec/changes/github-jira-yaml-workflow/tasks.md index e61024b08..25ce7e6f0 100644 --- a/openspec/changes/github-jira-yaml-workflow/tasks.md +++ b/openspec/changes/github-jira-yaml-workflow/tasks.md @@ -1,44 +1,44 @@ ## 1. Scaffold `.jira/` Directory and Schema -- [ ] 1.1 Create `.jira/` directory with a `.gitkeep` file; JIRA YAML files are tracked in version control -- [ ] 1.2 Write a `.jira/README.md` documenting: file naming convention, YAML schema (`details` / `updates`), custom field reference (component IDs, issue type IDs, `customfield_23300`), and the expected end-to-end flow (propose skill → PR review → apply script → fetch script → build workflow commit) +- [x] 1.1 Create `.jira/` directory with a `.gitkeep` file; JIRA YAML files are tracked in version control +- [x] 1.2 Write a `.jira/README.md` documenting: file naming convention, YAML schema (`details` / `updates`), custom field reference (component IDs, issue type IDs, `customfield_23300`), and the expected end-to-end flow (propose skill → PR review → apply script → fetch script → build workflow commit) ## 2. Fetch Script (`scripts/jira/fetch.mjs`) -- [ ] 2.1 Create `scripts/jira/fetch.mjs` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard -- [ ] 2.2 Implement `GET /rest/api/2/issue/{key}` call (supports any JIRA project, not limited to PDCL); extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` -- [ ] 2.3 Implement file write logic: if file exists, replace only the `details` section and preserve `updates`; if new, create file with only `details` plus `# fetched from JIRA ` comment -- [ ] 2.4 Add `--dry-run` output: print target path and YAML content without writing or fetching +- [x] 2.1 Create `scripts/jira/fetch.mjs` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard +- [x] 2.2 Implement `GET /rest/api/2/issue/{key}` call (supports any JIRA project, not limited to PDCL); extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` +- [x] 2.3 Implement file write logic: if file exists, replace only the `details` section and preserve `updates`; if new, create file with only `details` plus `# fetched from JIRA ` comment +- [x] 2.4 Add `--dry-run` output: print target path and YAML content without writing or fetching ## 3. Apply Script (`scripts/jira/apply.mjs`) -- [ ] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE`/`GITHUB_PR_NUMBER` env-var validation (required only when `updates` is non-empty) -- [ ] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, search JIRA for any issue with a remote link whose global ID is `repo-{PR#}` (no pagination — a single search hit is sufficient); if found, use that ticket key and exit 0; if not found, proceed to create -- [ ] 3.3 If the file has no `updates` or an empty array: print the resolved ticket key to stdout and exit 0 with no API calls -- [ ] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx -- [ ] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `url`, `title`, and `globalId: "repo-{PR#}"`; skip if global ID is already linked -- [ ] 3.6 Print the resolved ticket key as the final stdout line (e.g. `PDCL-1234`) -- [ ] 3.7 Add `--dry-run` output: print planned API calls and the resolved key without making HTTP requests -- [ ] 3.8 Test locally against a real PDCL ticket using `--dry-run` +- [x] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE`/`GITHUB_PR_NUMBER` env-var validation (required only when `updates` is non-empty) +- [x] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, search JIRA for any issue with a remote link whose global ID is `repo-{PR#}` (no pagination — a single search hit is sufficient); if found, use that ticket key and exit 0; if not found, proceed to create +- [x] 3.3 If the file has no `updates` or an empty array: print the resolved ticket key to stdout and exit 0 with no API calls +- [x] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx +- [x] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `url`, `title`, and `globalId: "repo-{PR#}"`; skip if global ID is already linked +- [x] 3.6 Print the resolved ticket key as the final stdout line (e.g. `PDCL-1234`) +- [x] 3.7 Add `--dry-run` output: print planned API calls and the resolved key without making HTTP requests +- [x] 3.8 Test locally against a real PDCL ticket using `--dry-run` ## 4. Build Workflow Integration (`.github/workflows/version-and-publish.yml`) -- [ ] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main`; use `Production` environment for `JIRA_API_TOKEN` access -- [ ] 4.2 Add step to extract `GITHUB_PR_NUMBER`, `GITHUB_PR_URL`, and `GITHUB_PR_TITLE` from the push event's associated PR via `gh pr list --merged` -- [ ] 4.3 Add step to detect changed `.jira/*.yml` files via `git diff HEAD^1 HEAD --name-only -- '.jira/*.yml'`; skip remaining steps if none -- [ ] 4.4 Add loop step: for each changed file that has an `updates` section, run `node scripts/jira/apply.mjs `, capture the printed ticket key; on success, delete the file, derive the new real-key filename (replace `XXXX` with the ticket number), and run `node scripts/jira/fetch.mjs ` -- [ ] 4.5 Add a step after apply-jira that posts a PR comment listing all JIRA tickets created or updated (using `gh pr comment`) -- [ ] 4.6 Combine the `.jira/` file additions/deletions with any changeset version-bump changes into a single skip-ci commit; add this as a job step with appropriate `needs` dependencies so JIRA and changeset changes land together +- [x] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main`; use `Production` environment for `JIRA_API_TOKEN` access +- [x] 4.2 Add step to extract `GITHUB_PR_NUMBER`, `GITHUB_PR_URL`, and `GITHUB_PR_TITLE` from the push event's associated PR via `gh pr list --merged` +- [x] 4.3 Add step to detect changed `.jira/*.yml` files via `git diff HEAD^1 HEAD --name-only -- '.jira/*.yml'`; skip remaining steps if none +- [x] 4.4 Add loop step: for each changed file that has an `updates` section, run `node scripts/jira/apply.mjs `, capture the printed ticket key; on success, delete the file, derive the new real-key filename (replace `XXXX` with the ticket number), and run `node scripts/jira/fetch.mjs ` +- [x] 4.5 Add a step after apply-jira that posts a PR comment listing all JIRA tickets created or updated (using `gh pr comment`) +- [x] 4.6 Combine the `.jira/` file additions/deletions with any changeset version-bump changes into a single skip-ci commit; add this as a job step with appropriate `needs` dependencies so JIRA and changeset changes land together ## 5. `/jira-propose` Claude Code Skill -- [ ] 5.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) -- [ ] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages -- [ ] 5.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields -- [ ] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file -- [ ] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix +- [x] 5.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) +- [x] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages +- [x] 5.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields +- [x] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file +- [x] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix ## 6. Cleanup and Documentation -- [ ] 6.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes +- [x] 6.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes - [ ] 6.2 Add `JIRA_API_TOKEN` secret to the `Production` GitHub Actions environment diff --git a/scripts/jira/apply.mjs b/scripts/jira/apply.mjs new file mode 100644 index 000000000..c1fd6457f --- /dev/null +++ b/scripts/jira/apply.mjs @@ -0,0 +1,223 @@ +#!/usr/bin/env node +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { readFileSync } from "fs"; +import { basename } from "path"; +import yaml from "js-yaml"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; + +function usage() { + console.error("Usage: apply.mjs [--dry-run] "); + console.error(" Path to a .jira/*.yml file"); + process.exit(1); +} + +const args = process.argv.slice(2).filter((a) => a !== "--dry-run"); +const dryRun = process.argv.slice(2).includes("--dry-run"); + +if (args.length < 1) { + usage(); +} + +const [filename] = args; + +// Parse ticket key from filename: {PROJECT}-{NUMBER}-*.yml or {PROJECT}-XXXX-*.yml +const fileBase = basename(filename, ".yml"); +const keyMatch = fileBase.match(/^([A-Z]+-(?:XXXX|\d+))/); +if (!keyMatch) { + console.error(`Cannot parse ticket key from filename: ${filename}`); + process.exit(1); +} +const fileKey = keyMatch[1]; +const isNewTicket = fileKey.endsWith("-XXXX") || fileKey.includes("XXXX"); + +const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; +const updates = parsed.updates ?? []; +const hasUpdates = Array.isArray(updates) && updates.length > 0; + +// Validate env vars only when updates are present +if (hasUpdates && !dryRun) { + if (!JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); + } + if (!process.env.GITHUB_PR_URL) { + console.error("GITHUB_PR_URL is required when updates are present"); + process.exit(1); + } + if (!process.env.GITHUB_PR_TITLE) { + console.error("GITHUB_PR_TITLE is required when updates are present"); + process.exit(1); + } +} + +const GITHUB_PR_URL = process.env.GITHUB_PR_URL ?? ""; +const GITHUB_PR_TITLE = process.env.GITHUB_PR_TITLE ?? ""; +const GITHUB_PR_NUMBER = process.env.GITHUB_PR_NUMBER ?? ""; +const globalId = `repo-${GITHUB_PR_NUMBER}`; +const baseUrl = JIRA_BASE_URL.replace(/\/$/, ""); + +async function jiraRequest(method, path, body) { + const url = `${baseUrl}${path}`; + if (dryRun) { + console.log(`[dry-run] ${method} ${url}`); + if (body !== undefined) { + console.log(JSON.stringify(body, null, 2)); + } + return { ok: true, status: 200, json: async () => ({}) }; + } + const response = await fetch(url, { + method, + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, + body: body !== undefined ? JSON.stringify(body) : undefined, + }); + if (!response.ok) { + const text = await response.text(); + console.error(`JIRA ${method} ${path} failed: ${response.status} ${text}`); + process.exit(1); + } + return response; +} + +async function resolveTicketKey() { + if (!isNewTicket) { + // Existing ticket: parse key directly from filename + return fileKey; // e.g. PDCL-1234 + } + + // New ticket (XXXX): search for an existing ticket with our remote link globalId + // to maintain idempotency across workflow re-runs. + if (GITHUB_PR_NUMBER) { + const foundKey = await searchByRemoteLinkGlobalId(globalId); + if (foundKey) { + console.log(`Found existing ticket ${foundKey} via remote link globalId ${globalId}`); + return foundKey; + } + } + + // No existing ticket found — create one + const createUpdate = updates.find( + (u) => u.method === "POST" && u.path === "/rest/api/2/issue", + ); + if (!createUpdate) { + console.error("XXXX file has no POST /rest/api/2/issue entry in updates"); + process.exit(1); + } + + if (dryRun) { + await jiraRequest("POST", "/rest/api/2/issue", createUpdate.body); + return "PDCL-XXXX"; + } + + const response = await jiraRequest("POST", "/rest/api/2/issue", createUpdate.body); + const data = await response.json(); + return data.key; +} + +async function searchByRemoteLinkGlobalId(searchGlobalId) { + // Search recently created PDCL issues and check their remote links for our globalId. + // Scoped to the past 7 days to keep the result set small — the ticket was created recently. + const jql = encodeURIComponent( + `project = PDCL AND created >= startOfDay("-7d") ORDER BY created DESC`, + ); + const url = `${baseUrl}/rest/api/2/search?jql=${jql}&fields=key&maxResults=50`; + if (dryRun) { + console.log(`[dry-run] Search for existing ticket: GET ${url}`); + return null; + } + + const response = await fetch(url, { + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, + }); + if (!response.ok) return null; + + const data = await response.json(); + const issues = data.issues ?? []; + + for (const issue of issues) { + const linksUrl = `${baseUrl}/rest/api/2/issue/${issue.key}/remotelink`; + const linksResponse = await fetch(linksUrl, { + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, + }); + if (!linksResponse.ok) continue; + const links = await linksResponse.json(); + const match = links.find((l) => l.globalId === searchGlobalId); + if (match) return issue.key; + } + return null; +} + +async function remoteLinksForIssue(key) { + if (dryRun) return []; + const response = await fetch(`${baseUrl}/rest/api/2/issue/${key}/remotelink`, { + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, + }); + if (!response.ok) return []; + return response.json(); +} + +// ── Main ──────────────────────────────────────────────────────────────────── + +const ticketKey = await resolveTicketKey(); + +if (!hasUpdates) { + if (dryRun) console.log(`[dry-run] No updates — would print key: ${ticketKey}`); + console.log(ticketKey); + process.exit(0); +} + +// Execute each update in order, skipping the create call for new tickets +// (it was handled during key resolution above) +const isCreate = (u) => + isNewTicket && u.method === "POST" && u.path === "/rest/api/2/issue"; + +for (const update of updates) { + if (isCreate(update)) continue; + + // Resolve {key} placeholder in path if present + const path = update.path.replace(/\{key\}/g, ticketKey); + await jiraRequest(update.method, path, update.body); +} + +// Create remote link after all updates +if (GITHUB_PR_URL && GITHUB_PR_NUMBER) { + const existingLinks = await remoteLinksForIssue(ticketKey); + const alreadyLinked = existingLinks.some((l) => l.globalId === globalId); + + if (alreadyLinked) { + console.log(`Remote link ${globalId} already exists on ${ticketKey} — skipping`); + } else { + await jiraRequest("POST", `/rest/api/2/issue/${ticketKey}/remotelink`, { + globalId, + relationship: "mentioned in", + object: { + url: GITHUB_PR_URL, + title: GITHUB_PR_TITLE || GITHUB_PR_URL, + }, + }); + } +} + +console.log(ticketKey); diff --git a/scripts/jira/fetch.mjs b/scripts/jira/fetch.mjs new file mode 100644 index 000000000..979ded4db --- /dev/null +++ b/scripts/jira/fetch.mjs @@ -0,0 +1,140 @@ +#!/usr/bin/env node +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { readFileSync, writeFileSync, existsSync } from "fs"; +import yaml from "js-yaml"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; + +const MAX_STRING_LENGTH = 500; + +function usage() { + console.error("Usage: fetch.mjs [--dry-run] "); + console.error(" JIRA issue key, e.g. PDCL-1234"); + console.error(" Path to write, e.g. .jira/PDCL-1234-my-feature.yml"); + process.exit(1); +} + +const args = process.argv.slice(2).filter((a) => a !== "--dry-run"); +const dryRun = process.argv.slice(2).includes("--dry-run"); + +if (args.length < 2) { + usage(); +} + +const [ticketKey, filename] = args; + +if (!dryRun && !JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); +} + +function truncate(value) { + if (typeof value === "string" && value.length > MAX_STRING_LENGTH) { + return value.slice(0, MAX_STRING_LENGTH) + "..."; + } + return value; +} + +function isNonEmpty(value) { + if (value === null || value === undefined) return false; + if (Array.isArray(value) && value.length === 0) return false; + return true; +} + +function extractFields(fields) { + const result = {}; + for (const [key, value] of Object.entries(fields)) { + if (!isNonEmpty(value)) continue; + if (typeof value === "string") { + result[key] = truncate(value); + } else if (typeof value === "object" && !Array.isArray(value)) { + const nested = extractFields(value); + if (Object.keys(nested).length > 0) { + result[key] = nested; + } + } else if (Array.isArray(value)) { + const filtered = value + .map((item) => + typeof item === "object" && item !== null + ? extractFields(item) + : item, + ) + .filter((item) => + typeof item === "object" ? Object.keys(item).length > 0 : isNonEmpty(item), + ); + if (filtered.length > 0) { + result[key] = filtered; + } + } else { + result[key] = value; + } + } + return result; +} + +async function fetchIssue(key) { + const url = `${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(key)}`; + const response = await fetch(url, { + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + const text = await response.text(); + console.error(`JIRA GET failed: ${response.status} ${text}`); + process.exit(1); + } + return response.json(); +} + +function buildDetailsYaml(details, timestamp) { + const comment = `# fetched from JIRA ${timestamp}`; + const detailsYaml = yaml.dump({ details }, { lineWidth: 120, noRefs: true }); + return `${comment}\n${detailsYaml}`; +} + +function mergeWithExisting(detailsYaml, filename) { + if (!existsSync(filename)) { + return detailsYaml; + } + const existing = yaml.load(readFileSync(filename, "utf8")); + if (!existing?.updates) { + return detailsYaml; + } + const detailsParsed = yaml.load(detailsYaml); + const merged = { ...detailsParsed, updates: existing.updates }; + const timestamp = detailsYaml.match(/# fetched from JIRA (.+)/)?.[1] ?? new Date().toISOString(); + const mergedYaml = yaml.dump(merged, { lineWidth: 120, noRefs: true }); + return `# fetched from JIRA ${timestamp}\n${mergedYaml}`; +} + +if (dryRun) { + const url = `${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(ticketKey)}`; + console.log(`[dry-run] Would fetch: GET ${url}`); + console.log(`[dry-run] Would write to: ${filename}`); + process.exit(0); +} + +const data = await fetchIssue(ticketKey); +const details = { + key: data.key, + ...extractFields(data.fields ?? {}), +}; + +const timestamp = new Date().toISOString(); +const detailsYaml = buildDetailsYaml(details, timestamp); +const finalYaml = mergeWithExisting(detailsYaml, filename); + +writeFileSync(filename, finalYaml, "utf8"); +console.log(`Wrote ${filename}`); From 8ccb96072b56c0a638f5d3b5882f8f7ef2cc54cb Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 11:28:57 -0600 Subject: [PATCH 05/10] chore: apply prettier formatting to jira scripts --- scripts/jira/apply.mjs | 30 +++++++++++++++++++++--------- scripts/jira/fetch.mjs | 12 +++++++++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/scripts/jira/apply.mjs b/scripts/jira/apply.mjs index c1fd6457f..baf6bf45e 100644 --- a/scripts/jira/apply.mjs +++ b/scripts/jira/apply.mjs @@ -103,7 +103,9 @@ async function resolveTicketKey() { if (GITHUB_PR_NUMBER) { const foundKey = await searchByRemoteLinkGlobalId(globalId); if (foundKey) { - console.log(`Found existing ticket ${foundKey} via remote link globalId ${globalId}`); + console.log( + `Found existing ticket ${foundKey} via remote link globalId ${globalId}`, + ); return foundKey; } } @@ -122,7 +124,11 @@ async function resolveTicketKey() { return "PDCL-XXXX"; } - const response = await jiraRequest("POST", "/rest/api/2/issue", createUpdate.body); + const response = await jiraRequest( + "POST", + "/rest/api/2/issue", + createUpdate.body, + ); const data = await response.json(); return data.key; } @@ -168,12 +174,15 @@ async function searchByRemoteLinkGlobalId(searchGlobalId) { async function remoteLinksForIssue(key) { if (dryRun) return []; - const response = await fetch(`${baseUrl}/rest/api/2/issue/${key}/remotelink`, { - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", + const response = await fetch( + `${baseUrl}/rest/api/2/issue/${key}/remotelink`, + { + headers: { + Authorization: `Bearer ${JIRA_API_TOKEN}`, + "Content-Type": "application/json", + }, }, - }); + ); if (!response.ok) return []; return response.json(); } @@ -183,7 +192,8 @@ async function remoteLinksForIssue(key) { const ticketKey = await resolveTicketKey(); if (!hasUpdates) { - if (dryRun) console.log(`[dry-run] No updates — would print key: ${ticketKey}`); + if (dryRun) + console.log(`[dry-run] No updates — would print key: ${ticketKey}`); console.log(ticketKey); process.exit(0); } @@ -207,7 +217,9 @@ if (GITHUB_PR_URL && GITHUB_PR_NUMBER) { const alreadyLinked = existingLinks.some((l) => l.globalId === globalId); if (alreadyLinked) { - console.log(`Remote link ${globalId} already exists on ${ticketKey} — skipping`); + console.log( + `Remote link ${globalId} already exists on ${ticketKey} — skipping`, + ); } else { await jiraRequest("POST", `/rest/api/2/issue/${ticketKey}/remotelink`, { globalId, diff --git a/scripts/jira/fetch.mjs b/scripts/jira/fetch.mjs index 979ded4db..c3fbaebed 100644 --- a/scripts/jira/fetch.mjs +++ b/scripts/jira/fetch.mjs @@ -20,7 +20,9 @@ const MAX_STRING_LENGTH = 500; function usage() { console.error("Usage: fetch.mjs [--dry-run] "); console.error(" JIRA issue key, e.g. PDCL-1234"); - console.error(" Path to write, e.g. .jira/PDCL-1234-my-feature.yml"); + console.error( + " Path to write, e.g. .jira/PDCL-1234-my-feature.yml", + ); process.exit(1); } @@ -70,7 +72,9 @@ function extractFields(fields) { : item, ) .filter((item) => - typeof item === "object" ? Object.keys(item).length > 0 : isNonEmpty(item), + typeof item === "object" + ? Object.keys(item).length > 0 + : isNonEmpty(item), ); if (filtered.length > 0) { result[key] = filtered; @@ -114,7 +118,9 @@ function mergeWithExisting(detailsYaml, filename) { } const detailsParsed = yaml.load(detailsYaml); const merged = { ...detailsParsed, updates: existing.updates }; - const timestamp = detailsYaml.match(/# fetched from JIRA (.+)/)?.[1] ?? new Date().toISOString(); + const timestamp = + detailsYaml.match(/# fetched from JIRA (.+)/)?.[1] ?? + new Date().toISOString(); const mergedYaml = yaml.dump(merged, { lineWidth: 120, noRefs: true }); return `# fetched from JIRA ${timestamp}\n${mergedYaml}`; } From a8fc9439ddd61a44e175210c5cf88e10c18fadcd Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 12:21:55 -0600 Subject: [PATCH 06/10] refactor(jira): extract api.mjs with DI, add process.mjs, fix globalId per-ticket MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses four review comments on PR #1553: - api.mjs: extract all JIRA HTTP calls into a factory (createApi) with dryRun, baseUrl, and token injected — enables full unit testing without vi.mock() - apply.mjs / fetch.mjs: converted to exported functions (applyFile, fetchFile) that accept an injected api object; isMain guard added for CLI entry point - process.mjs: new script that orchestrates apply + fetch for a single file, handles XXXX→real-key rename, and short-circuits on missing file or empty updates — replaces 30+ lines of inline bash in the workflow - globalId: moved from auto-generated `repo-{PR#}` to a per-ticket unique hex string specified in the YAML remotelink entry, enabling multiple new tickets per PR merge - When a re-run finds an existing ticket via globalId search, the create fields are PUT to that ticket instead of creating a duplicate - apply.spec.js / fetch.spec.js / process.spec.js: new test files (78 tests passing) using injected mock APIs - jira-propose SKILL.md: updated template to include the remotelink entry with a unique generated globalId - workflow: bash per-file logic replaced with `node scripts/jira/process.mjs "$file"` Co-Authored-By: Claude Sonnet 4.6 --- .claude/skills/jira-propose/SKILL.md | 10 + .github/workflows/version-and-publish.yml | 36 +-- scripts/jira/api.mjs | 70 +++++ scripts/jira/apply.mjs | 322 +++++++++------------- scripts/jira/apply.spec.js | 197 +++++++++++++ scripts/jira/fetch.mjs | 150 +++++----- scripts/jira/fetch.spec.js | 128 +++++++++ scripts/jira/process.mjs | 109 ++++++++ scripts/jira/process.spec.js | 122 ++++++++ 9 files changed, 839 insertions(+), 305 deletions(-) create mode 100644 scripts/jira/api.mjs create mode 100644 scripts/jira/apply.spec.js create mode 100644 scripts/jira/fetch.spec.js create mode 100644 scripts/jira/process.mjs create mode 100644 scripts/jira/process.spec.js diff --git a/.claude/skills/jira-propose/SKILL.md b/.claude/skills/jira-propose/SKILL.md index cd02ce6c3..43c7af050 100644 --- a/.claude/skills/jira-propose/SKILL.md +++ b/.claude/skills/jira-propose/SKILL.md @@ -64,8 +64,18 @@ updates: - id: "155901" # AEP Web SDK customfield_23300: # AEP Web SDK product field id: "116005" + - path: /rest/api/2/issue/{key}/remotelink + method: POST + body: + globalId: + relationship: mentioned in + object: + url: "{GITHUB_PR_URL}" + title: "{GITHUB_PR_TITLE}" ``` +The `globalId` is the idempotency key for this ticket — it must be unique per ticket file so that multiple new tickets can be created in a single PR merge. Generate a random 12-character hex string (e.g. using `Math.random().toString(16).slice(2,14)` mentally). The `{GITHUB_PR_URL}` and `{GITHUB_PR_TITLE}` placeholders are substituted by `apply.mjs` at run time. + **Description guidelines:** - Lead with who benefits (e.g., "Analytics customers using the Web SDK...") - Explain the problem being solved diff --git a/.github/workflows/version-and-publish.yml b/.github/workflows/version-and-publish.yml index 8eae9d409..4b52f293e 100644 --- a/.github/workflows/version-and-publish.yml +++ b/.github/workflows/version-and-publish.yml @@ -61,46 +61,14 @@ jobs: id: apply-jira if: steps.jira-files.outputs.has_changes == 'true' env: - GITHUB_PR_NUMBER: ${{ steps.pr-context.outputs.pr_number }} GITHUB_PR_URL: ${{ steps.pr-context.outputs.pr_url }} GITHUB_PR_TITLE: ${{ steps.pr-context.outputs.pr_title }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | applied_tickets="" for file in ${{ steps.jira-files.outputs.files }}; do - [ -f "$file" ] || continue - - # Only process files with an updates section - has_updates=$(node -e " - import yaml from 'js-yaml'; - import { readFileSync } from 'fs'; - const doc = yaml.load(readFileSync('$file','utf8')) ?? {}; - const u = doc.updates; - process.stdout.write(Array.isArray(u) && u.length > 0 ? 'true' : 'false'); - " 2>/dev/null || echo 'false') - - if [ "$has_updates" != "true" ]; then - echo "Skipping $file (no updates)" - continue - fi - - echo "Applying $file" - ticket_key=$(node scripts/jira/apply.mjs "$file") - echo "Applied: $ticket_key" - - # Derive the new filename with the real ticket key - dir=$(dirname "$file") - base=$(basename "$file") - new_base=$(echo "$base" | sed "s/XXXX/${ticket_key##*-}/") - new_file="$dir/$new_base" - - # Replace the XXXX file with a real-key file via fetch - if [ "$file" != "$new_file" ]; then - rm -f "$file" - fi - node scripts/jira/fetch.mjs "$ticket_key" "$new_file" - - applied_tickets="$applied_tickets $ticket_key" + ticket_key=$(node scripts/jira/process.mjs "$file") + [ -n "$ticket_key" ] && applied_tickets="$applied_tickets $ticket_key" done echo "tickets=$applied_tickets" >> "$GITHUB_OUTPUT" diff --git a/scripts/jira/api.mjs b/scripts/jira/api.mjs new file mode 100644 index 000000000..e0ffd61f6 --- /dev/null +++ b/scripts/jira/api.mjs @@ -0,0 +1,70 @@ +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +/** + * Factory that returns a JIRA REST API client. + * @param {{ dryRun?: boolean, baseUrl: string, token: string }} opts + */ +export default function createApi({ dryRun = false, baseUrl, token }) { + const authHeaders = { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }; + + async function request(method, path, body) { + const url = `${baseUrl}${path}`; + if (dryRun) { + console.log(`[dry-run] ${method} ${url}`); + if (body !== undefined) console.log(JSON.stringify(body, null, 2)); + return {}; + } + const response = await fetch(url, { + method, + headers: authHeaders, + body: body !== undefined ? JSON.stringify(body) : undefined, + }); + if (!response.ok) { + const text = await response.text(); + throw new Error( + `JIRA ${method} ${path} failed: ${response.status} ${text}`, + ); + } + const text = await response.text(); + return text ? JSON.parse(text) : {}; + } + + async function searchIssues(jql, { fields = "key", maxResults = 50 } = {}) { + const qs = `jql=${encodeURIComponent(jql)}&fields=${fields}&maxResults=${maxResults}`; + if (dryRun) { + console.log(`[dry-run] Search: GET ${baseUrl}/rest/api/2/search?${qs}`); + return []; + } + const response = await fetch(`${baseUrl}/rest/api/2/search?${qs}`, { + headers: authHeaders, + }); + if (!response.ok) return []; + const data = await response.json(); + return data.issues ?? []; + } + + async function getRemoteLinks(key) { + if (dryRun) return []; + const response = await fetch( + `${baseUrl}/rest/api/2/issue/${key}/remotelink`, + { headers: authHeaders }, + ); + if (!response.ok) return []; + return response.json(); + } + + return { dryRun, request, searchIssues, getRemoteLinks }; +} diff --git a/scripts/jira/apply.mjs b/scripts/jira/apply.mjs index baf6bf45e..6cf072e97 100644 --- a/scripts/jira/apply.mjs +++ b/scripts/jira/apply.mjs @@ -13,223 +13,163 @@ governing permissions and limitations under the License. import { readFileSync } from "fs"; import { basename } from "path"; +import { fileURLToPath } from "url"; import yaml from "js-yaml"; +import createApi from "./api.mjs"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; -function usage() { - console.error("Usage: apply.mjs [--dry-run] "); - console.error(" Path to a .jira/*.yml file"); - process.exit(1); -} - -const args = process.argv.slice(2).filter((a) => a !== "--dry-run"); -const dryRun = process.argv.slice(2).includes("--dry-run"); - -if (args.length < 1) { - usage(); -} - -const [filename] = args; - -// Parse ticket key from filename: {PROJECT}-{NUMBER}-*.yml or {PROJECT}-XXXX-*.yml -const fileBase = basename(filename, ".yml"); -const keyMatch = fileBase.match(/^([A-Z]+-(?:XXXX|\d+))/); -if (!keyMatch) { - console.error(`Cannot parse ticket key from filename: ${filename}`); - process.exit(1); -} -const fileKey = keyMatch[1]; -const isNewTicket = fileKey.endsWith("-XXXX") || fileKey.includes("XXXX"); - -const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; -const updates = parsed.updates ?? []; -const hasUpdates = Array.isArray(updates) && updates.length > 0; - -// Validate env vars only when updates are present -if (hasUpdates && !dryRun) { - if (!JIRA_API_TOKEN) { - console.error("JIRA_API_TOKEN is required"); - process.exit(1); +// Recursively replace {PLACEHOLDER} tokens in body values. +function interpolate(value, vars) { + if (typeof value === "string") { + return value.replace(/\{(\w+)\}/g, (_, k) => vars[k] ?? `{${k}}`); } - if (!process.env.GITHUB_PR_URL) { - console.error("GITHUB_PR_URL is required when updates are present"); - process.exit(1); - } - if (!process.env.GITHUB_PR_TITLE) { - console.error("GITHUB_PR_TITLE is required when updates are present"); - process.exit(1); + if (Array.isArray(value)) return value.map((v) => interpolate(v, vars)); + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value).map(([k, v]) => [k, interpolate(v, vars)]), + ); } + return value; } -const GITHUB_PR_URL = process.env.GITHUB_PR_URL ?? ""; -const GITHUB_PR_TITLE = process.env.GITHUB_PR_TITLE ?? ""; -const GITHUB_PR_NUMBER = process.env.GITHUB_PR_NUMBER ?? ""; -const globalId = `repo-${GITHUB_PR_NUMBER}`; -const baseUrl = JIRA_BASE_URL.replace(/\/$/, ""); - -async function jiraRequest(method, path, body) { - const url = `${baseUrl}${path}`; - if (dryRun) { - console.log(`[dry-run] ${method} ${url}`); - if (body !== undefined) { - console.log(JSON.stringify(body, null, 2)); - } - return { ok: true, status: 200, json: async () => ({}) }; - } - const response = await fetch(url, { - method, - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", - }, - body: body !== undefined ? JSON.stringify(body) : undefined, - }); - if (!response.ok) { - const text = await response.text(); - console.error(`JIRA ${method} ${path} failed: ${response.status} ${text}`); - process.exit(1); - } - return response; -} +/** + * Apply a .jira/*.yml file's updates to JIRA. + * @param {string} filename + * @param {{ api: object, prUrl?: string, prTitle?: string }} opts + * @returns {Promise} resolved ticket key, e.g. "PDCL-1234" + */ +export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { + const fileBase = basename(filename, ".yml"); + const keyMatch = fileBase.match(/^([A-Z]+-(?:XXXX|\d+))/); + if (!keyMatch) + throw new Error(`Cannot parse ticket key from filename: ${filename}`); + + const fileKey = keyMatch[1]; + const isNewTicket = fileKey.includes("XXXX"); + const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; + const updates = Array.isArray(parsed.updates) ? parsed.updates : []; + const hasUpdates = updates.length > 0; + + const vars = { GITHUB_PR_URL: prUrl, GITHUB_PR_TITLE: prTitle }; + + // For new tickets, find the remote-link entry to get its globalId (idempotency key). + const remoteLinkUpdate = updates.find( + (u) => u.method === "POST" && String(u.path).includes("/remotelink"), + ); + const globalId = remoteLinkUpdate?.body?.globalId; -async function resolveTicketKey() { - if (!isNewTicket) { - // Existing ticket: parse key directly from filename - return fileKey; // e.g. PDCL-1234 - } + async function resolveKey() { + if (!isNewTicket) return fileKey; - // New ticket (XXXX): search for an existing ticket with our remote link globalId - // to maintain idempotency across workflow re-runs. - if (GITHUB_PR_NUMBER) { - const foundKey = await searchByRemoteLinkGlobalId(globalId); - if (foundKey) { - console.log( - `Found existing ticket ${foundKey} via remote link globalId ${globalId}`, + // Search for an existing ticket that already has this globalId on its remote links. + if (globalId) { + const issues = await api.searchIssues( + `project = PDCL AND created >= startOfDay("-7d") ORDER BY created DESC`, ); - return foundKey; + for (const issue of issues) { + const links = await api.getRemoteLinks(issue.key); + if (links.some((l) => l.globalId === globalId)) { + console.log( + `Found existing ticket ${issue.key} via globalId ${globalId}`, + ); + // Update the existing ticket with the create details to ensure idempotency. + const createUpdate = updates.find( + (u) => u.method === "POST" && u.path === "/rest/api/2/issue", + ); + if (createUpdate?.body?.fields) { + await api.request("PUT", `/rest/api/2/issue/${issue.key}`, { + fields: createUpdate.body.fields, + }); + } + return issue.key; + } + } } - } - // No existing ticket found — create one - const createUpdate = updates.find( - (u) => u.method === "POST" && u.path === "/rest/api/2/issue", - ); - if (!createUpdate) { - console.error("XXXX file has no POST /rest/api/2/issue entry in updates"); - process.exit(1); + // No existing ticket found — create one. + const createUpdate = updates.find( + (u) => u.method === "POST" && u.path === "/rest/api/2/issue", + ); + if (!createUpdate) + throw new Error( + "XXXX file has no POST /rest/api/2/issue entry in updates", + ); + const data = await api.request( + "POST", + "/rest/api/2/issue", + createUpdate.body, + ); + return data.key ?? "PDCL-XXXX"; } - if (dryRun) { - await jiraRequest("POST", "/rest/api/2/issue", createUpdate.body); - return "PDCL-XXXX"; - } + const ticketKey = await resolveKey(); - const response = await jiraRequest( - "POST", - "/rest/api/2/issue", - createUpdate.body, - ); - const data = await response.json(); - return data.key; -} + if (!hasUpdates) return ticketKey; -async function searchByRemoteLinkGlobalId(searchGlobalId) { - // Search recently created PDCL issues and check their remote links for our globalId. - // Scoped to the past 7 days to keep the result set small — the ticket was created recently. - const jql = encodeURIComponent( - `project = PDCL AND created >= startOfDay("-7d") ORDER BY created DESC`, - ); - const url = `${baseUrl}/rest/api/2/search?jql=${jql}&fields=key&maxResults=50`; - if (dryRun) { - console.log(`[dry-run] Search for existing ticket: GET ${url}`); - return null; - } + const isCreateCall = (u) => + isNewTicket && u.method === "POST" && u.path === "/rest/api/2/issue"; - const response = await fetch(url, { - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", - }, - }); - if (!response.ok) return null; - - const data = await response.json(); - const issues = data.issues ?? []; - - for (const issue of issues) { - const linksUrl = `${baseUrl}/rest/api/2/issue/${issue.key}/remotelink`; - const linksResponse = await fetch(linksUrl, { - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", - }, - }); - if (!linksResponse.ok) continue; - const links = await linksResponse.json(); - const match = links.find((l) => l.globalId === searchGlobalId); - if (match) return issue.key; + for (const update of updates) { + if (isCreateCall(update)) continue; + const path = String(update.path).replace(/\{key\}/g, ticketKey); + const body = interpolate(update.body, vars); + await api.request(update.method, path, body); } - return null; -} -async function remoteLinksForIssue(key) { - if (dryRun) return []; - const response = await fetch( - `${baseUrl}/rest/api/2/issue/${key}/remotelink`, - { - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", - }, - }, - ); - if (!response.ok) return []; - return response.json(); + return ticketKey; } -// ── Main ──────────────────────────────────────────────────────────────────── - -const ticketKey = await resolveTicketKey(); +// Script entry point — only executes when run directly. +if (process.argv[1] === fileURLToPath(import.meta.url)) { + const rawArgs = process.argv.slice(2); + const dryRun = rawArgs.includes("--dry-run"); + const args = rawArgs.filter((a) => a !== "--dry-run"); -if (!hasUpdates) { - if (dryRun) - console.log(`[dry-run] No updates — would print key: ${ticketKey}`); - console.log(ticketKey); - process.exit(0); -} + if (args.length < 1) { + console.error("Usage: apply.mjs [--dry-run] "); + process.exit(1); + } -// Execute each update in order, skipping the create call for new tickets -// (it was handled during key resolution above) -const isCreate = (u) => - isNewTicket && u.method === "POST" && u.path === "/rest/api/2/issue"; + const [filename] = args; -for (const update of updates) { - if (isCreate(update)) continue; + const parsed = (() => { + try { + return yaml.load(readFileSync(filename, "utf8")) ?? {}; + } catch { + return {}; + } + })(); + const hasUpdates = Array.isArray(parsed.updates) && parsed.updates.length > 0; - // Resolve {key} placeholder in path if present - const path = update.path.replace(/\{key\}/g, ticketKey); - await jiraRequest(update.method, path, update.body); -} + if (hasUpdates && !dryRun) { + if (!JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); + } + if (!process.env.GITHUB_PR_URL) { + console.error("GITHUB_PR_URL is required when updates are present"); + process.exit(1); + } + if (!process.env.GITHUB_PR_TITLE) { + console.error("GITHUB_PR_TITLE is required when updates are present"); + process.exit(1); + } + } -// Create remote link after all updates -if (GITHUB_PR_URL && GITHUB_PR_NUMBER) { - const existingLinks = await remoteLinksForIssue(ticketKey); - const alreadyLinked = existingLinks.some((l) => l.globalId === globalId); + const api = createApi({ + dryRun, + baseUrl: JIRA_BASE_URL.replace(/\/$/, ""), + token: JIRA_API_TOKEN ?? "", + }); - if (alreadyLinked) { - console.log( - `Remote link ${globalId} already exists on ${ticketKey} — skipping`, - ); - } else { - await jiraRequest("POST", `/rest/api/2/issue/${ticketKey}/remotelink`, { - globalId, - relationship: "mentioned in", - object: { - url: GITHUB_PR_URL, - title: GITHUB_PR_TITLE || GITHUB_PR_URL, - }, + applyFile(filename, { + api, + prUrl: process.env.GITHUB_PR_URL ?? "", + prTitle: process.env.GITHUB_PR_TITLE ?? "", + }) + .then((key) => console.log(key)) + .catch((e) => { + console.error(e.message); + process.exit(1); }); - } } - -console.log(ticketKey); diff --git a/scripts/jira/apply.spec.js b/scripts/jira/apply.spec.js new file mode 100644 index 000000000..99c2cb9ed --- /dev/null +++ b/scripts/jira/apply.spec.js @@ -0,0 +1,197 @@ +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { describe, it, expect, vi, beforeEach } from "vitest"; +import { writeFileSync, unlinkSync } from "fs"; +import { join } from "path"; +import { tmpdir } from "os"; +import { applyFile } from "./apply.mjs"; + +// Unique prefix per spec file avoids temp-file collisions when tests run in parallel. +function uid() { + return `${Date.now()}-${Math.random().toString(36).slice(2)}`; +} + +function tempFile(content) { + const path = join(tmpdir(), `PDCL-1234-apply-spec-${uid()}.yml`); + writeFileSync(path, content, "utf8"); + return path; +} + +function xxxxFile(content) { + const path = join(tmpdir(), `PDCL-XXXX-apply-spec-${uid()}.yml`); + writeFileSync(path, content, "utf8"); + return path; +} + +function mockApi(overrides = {}) { + return { + dryRun: false, + request: vi.fn(async (method) => + method === "POST" ? { key: "PDCL-9999" } : {}, + ), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), + ...overrides, + }; +} + +describe("applyFile — existing ticket", () => { + it("returns the ticket key from the filename", async () => { + const file = tempFile(` +updates: + - path: /rest/api/2/issue/PDCL-1234 + method: PUT + body: + update: + summary: + - set: "New title" +`); + const api = mockApi(); + const key = await applyFile(file, { api }); + expect(key).toBe("PDCL-1234"); + unlinkSync(file); + }); + + it("calls JIRA with interpolated PR URL and title", async () => { + const file = tempFile(` +updates: + - path: /rest/api/2/issue/PDCL-1234/remotelink + method: POST + body: + globalId: abc-123 + object: + url: "{GITHUB_PR_URL}" + title: "{GITHUB_PR_TITLE}" +`); + const api = mockApi(); + await applyFile(file, { + api, + prUrl: "https://github.com/adobe/alloy/pull/99", + prTitle: "My PR", + }); + expect(api.request).toHaveBeenCalledWith( + "POST", + "/rest/api/2/issue/PDCL-1234/remotelink", + expect.objectContaining({ + object: expect.objectContaining({ + url: "https://github.com/adobe/alloy/pull/99", + title: "My PR", + }), + }), + ); + unlinkSync(file); + }); + + it("returns key immediately when there are no updates", async () => { + const file = tempFile(`details:\n key: PDCL-1234\n`); + const api = mockApi(); + const key = await applyFile(file, { api }); + expect(key).toBe("PDCL-1234"); + expect(api.request).not.toHaveBeenCalled(); + unlinkSync(file); + }); +}); + +describe("applyFile — new ticket (XXXX)", () => { + it("creates ticket and returns real key when no existing ticket found", async () => { + const file = xxxxFile(` +updates: + - path: /rest/api/2/issue + method: POST + body: + fields: + project: { key: PDCL } + summary: New feature + - path: /rest/api/2/issue/{key}/remotelink + method: POST + body: + globalId: unique-abc-123 + object: + url: "{GITHUB_PR_URL}" +`); + const api = mockApi(); + const key = await applyFile(file, { + api, + prUrl: "https://github.com/adobe/alloy/pull/1", + }); + expect(key).toBe("PDCL-9999"); + // Create call executed + expect(api.request).toHaveBeenCalledWith( + "POST", + "/rest/api/2/issue", + expect.any(Object), + ); + // Remotelink call executed with resolved key + expect(api.request).toHaveBeenCalledWith( + "POST", + "/rest/api/2/issue/PDCL-9999/remotelink", + expect.any(Object), + ); + unlinkSync(file); + }); + + it("finds existing ticket via globalId and updates it instead of creating", async () => { + const file = xxxxFile(` +updates: + - path: /rest/api/2/issue + method: POST + body: + fields: + project: { key: PDCL } + summary: New feature + - path: /rest/api/2/issue/{key}/remotelink + method: POST + body: + globalId: existing-global-id + object: + url: "{GITHUB_PR_URL}" +`); + const api = mockApi({ + searchIssues: vi.fn(async () => [{ key: "PDCL-5678" }]), + getRemoteLinks: vi.fn(async () => [{ globalId: "existing-global-id" }]), + }); + const key = await applyFile(file, { + api, + prUrl: "https://github.com/adobe/alloy/pull/1", + }); + expect(key).toBe("PDCL-5678"); + // Should NOT have called create + expect(api.request).not.toHaveBeenCalledWith( + "POST", + "/rest/api/2/issue", + expect.any(Object), + ); + // Should have updated the existing ticket with create fields + expect(api.request).toHaveBeenCalledWith( + "PUT", + "/rest/api/2/issue/PDCL-5678", + expect.objectContaining({ fields: expect.any(Object) }), + ); + unlinkSync(file); + }); + + it("throws when XXXX file has no create entry", async () => { + const file = xxxxFile(` +updates: + - path: /rest/api/2/issue/PDCL-1234 + method: PUT + body: + update: {} +`); + const api = mockApi(); + await expect(applyFile(file, { api })).rejects.toThrow( + "XXXX file has no POST /rest/api/2/issue entry", + ); + unlinkSync(file); + }); +}); diff --git a/scripts/jira/fetch.mjs b/scripts/jira/fetch.mjs index c3fbaebed..5c8d0dfa3 100644 --- a/scripts/jira/fetch.mjs +++ b/scripts/jira/fetch.mjs @@ -12,34 +12,13 @@ governing permissions and limitations under the License. */ import { readFileSync, writeFileSync, existsSync } from "fs"; +import { fileURLToPath } from "url"; import yaml from "js-yaml"; +import createApi from "./api.mjs"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; const MAX_STRING_LENGTH = 500; -function usage() { - console.error("Usage: fetch.mjs [--dry-run] "); - console.error(" JIRA issue key, e.g. PDCL-1234"); - console.error( - " Path to write, e.g. .jira/PDCL-1234-my-feature.yml", - ); - process.exit(1); -} - -const args = process.argv.slice(2).filter((a) => a !== "--dry-run"); -const dryRun = process.argv.slice(2).includes("--dry-run"); - -if (args.length < 2) { - usage(); -} - -const [ticketKey, filename] = args; - -if (!dryRun && !JIRA_API_TOKEN) { - console.error("JIRA_API_TOKEN is required"); - process.exit(1); -} - function truncate(value) { if (typeof value === "string" && value.length > MAX_STRING_LENGTH) { return value.slice(0, MAX_STRING_LENGTH) + "..."; @@ -59,11 +38,6 @@ function extractFields(fields) { if (!isNonEmpty(value)) continue; if (typeof value === "string") { result[key] = truncate(value); - } else if (typeof value === "object" && !Array.isArray(value)) { - const nested = extractFields(value); - if (Object.keys(nested).length > 0) { - result[key] = nested; - } } else if (Array.isArray(value)) { const filtered = value .map((item) => @@ -76,9 +50,10 @@ function extractFields(fields) { ? Object.keys(item).length > 0 : isNonEmpty(item), ); - if (filtered.length > 0) { - result[key] = filtered; - } + if (filtered.length > 0) result[key] = filtered; + } else if (typeof value === "object") { + const nested = extractFields(value); + if (Object.keys(nested).length > 0) result[key] = nested; } else { result[key] = value; } @@ -86,61 +61,76 @@ function extractFields(fields) { return result; } -async function fetchIssue(key) { - const url = `${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(key)}`; - const response = await fetch(url, { - headers: { - Authorization: `Bearer ${JIRA_API_TOKEN}`, - "Content-Type": "application/json", - }, - }); - if (!response.ok) { - const text = await response.text(); - console.error(`JIRA GET failed: ${response.status} ${text}`); - process.exit(1); - } - return response.json(); -} - -function buildDetailsYaml(details, timestamp) { - const comment = `# fetched from JIRA ${timestamp}`; - const detailsYaml = yaml.dump({ details }, { lineWidth: 120, noRefs: true }); - return `${comment}\n${detailsYaml}`; +function buildYaml(details, existingUpdates, timestamp) { + const doc = existingUpdates + ? { details, updates: existingUpdates } + : { details }; + return `# fetched from JIRA ${timestamp}\n${yaml.dump(doc, { lineWidth: 120, noRefs: true })}`; } -function mergeWithExisting(detailsYaml, filename) { - if (!existsSync(filename)) { - return detailsYaml; +/** + * Fetch live JIRA state for a ticket and write it to a file. + * @param {string} ticketKey e.g. "PDCL-1234" + * @param {string} filename target file path + * @param {{ api: object }} opts + */ +export async function fetchFile(ticketKey, filename, { api }) { + if (api.dryRun) { + console.log( + `[dry-run] Would fetch: GET ${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(ticketKey)}`, + ); + console.log(`[dry-run] Would write to: ${filename}`); + return; } - const existing = yaml.load(readFileSync(filename, "utf8")); - if (!existing?.updates) { - return detailsYaml; + + const data = await api.request( + "GET", + `/rest/api/2/issue/${encodeURIComponent(ticketKey)}`, + ); + const details = { key: data.key, ...extractFields(data.fields ?? {}) }; + + let existingUpdates; + if (existsSync(filename)) { + const existing = yaml.load(readFileSync(filename, "utf8")); + existingUpdates = existing?.updates; } - const detailsParsed = yaml.load(detailsYaml); - const merged = { ...detailsParsed, updates: existing.updates }; - const timestamp = - detailsYaml.match(/# fetched from JIRA (.+)/)?.[1] ?? - new Date().toISOString(); - const mergedYaml = yaml.dump(merged, { lineWidth: 120, noRefs: true }); - return `# fetched from JIRA ${timestamp}\n${mergedYaml}`; -} -if (dryRun) { - const url = `${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(ticketKey)}`; - console.log(`[dry-run] Would fetch: GET ${url}`); - console.log(`[dry-run] Would write to: ${filename}`); - process.exit(0); + const timestamp = new Date().toISOString(); + const content = buildYaml(details, existingUpdates, timestamp); + writeFileSync(filename, content, "utf8"); + console.log(`Wrote ${filename}`); } -const data = await fetchIssue(ticketKey); -const details = { - key: data.key, - ...extractFields(data.fields ?? {}), -}; +// Script entry point — only executes when run directly. +if (process.argv[1] === fileURLToPath(import.meta.url)) { + const rawArgs = process.argv.slice(2); + const dryRun = rawArgs.includes("--dry-run"); + const args = rawArgs.filter((a) => a !== "--dry-run"); + + if (args.length < 2) { + console.error("Usage: fetch.mjs [--dry-run] "); + console.error(" JIRA issue key, e.g. PDCL-1234"); + console.error( + " Path to write, e.g. .jira/PDCL-1234-my-feature.yml", + ); + process.exit(1); + } -const timestamp = new Date().toISOString(); -const detailsYaml = buildDetailsYaml(details, timestamp); -const finalYaml = mergeWithExisting(detailsYaml, filename); + const [ticketKey, filename] = args; -writeFileSync(filename, finalYaml, "utf8"); -console.log(`Wrote ${filename}`); + if (!dryRun && !JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); + } + + const api = createApi({ + dryRun, + baseUrl: JIRA_BASE_URL.replace(/\/$/, ""), + token: JIRA_API_TOKEN ?? "", + }); + + fetchFile(ticketKey, filename, { api }).catch((e) => { + console.error(e.message); + process.exit(1); + }); +} diff --git a/scripts/jira/fetch.spec.js b/scripts/jira/fetch.spec.js new file mode 100644 index 000000000..08e527749 --- /dev/null +++ b/scripts/jira/fetch.spec.js @@ -0,0 +1,128 @@ +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { describe, it, expect, vi } from "vitest"; +import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs"; +import { join } from "path"; +import { tmpdir } from "os"; +import yaml from "js-yaml"; +import { fetchFile } from "./fetch.mjs"; + +function mockApi(issueData = {}) { + return { + dryRun: false, + request: vi.fn(async () => ({ + key: "PDCL-1234", + fields: { + summary: "My feature", + status: { name: "In Progress" }, + assignee: null, + description: null, + components: [], + ...issueData, + }, + })), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), + }; +} + +// Unique prefix per spec file avoids temp-file collisions when tests run in parallel. +function tempPath(label) { + return join( + tmpdir(), + `fetch-spec-${label}-${Date.now()}-${Math.random().toString(36).slice(2)}.yml`, + ); +} + +describe("fetchFile", () => { + it("writes details section to a new file", async () => { + const filename = tempPath("pdcl-1234"); + const api = mockApi({ summary: "Hello world" }); + + await fetchFile("PDCL-1234", filename, { api }); + + const content = readFileSync(filename, "utf8"); + const parsed = yaml.load(content.replace(/^#.*\n/, "")); + expect(parsed.details.key).toBe("PDCL-1234"); + expect(parsed.details.summary).toBe("Hello world"); + expect(parsed.details.assignee).toBeUndefined(); + expect(parsed.details.components).toBeUndefined(); + unlinkSync(filename); + }); + + it("omits null and empty-array fields from details", async () => { + const filename = tempPath("pdcl-1234"); + const api = mockApi({ description: null, components: [] }); + + await fetchFile("PDCL-1234", filename, { api }); + + const content = readFileSync(filename, "utf8"); + const parsed = yaml.load(content.replace(/^#.*\n/, "")); + expect(parsed.details.description).toBeUndefined(); + expect(parsed.details.components).toBeUndefined(); + unlinkSync(filename); + }); + + it("truncates long string fields to 500 chars", async () => { + const filename = tempPath("pdcl-1234"); + const longDesc = "x".repeat(600); + const api = mockApi({ description: longDesc }); + + await fetchFile("PDCL-1234", filename, { api }); + + const content = readFileSync(filename, "utf8"); + const parsed = yaml.load(content.replace(/^#.*\n/, "")); + expect(parsed.details.description).toHaveLength(503); // 500 + "..." + expect(parsed.details.description.endsWith("...")).toBe(true); + unlinkSync(filename); + }); + + it("preserves existing updates section when file already exists", async () => { + const filename = tempPath("pdcl-1234"); + writeFileSync( + filename, + `updates:\n - path: /rest/api/2/issue/PDCL-1234\n method: PUT\n body: {}\n`, + "utf8", + ); + const api = mockApi({ summary: "Updated" }); + + await fetchFile("PDCL-1234", filename, { api }); + + const content = readFileSync(filename, "utf8"); + const parsed = yaml.load(content.replace(/^#.*\n/, "")); + expect(parsed.details.summary).toBe("Updated"); + expect(parsed.updates).toHaveLength(1); + expect(parsed.updates[0].method).toBe("PUT"); + unlinkSync(filename); + }); + + it("includes a fetched-from-JIRA comment on the first line", async () => { + const filename = tempPath("pdcl-1234"); + const api = mockApi(); + + await fetchFile("PDCL-1234", filename, { api }); + + const content = readFileSync(filename, "utf8"); + expect(content.startsWith("# fetched from JIRA ")).toBe(true); + unlinkSync(filename); + }); + + it("skips file write in dry-run mode", async () => { + const filename = tempPath("pdcl-1234"); + const api = { ...mockApi(), dryRun: true }; + + await fetchFile("PDCL-1234", filename, { api }); + + expect(existsSync(filename)).toBe(false); + }); +}); diff --git a/scripts/jira/process.mjs b/scripts/jira/process.mjs new file mode 100644 index 000000000..4576ba3ef --- /dev/null +++ b/scripts/jira/process.mjs @@ -0,0 +1,109 @@ +#!/usr/bin/env node +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { readFileSync, unlinkSync, existsSync } from "fs"; +import { basename, dirname } from "path"; +import { fileURLToPath } from "url"; +import yaml from "js-yaml"; +import createApi from "./api.mjs"; +import { applyFile } from "./apply.mjs"; +import { fetchFile } from "./fetch.mjs"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; + +/** + * Process a single .jira/*.yml file: apply updates, refresh details via fetch. + * For XXXX files, deletes the placeholder file and creates a real-key file. + * @param {string} filename + * @param {{ api: object, prUrl?: string, prTitle?: string }} opts + * @returns {Promise} ticket key if processed, null if skipped + */ +export async function processFile(filename, { api, prUrl = "", prTitle = "" }) { + if (!existsSync(filename)) { + console.log(`Skipping ${filename} (file not found)`); + return null; + } + + const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; + const hasUpdates = Array.isArray(parsed.updates) && parsed.updates.length > 0; + + if (!hasUpdates) { + console.log(`Skipping ${filename} (no updates)`); + return null; + } + + const ticketKey = await applyFile(filename, { api, prUrl, prTitle }); + console.log(`Applied: ${ticketKey}`); + + // Derive new filename: replace XXXX with the real ticket number. + const dir = dirname(filename); + const base = basename(filename); + const ticketNum = ticketKey.split("-").pop(); + const newBase = base.replace("XXXX", ticketNum); + const newFilename = `${dir}/${newBase}`; + + if (filename !== newFilename && !api.dryRun) { + unlinkSync(filename); + } + + await fetchFile(ticketKey, newFilename, { api }); + + return ticketKey; +} + +// Script entry point — only executes when run directly. +if (process.argv[1] === fileURLToPath(import.meta.url)) { + const rawArgs = process.argv.slice(2); + const dryRun = rawArgs.includes("--dry-run"); + const args = rawArgs.filter((a) => a !== "--dry-run"); + + if (args.length < 1) { + console.error("Usage: process.mjs [--dry-run] "); + process.exit(1); + } + + const [filename] = args; + + if (!dryRun) { + if (!JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); + } + if (!process.env.GITHUB_PR_URL) { + console.error("GITHUB_PR_URL is required"); + process.exit(1); + } + if (!process.env.GITHUB_PR_TITLE) { + console.error("GITHUB_PR_TITLE is required"); + process.exit(1); + } + } + + const api = createApi({ + dryRun, + baseUrl: JIRA_BASE_URL.replace(/\/$/, ""), + token: JIRA_API_TOKEN ?? "", + }); + + processFile(filename, { + api, + prUrl: process.env.GITHUB_PR_URL ?? "", + prTitle: process.env.GITHUB_PR_TITLE ?? "", + }) + .then((key) => { + if (key) console.log(key); + }) + .catch((e) => { + console.error(e.message); + process.exit(1); + }); +} diff --git a/scripts/jira/process.spec.js b/scripts/jira/process.spec.js new file mode 100644 index 000000000..e1157c5da --- /dev/null +++ b/scripts/jira/process.spec.js @@ -0,0 +1,122 @@ +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { describe, it, expect, vi } from "vitest"; +import { writeFileSync, existsSync, unlinkSync } from "fs"; +import { join } from "path"; +import { tmpdir } from "os"; +import { processFile } from "./process.mjs"; + +function mockApi(overrides = {}) { + return { + dryRun: false, + request: vi.fn(async (method) => + method === "POST" + ? { key: "PDCL-9999" } + : { key: "PDCL-1234", fields: { summary: "Test" } }, + ), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), + ...overrides, + }; +} + +// jiraKey must be at the start of the basename for the filename regex to match. +// Unique suffix per spec file prevents collisions when tests run in parallel. +function writeTemp(jiraKey, content) { + const uid = `${Date.now()}-${Math.random().toString(36).slice(2)}`; + const path = join(tmpdir(), `${jiraKey}-proc-spec-${uid}.yml`); + writeFileSync(path, content, "utf8"); + return path; +} + +describe("processFile", () => { + it("returns null and skips when file has no updates", async () => { + const file = writeTemp("PDCL-1234", `details:\n key: PDCL-1234\n`); + const api = mockApi(); + const result = await processFile(file, { api }); + expect(result).toBeNull(); + expect(api.request).not.toHaveBeenCalled(); + unlinkSync(file); + }); + + it("returns null when file does not exist", async () => { + const api = mockApi(); + const result = await processFile("/tmp/PDCL-1234-nonexistent.yml", { api }); + expect(result).toBeNull(); + }); + + it("applies updates and returns ticket key for existing ticket", async () => { + const file = writeTemp( + "PDCL-1234", + ` +updates: + - path: /rest/api/2/issue/PDCL-1234 + method: PUT + body: + update: + summary: + - set: "Updated" +`, + ); + const api = mockApi(); + const result = await processFile(file, { + api, + prUrl: "https://github.com/adobe/alloy/pull/1", + prTitle: "PR", + }); + expect(result).toBe("PDCL-1234"); + expect(api.request).toHaveBeenCalled(); + expect(api.request).toHaveBeenCalledWith( + "GET", + expect.stringContaining("PDCL-1234"), + ); + if (existsSync(file)) unlinkSync(file); + }); + + it("deletes XXXX file and creates real-key file", async () => { + const uid = `${Date.now()}-${Math.random().toString(36).slice(2)}`; + const xxxxPath = join(tmpdir(), `PDCL-XXXX-proc-spec-${uid}.yml`); + writeFileSync( + xxxxPath, + ` +updates: + - path: /rest/api/2/issue + method: POST + body: + fields: + project: { key: PDCL } + summary: New feat + - path: /rest/api/2/issue/{key}/remotelink + method: POST + body: + globalId: abc-xyz + object: + url: "{GITHUB_PR_URL}" +`, + "utf8", + ); + + const api = mockApi(); + const result = await processFile(xxxxPath, { + api, + prUrl: "https://github.com/adobe/alloy/pull/2", + prTitle: "PR", + }); + + expect(result).toBe("PDCL-9999"); + expect(existsSync(xxxxPath)).toBe(false); + const realPath = xxxxPath.replace("XXXX", "9999"); + expect(existsSync(realPath)).toBe(true); + if (existsSync(realPath)) unlinkSync(realPath); + }); +}); From e6b962a70db70aee5c48cdaee0125073a764369d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 14:06:54 -0600 Subject: [PATCH 07/10] chore(jira): rename scripts from .mjs to .js, switch to named js-yaml imports - Renamed api/apply/fetch/process from .mjs to .js to match repo convention (package.json has "type": "module" so .js files are already ESM) - Switched from default import to named imports for js-yaml v5 compatibility: `import { load as yamlLoad, dump as yamlDump } from "js-yaml"` - Added js-yaml as an explicit root devDependency (was previously a hoisted transitive dep from read-yaml-file@js-yaml@3.x) - Updated workflow and CLAUDE.md script references from .mjs to .js Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/version-and-publish.yml | 2 +- CLAUDE.md | 8 +- package.json | 1 + pnpm-lock.yaml | 1744 +++++++++------------ scripts/jira/{api.mjs => api.js} | 0 scripts/jira/{apply.mjs => apply.js} | 10 +- scripts/jira/apply.spec.js | 2 +- scripts/jira/{fetch.mjs => fetch.js} | 10 +- scripts/jira/fetch.spec.js | 12 +- scripts/jira/{process.mjs => process.js} | 12 +- scripts/jira/process.spec.js | 2 +- 11 files changed, 796 insertions(+), 1007 deletions(-) rename scripts/jira/{api.mjs => api.js} (100%) rename scripts/jira/{apply.mjs => apply.js} (95%) rename scripts/jira/{fetch.mjs => fetch.js} (92%) rename scripts/jira/{process.mjs => process.js} (91%) diff --git a/.github/workflows/version-and-publish.yml b/.github/workflows/version-and-publish.yml index 4b52f293e..21ba96611 100644 --- a/.github/workflows/version-and-publish.yml +++ b/.github/workflows/version-and-publish.yml @@ -67,7 +67,7 @@ jobs: run: | applied_tickets="" for file in ${{ steps.jira-files.outputs.files }}; do - ticket_key=$(node scripts/jira/process.mjs "$file") + ticket_key=$(node scripts/jira/process.js "$file") [ -n "$ticket_key" ] && applied_tickets="$applied_tickets $ticket_key" done echo "tickets=$applied_tickets" >> "$GITHUB_OUTPUT" diff --git a/CLAUDE.md b/CLAUDE.md index 703472800..f649934c1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,7 +9,7 @@ JIRA changes are version-controlled as YAML files in `.jira/`. No JIRA API calls 1. **Propose** — Run `/jira-propose` to create or update a `.jira/*.yml` file based on current git changes and context. 2. **Review** — The `.jira/` diff appears in the PR. Reviewers approve JIRA changes alongside code changes. 3. **Apply** — On merge to `main`, the `apply-jira` CI job executes each file's `updates` array against the JIRA REST API, creates a remote link back to the PR, and posts a PR comment listing updated tickets. -4. **Fetch** — After apply, the XXXX file is deleted and `fetch.mjs` writes a fresh file with the real ticket key and current JIRA state. A `[skip ci]` commit lands these changes. +4. **Fetch** — After apply, the XXXX file is deleted and `fetch.js` writes a fresh file with the real ticket key and current JIRA state. A `[skip ci]` commit lands these changes. ### File naming @@ -20,17 +20,17 @@ JIRA changes are version-controlled as YAML files in `.jira/`. No JIRA API calls ```bash # See planned JIRA calls without making them (safe for local use) -node scripts/jira/apply.mjs --dry-run .jira/PDCL-1234-my-feature.yml +node scripts/jira/apply.js --dry-run .jira/PDCL-1234-my-feature.yml # Fetch current JIRA state into a file -JIRA_API_TOKEN= node scripts/jira/fetch.mjs PDCL-1234 .jira/PDCL-1234-my-feature.yml +JIRA_API_TOKEN= node scripts/jira/fetch.js PDCL-1234 .jira/PDCL-1234-my-feature.yml ``` ### CI environment variables (Production GitHub Actions environment) | Variable | Required for | |----------|-------------| -| `JIRA_API_TOKEN` | apply.mjs and fetch.mjs API calls | +| `JIRA_API_TOKEN` | apply.js and fetch.js API calls | | `ALLOY_BOT_GITHUB_SSH_PRIVATE_KEY` | Pushing skip-ci commits to main | ### Custom fields (PDCL project) diff --git a/package.json b/package.json index 880964025..0cdfb16c7 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "globals": "^17.6.0", "happy-dom": "^20.9.0", "husky": "^9.1.7", + "js-yaml": "^5.1.0", "minimatch": "^10.2.5", "msw": "^2.14.3", "playwright": "^1.60.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8519486ed..a0b45d45a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,202 +1,3 @@ ---- -lockfileVersion: '9.0' - -importers: - - .: - configDependencies: {} - packageManagerDependencies: - '@pnpm/exe': - specifier: ^11.4.0 - version: 11.5.2 - pnpm: - specifier: ^11.4.0 - version: 11.5.2 - -packages: - - '@pnpm/exe@11.5.2': - resolution: {integrity: sha512-4UFnP2rhNu1xjAQ+I1GdIUUEtCJuTYJlbpiWSFA4POAID3Lpt+2vrjImWO7eOJ7iCY3vpc4TFe2IW3sAolW4Kg==} - hasBin: true - - '@pnpm/linux-arm64@11.5.2': - resolution: {integrity: sha512-MbJySnu2y9cCBqlODLjUlZ87JnRC3Inq40rvGHWJSrSQ0PnuHeSw2NDMnLI8Hf9hCY+ooussRc5iiR4IAkjUvg==} - cpu: [arm64] - os: [linux] - - '@pnpm/linux-x64@11.5.2': - resolution: {integrity: sha512-g6g2BGpQA47wUACy6B1MdeSHPtnl6x4AeCg0IOWQ7xXorEtC+VRiSHhLpA5kByFGeSwyYh/nLc7mLul5DAaELw==} - cpu: [x64] - os: [linux] - - '@pnpm/linuxstatic-arm64@11.5.2': - resolution: {integrity: sha512-xTxs9BLxYW39BPNGnmvYCUBnMPWm4mzmzujmdYbpRxDnBXrx55qPR5K/3LSohX7VrmsdDrYxuH6AmG1AaOlIfA==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@pnpm/linuxstatic-x64@11.5.2': - resolution: {integrity: sha512-RGmmc/SoGLD90gmOHcU85UEKNoNRstLvizli4wzDASmETz/VeqJOqU5nD1YBgjzcP72sUMS352dh4bmzTfKyvQ==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@pnpm/macos-arm64@11.5.2': - resolution: {integrity: sha512-gW3A2jRlC3SJRw8qX2SAzjMIu9o98daTSqCKzeeYcjF/uEbtbz3dn4HqYrYffBnenKbc4hsgZQmNOHAvUKIlSg==} - cpu: [arm64] - os: [darwin] - - '@pnpm/win-arm64@11.5.2': - resolution: {integrity: sha512-+VJCDoH/pRzLXBikwjvxgAnGfQufT8EALBX8cfSmrwD40JABUZvgPtjBjde7OwEoK/XwtlH8w+ZceFV0K3/YHQ==} - cpu: [arm64] - os: [win32] - - '@pnpm/win-x64@11.5.2': - resolution: {integrity: sha512-zgglREh75RbFgV/E0tNRS03ElX+hJOV43KRSSeaboxtj3ei1rrguxOgOCXUs/GsizoHVsuD+qXGABE4Kc4GMCg==} - cpu: [x64] - os: [win32] - - '@reflink/reflink-darwin-arm64@0.1.19': - resolution: {integrity: sha512-ruy44Lpepdk1FqDz38vExBY/PVUsjxZA+chd9wozjUH9JjuDT/HEaQYA6wYN9mf041l0yLVar6BCZuWABJvHSA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@reflink/reflink-darwin-x64@0.1.19': - resolution: {integrity: sha512-By85MSWrMZa+c26TcnAy8SDk0sTUkYlNnwknSchkhHpGXOtjNDUOxJE9oByBnGbeuIE1PiQsxDG3Ud+IVV9yuA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@reflink/reflink-linux-arm64-gnu@0.1.19': - resolution: {integrity: sha512-7P+er8+rP9iNeN+bfmccM4hTAaLP6PQJPKWSA4iSk2bNvo6KU6RyPgYeHxXmzNKzPVRcypZQTpFgstHam6maVg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@reflink/reflink-linux-arm64-musl@0.1.19': - resolution: {integrity: sha512-37iO/Dp6m5DDaC2sf3zPtx/hl9FV3Xze4xoYidrxxS9bgP3S8ALroxRK6xBG/1TtfXKTvolvp+IjrUU6ujIGmA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@reflink/reflink-linux-x64-gnu@0.1.19': - resolution: {integrity: sha512-jbI8jvuYCaA3MVUdu8vLoLAFqC+iNMpiSuLbxlAgg7x3K5bsS8nOpTRnkLF7vISJ+rVR8W+7ThXlXlUQ93ulkw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@reflink/reflink-linux-x64-musl@0.1.19': - resolution: {integrity: sha512-e9FBWDe+lv7QKAwtKOt6A2W/fyy/aEEfr0g6j/hWzvQcrzHCsz07BNQYlNOjTfeytrtLU7k449H1PI95jA4OjQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@reflink/reflink-win32-arm64-msvc@0.1.19': - resolution: {integrity: sha512-09PxnVIQcd+UOn4WAW73WU6PXL7DwGS6wPlkMhMg2zlHHG65F3vHepOw06HFCq+N42qkaNAc8AKIabWvtk6cIQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@reflink/reflink-win32-x64-msvc@0.1.19': - resolution: {integrity: sha512-E//yT4ni2SyhwP8JRjVGWr3cbnhWDiPLgnQ66qqaanjjnMiu3O/2tjCPQXlcGc/DEYofpDc9fvhv6tALQsMV9w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@reflink/reflink@0.1.19': - resolution: {integrity: sha512-DmCG8GzysnCZ15bres3N5AHCmwBwYgp0As6xjhQ47rAUTUXxJiK+lLUxaGsX3hd/30qUpVElh05PbGuxRPgJwA==} - engines: {node: '>= 10'} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - pnpm@11.5.2: - resolution: {integrity: sha512-ccYx44IGbvwlYl1c8CkHXeB7YbN/bic1D72Esb2lhkyMGWetwoB3a0XDCnFcA1mjvgj+9C1bsJ4rmQKZeWkpFg==} - engines: {node: '>=22.13'} - hasBin: true - -snapshots: - - '@pnpm/exe@11.5.2': - dependencies: - '@reflink/reflink': 0.1.19 - detect-libc: 2.1.2 - optionalDependencies: - '@pnpm/linux-arm64': 11.5.2 - '@pnpm/linux-x64': 11.5.2 - '@pnpm/linuxstatic-arm64': 11.5.2 - '@pnpm/linuxstatic-x64': 11.5.2 - '@pnpm/macos-arm64': 11.5.2 - '@pnpm/win-arm64': 11.5.2 - '@pnpm/win-x64': 11.5.2 - - '@pnpm/linux-arm64@11.5.2': - optional: true - - '@pnpm/linux-x64@11.5.2': - optional: true - - '@pnpm/linuxstatic-arm64@11.5.2': - optional: true - - '@pnpm/linuxstatic-x64@11.5.2': - optional: true - - '@pnpm/macos-arm64@11.5.2': - optional: true - - '@pnpm/win-arm64@11.5.2': - optional: true - - '@pnpm/win-x64@11.5.2': - optional: true - - '@reflink/reflink-darwin-arm64@0.1.19': - optional: true - - '@reflink/reflink-darwin-x64@0.1.19': - optional: true - - '@reflink/reflink-linux-arm64-gnu@0.1.19': - optional: true - - '@reflink/reflink-linux-arm64-musl@0.1.19': - optional: true - - '@reflink/reflink-linux-x64-gnu@0.1.19': - optional: true - - '@reflink/reflink-linux-x64-musl@0.1.19': - optional: true - - '@reflink/reflink-win32-arm64-msvc@0.1.19': - optional: true - - '@reflink/reflink-win32-x64-msvc@0.1.19': - optional: true - - '@reflink/reflink@0.1.19': - optionalDependencies: - '@reflink/reflink-darwin-arm64': 0.1.19 - '@reflink/reflink-darwin-x64': 0.1.19 - '@reflink/reflink-linux-arm64-gnu': 0.1.19 - '@reflink/reflink-linux-arm64-musl': 0.1.19 - '@reflink/reflink-linux-x64-gnu': 0.1.19 - '@reflink/reflink-linux-x64-musl': 0.1.19 - '@reflink/reflink-win32-arm64-msvc': 0.1.19 - '@reflink/reflink-win32-x64-msvc': 0.1.19 - - detect-libc@2.1.2: {} - - pnpm@11.5.2: {} - ---- lockfileVersion: '9.0' settings: @@ -243,13 +44,13 @@ importers: version: 6.0.1(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) '@vitest/browser-playwright': specifier: ^4.1.6 - version: 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7) + version: 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9) '@vitest/coverage-v8': specifier: ^4.1.6 - version: 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7) + version: 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) '@vitest/eslint-plugin': specifier: ^1.6.16 - version: 1.6.17(eslint@10.3.0)(typescript@6.0.3)(vitest@4.1.7) + version: 1.6.17(eslint@10.3.0)(typescript@6.0.3)(vitest@4.1.9) baseline-browser-mapping: specifier: ^2.10.27 version: 2.10.29 @@ -301,6 +102,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + js-yaml: + specifier: ^5.1.0 + version: 5.1.0 minimatch: specifier: ^10.2.5 version: 10.2.5 @@ -330,10 +134,10 @@ importers: version: 0.2.4 vitest: specifier: ^4.1.6 - version: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + version: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) vitest-browser-react: specifier: ^2.0.2 - version: 2.2.0(@types/react@19.2.14)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vitest@4.1.7) + version: 2.2.0(@types/react@19.2.14)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vitest@4.1.9) packages/browser: dependencies: @@ -388,13 +192,13 @@ importers: version: 14.0.0 vitest: specifier: ^4.1.6 - version: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + version: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) packages/core: dependencies: '@adobe/aep-rules-engine': specifier: ^3.1.1 - version: 3.1.1(@vitest/browser@4.1.7)(vitest@4.1.7) + version: 3.1.1(@vitest/browser@4.1.9)(vitest@4.1.9) '@adobe/reactor-query-string': specifier: ^2.0.0 version: 2.0.0 @@ -781,8 +585,8 @@ packages: resolution: {integrity: sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==} engines: {node: '>=20.0.0'} - '@azure/core-client@1.10.1': - resolution: {integrity: sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==} + '@azure/core-client@1.10.2': + resolution: {integrity: sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==} engines: {node: '>=20.0.0'} '@azure/core-lro@2.7.2': @@ -793,8 +597,8 @@ packages: resolution: {integrity: sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA==} engines: {node: '>=18.0.0'} - '@azure/core-rest-pipeline@1.23.0': - resolution: {integrity: sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ==} + '@azure/core-rest-pipeline@1.24.0': + resolution: {integrity: sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==} engines: {node: '>=20.0.0'} '@azure/core-tracing@1.3.1': @@ -813,20 +617,20 @@ packages: resolution: {integrity: sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==} engines: {node: '>=20.0.0'} - '@azure/msal-browser@5.11.0': - resolution: {integrity: sha512-zkGNYS3TwY8lUpPIafAmsFCYZbgFixY9y/LZB9GUg0IILoHTqpN26j5OrkL1AQThh/YdZsawe4iWXfp85lFVxg==} + '@azure/msal-browser@5.15.0': + resolution: {integrity: sha512-2NYT6v+eeQn8kmNddr9LnbXSvXbVELpmFMmfFvtRxD7I/5+5GlkMlncApeuRFj+mY6C9syOwQip1a0Y+TIbyiA==} engines: {node: '>=0.8.0'} '@azure/msal-common@14.16.1': resolution: {integrity: sha512-nyxsA6NA4SVKh5YyRpbSXiMr7oQbwark7JU9LMeg6tJYTSPyAGkdx61wPT4gyxZfxlSxMMEyAsWaubBlNyIa1w==} engines: {node: '>=0.8.0'} - '@azure/msal-common@16.6.2': - resolution: {integrity: sha512-hQjjsekAjB00cM1EmatWJlzhEoK2Qhz7Rj5gvM6tYf8iL7RM3tkxlpU9fG0+ofkulzg9AEEA6dIEnSmDr5ZqUA==} + '@azure/msal-common@16.10.0': + resolution: {integrity: sha512-iYtjpanlv6963Jprs0MvzIap07V+QhultjQctfbEDQCflsDAEeO3R7XnVA5gk30fhoBFLdgJT7VqO0TGsEsN9w==} engines: {node: '>=0.8.0'} - '@azure/msal-node@5.2.2': - resolution: {integrity: sha512-toS+2AePxqyzb0YOKttDOOiSl3jrkK9aiqIvpurpis0O34QcIS5gToqrgT39p04Dpxw3YoUU0lxJKTpSFFfA6Q==} + '@azure/msal-node@5.3.0': + resolution: {integrity: sha512-fXtJX811pX8y8QlrQqBSH6+plvWyKZDI0IxkheAcyAw9OtcpXyFivmTC7eGUqutLWaDlKXuQ3yOESD4zAmkjHg==} engines: {node: '>=20'} '@azure/static-web-apps-cli@2.0.9': @@ -979,18 +783,10 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': - resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.29.7': - resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} @@ -1007,13 +803,18 @@ packages: resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} engines: {node: '>=6.9.0'} + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/parser@7.29.2': resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.29.7': - resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} engines: {node: '>=6.0.0'} hasBin: true @@ -1490,12 +1291,12 @@ packages: resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.7': - resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -2751,8 +2552,8 @@ packages: resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} engines: {node: '>=12.22.0'} - '@pnpm/npm-conf@3.0.2': - resolution: {integrity: sha512-h104Kh26rR8tm+a3Qkc5S4VLYint3FE48as7+/5oCEcKR2idC/pF1G6AhIXKI+eHPJa/3J9i5z0Al47IeGHPkA==} + '@pnpm/npm-conf@3.0.3': + resolution: {integrity: sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA==} engines: {node: '>=12'} '@polka/url@1.0.0-next.29': @@ -4535,8 +4336,8 @@ packages: '@types/node@20.14.5': resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} - '@types/node@22.19.19': - resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + '@types/node@22.20.0': + resolution: {integrity: sha512-QWlFW2wf3nTjC13/DqRnBpR4ZO36VJH/JVBkA/vcnmbTBNQIlnObqyqZE1tUR7+Ni23Lda8R1BxMfbXRpCUx5g==} '@types/node@25.6.2': resolution: {integrity: sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==} @@ -4614,8 +4415,8 @@ packages: resolution: {integrity: sha512-y+vH7QE8ycjoa0bWciFg7OpFcipUuem1ujhrdLtq1gByKwfbC7bPeKsiny9e0urg93DqwGcHey+bGRKCnF1nZQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typespec/ts-http-runtime@0.3.5': - resolution: {integrity: sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw==} + '@typespec/ts-http-runtime@0.3.6': + resolution: {integrity: sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==} engines: {node: '>=20.0.0'} '@vitejs/plugin-react@6.0.1': @@ -4631,16 +4432,16 @@ packages: babel-plugin-react-compiler: optional: true - '@vitest/browser-playwright@4.1.7': - resolution: {integrity: sha512-OlTlJej7YN6VwV7zJJoNeaCsctF+JXpzpZ4oBHUbrQFfIq+0KW2f07rprCLh9N/zRIZ0v4Mchn1QDDmWMUhPKw==} + '@vitest/browser-playwright@4.1.9': + resolution: {integrity: sha512-Bq1rOGf9waevzG3EOkO/dene6bvKTUsZMVg8S1i+WH3JcMjuXEjiahP9rAqZRELUqjBySOJsvvSWqK/B3wjKQw==} peerDependencies: playwright: '*' - vitest: 4.1.7 + vitest: 4.1.9 - '@vitest/browser@4.1.7': - resolution: {integrity: sha512-N2JFGfXoEGVAut+kHeru9dD4BUMq/q5xDvBARNl0tUsly3m5KglLOu8VO/6MkDfOlgxXTycojkt6gBKsuyR+IQ==} + '@vitest/browser@4.1.9': + resolution: {integrity: sha512-j1BKtWmPcqpMhmx/L9EPLgAJpCb0zKfwoWLmqBbxaogCXHjOwHFSEoHCBfnGtx93xKQwilZ26m+UOsHqHMkRNg==} peerDependencies: - vitest: 4.1.7 + vitest: 4.1.9 '@vitest/coverage-v8@3.2.4': resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} @@ -4651,11 +4452,11 @@ packages: '@vitest/browser': optional: true - '@vitest/coverage-v8@4.1.7': - resolution: {integrity: sha512-qsYPeXc5Q9dFLd1i8Ap+Bx8sQgcp+rFVQo4R0dDsWNBzl26ldVF1qOO+RL24K7FDrR6pA+50XedRLSoSG24bVQ==} + '@vitest/coverage-v8@4.1.9': + resolution: {integrity: sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g==} peerDependencies: - '@vitest/browser': 4.1.7 - vitest: 4.1.7 + '@vitest/browser': 4.1.9 + vitest: 4.1.9 peerDependenciesMeta: '@vitest/browser': optional: true @@ -4676,11 +4477,11 @@ packages: vitest: optional: true - '@vitest/expect@4.1.7': - resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==} + '@vitest/expect@4.1.9': + resolution: {integrity: sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA==} - '@vitest/mocker@4.1.7': - resolution: {integrity: sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==} + '@vitest/mocker@4.1.9': + resolution: {integrity: sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -4690,20 +4491,20 @@ packages: vite: optional: true - '@vitest/pretty-format@4.1.7': - resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==} + '@vitest/pretty-format@4.1.9': + resolution: {integrity: sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A==} - '@vitest/runner@4.1.7': - resolution: {integrity: sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==} + '@vitest/runner@4.1.9': + resolution: {integrity: sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg==} - '@vitest/snapshot@4.1.7': - resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==} + '@vitest/snapshot@4.1.9': + resolution: {integrity: sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA==} - '@vitest/spy@4.1.7': - resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==} + '@vitest/spy@4.1.9': + resolution: {integrity: sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA==} - '@vitest/utils@4.1.7': - resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} + '@vitest/utils@4.1.9': + resolution: {integrity: sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA==} '@zeit/schemas@2.36.0': resolution: {integrity: sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==} @@ -4979,8 +4780,8 @@ packages: resolution: {integrity: sha512-byD6KPdvo72y/wj2T/4zGEvvlis+PsZsn/yPS3pEO+sFpcrqRpX/TJCxvVaEsNeMrfQbCr7w163YqoD9IYwHXw==} engines: {node: '>=4'} - axios@1.16.1: - resolution: {integrity: sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==} + axios@1.18.1: + resolution: {integrity: sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==} axobject-query@4.1.0: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} @@ -5152,11 +4953,11 @@ packages: brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} - brace-expansion@2.1.1: - resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - brace-expansion@5.0.6: - resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + brace-expansion@5.0.5: + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} engines: {node: 18 || 20 || >=22} braces@3.0.3: @@ -6292,8 +6093,8 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + form-data@4.0.6: + resolution: {integrity: sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==} engines: {node: '>= 6'} formdata-polyfill@4.0.10: @@ -6541,6 +6342,10 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} + engines: {node: '>= 0.4'} + headers-polyfill@5.0.1: resolution: {integrity: sha512-1TJ6Fih/b8h5TIcv+1+Hw0PDQWJTKDKzFZzcKOiW1wJza3XoAQlkCuXLbymPYB8+ZQyw8mHvdw560e8zVFIWyA==} @@ -6993,8 +6798,8 @@ packages: resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} engines: {node: 20 || >=22} - joi@17.13.3: - resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==} + joi@17.13.4: + resolution: {integrity: sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ==} jose@6.2.3: resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==} @@ -7034,6 +6839,10 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + js-yaml@5.1.0: + resolution: {integrity: sha512-s8VA5jkR8f22S3NAXmhKPFqGUduqZGlsufabVOgN14iTdw/RXcym7bKkbwjxLK9Yw2lEvvmJjFp119+KPeo8Kg==} + hasBin: true + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -9208,6 +9017,10 @@ packages: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tinyglobby@0.2.16: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} @@ -9550,20 +9363,20 @@ packages: '@types/react-dom': optional: true - vitest@4.1.7: - resolution: {integrity: sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==} + vitest@4.1.9: + resolution: {integrity: sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ==} engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' '@opentelemetry/api': ^1.9.0 '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.7 - '@vitest/browser-preview': 4.1.7 - '@vitest/browser-webdriverio': 4.1.7 - '@vitest/coverage-istanbul': 4.1.7 - '@vitest/coverage-v8': 4.1.7 - '@vitest/ui': 4.1.7 + '@vitest/browser-playwright': 4.1.9 + '@vitest/browser-preview': 4.1.9 + '@vitest/browser-webdriverio': 4.1.9 + '@vitest/coverage-istanbul': 4.1.9 + '@vitest/coverage-v8': 4.1.9 + '@vitest/ui': 4.1.9 happy-dom: '*' jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -9783,9 +9596,9 @@ packages: snapshots: - '@adobe/aep-rules-engine@3.1.1(@vitest/browser@4.1.7)(vitest@4.1.7)': + '@adobe/aep-rules-engine@3.1.1(@vitest/browser@4.1.9)(vitest@4.1.9)': dependencies: - '@vitest/coverage-v8': 3.2.4(@vitest/browser@4.1.7)(vitest@4.1.7) + '@vitest/coverage-v8': 3.2.4(@vitest/browser@4.1.9)(vitest@4.1.9) transitivePeerDependencies: - '@vitest/browser' - supports-color @@ -9840,59 +9653,59 @@ snapshots: '@react-aria/ssr': 3.9.10(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/visually-hidden': 3.8.31(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/accordion': 3.0.16(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/actionbar': 3.6.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/avatar': 3.0.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/badge': 3.1.33(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/breadcrumbs': 3.9.27(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/color': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/combobox': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/contextualhelp': 3.6.31(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/datepicker': 3.14.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/accordion': 3.0.16(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/actionbar': 3.6.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/avatar': 3.0.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/badge': 3.1.33(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/breadcrumbs': 3.9.27(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/color': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/combobox': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/contextualhelp': 3.6.31(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/datepicker': 3.14.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/divider': 3.5.30(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dropzone': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/filetrigger': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/illustratedmessage': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/image': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/inlinealert': 3.2.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/labeledvalue': 3.2.10(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/link': 3.6.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/list': 3.10.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/meter': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/numberfield': 3.10.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dropzone': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/filetrigger': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/illustratedmessage': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/image': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/inlinealert': 3.2.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/labeledvalue': 3.2.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/link': 3.6.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/list': 3.10.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/meter': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/numberfield': 3.10.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/radio': 3.7.24(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/searchfield': 3.8.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/slider': 3.8.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/statuslight': 3.5.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/switch': 3.6.9(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/table': 3.17.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tabs': 3.8.30(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tag': 3.3.10(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/radio': 3.7.24(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/searchfield': 3.8.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/slider': 3.8.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/statuslight': 3.5.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/switch': 3.6.9(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/table': 3.17.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/tabs': 3.8.30(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/tag': 3.3.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/theme-dark': 3.5.24(react@17.0.2) '@react-spectrum/theme-default': 3.5.24(react@17.0.2) '@react-spectrum/theme-light': 3.4.24(react@17.0.2) - '@react-spectrum/toast': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tree': 3.1.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/toast': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/tree': 3.1.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/well': 3.4.30(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/data': 3.15.2(react@17.0.2) @@ -9909,59 +9722,59 @@ snapshots: '@react-aria/ssr': 3.9.10(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/visually-hidden': 3.8.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/accordion': 3.0.16(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/actionbar': 3.6.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/avatar': 3.0.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/badge': 3.1.33(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/breadcrumbs': 3.9.27(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/color': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/combobox': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/contextualhelp': 3.6.31(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/datepicker': 3.14.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/accordion': 3.0.16(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/actionbar': 3.6.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/avatar': 3.0.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/badge': 3.1.33(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/breadcrumbs': 3.9.27(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/color': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/combobox': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/contextualhelp': 3.6.31(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/datepicker': 3.14.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/divider': 3.5.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dropzone': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/filetrigger': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/illustratedmessage': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/image': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/inlinealert': 3.2.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/labeledvalue': 3.2.10(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/link': 3.6.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/list': 3.10.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/meter': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/numberfield': 3.10.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dropzone': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/filetrigger': 3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/illustratedmessage': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/image': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/inlinealert': 3.2.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/labeledvalue': 3.2.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/link': 3.6.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/list': 3.10.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/meter': 3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/numberfield': 3.10.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/radio': 3.7.24(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/searchfield': 3.8.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/slider': 3.8.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/statuslight': 3.5.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/switch': 3.6.9(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/table': 3.17.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tabs': 3.8.30(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tag': 3.3.10(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/radio': 3.7.24(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/searchfield': 3.8.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/slider': 3.8.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/statuslight': 3.5.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/switch': 3.6.9(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/table': 3.17.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/tabs': 3.8.30(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/tag': 3.3.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/theme-dark': 3.5.24(react@18.3.1) '@react-spectrum/theme-default': 3.5.24(react@18.3.1) '@react-spectrum/theme-light': 3.4.24(react@18.3.1) - '@react-spectrum/toast': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tree': 3.1.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/toast': 3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/tree': 3.1.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/well': 3.4.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/data': 3.15.2(react@18.3.1) @@ -10184,7 +9997,7 @@ snapshots: '@adobe/auth-token': 1.0.1(@types/node@25.6.2) chalk: 4.1.2 delay: 4.4.1 - form-data: 4.0.5 + form-data: 4.0.6 inquirer: 10.2.2 node-fetch: 2.7.0 ora: 5.4.1 @@ -10271,10 +10084,10 @@ snapshots: dependencies: '@azure/abort-controller': 1.1.0 '@azure/core-auth': 1.10.1 - '@azure/core-client': 1.10.1 + '@azure/core-client': 1.10.2 '@azure/core-lro': 2.7.2 '@azure/core-paging': 1.6.2 - '@azure/core-rest-pipeline': 1.23.0 + '@azure/core-rest-pipeline': 1.24.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10283,10 +10096,10 @@ snapshots: dependencies: '@azure/abort-controller': 1.1.0 '@azure/core-auth': 1.10.1 - '@azure/core-client': 1.10.1 + '@azure/core-client': 1.10.2 '@azure/core-lro': 2.7.2 '@azure/core-paging': 1.6.2 - '@azure/core-rest-pipeline': 1.23.0 + '@azure/core-rest-pipeline': 1.24.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10295,10 +10108,10 @@ snapshots: dependencies: '@azure/abort-controller': 2.1.2 '@azure/core-auth': 1.10.1 - '@azure/core-client': 1.10.1 + '@azure/core-client': 1.10.2 '@azure/core-lro': 2.7.2 '@azure/core-paging': 1.6.2 - '@azure/core-rest-pipeline': 1.23.0 + '@azure/core-rest-pipeline': 1.24.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10311,11 +10124,11 @@ snapshots: transitivePeerDependencies: - supports-color - '@azure/core-client@1.10.1': + '@azure/core-client@1.10.2': dependencies: '@azure/abort-controller': 2.1.2 '@azure/core-auth': 1.10.1 - '@azure/core-rest-pipeline': 1.23.0 + '@azure/core-rest-pipeline': 1.24.0 '@azure/core-tracing': 1.3.1 '@azure/core-util': 1.13.1 '@azure/logger': 1.3.0 @@ -10336,14 +10149,14 @@ snapshots: dependencies: tslib: 2.8.1 - '@azure/core-rest-pipeline@1.23.0': + '@azure/core-rest-pipeline@1.24.0': dependencies: '@azure/abort-controller': 2.1.2 '@azure/core-auth': 1.10.1 '@azure/core-tracing': 1.3.1 '@azure/core-util': 1.13.1 '@azure/logger': 1.3.0 - '@typespec/ts-http-runtime': 0.3.5 + '@typespec/ts-http-runtime': 0.3.6 tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10355,7 +10168,7 @@ snapshots: '@azure/core-util@1.13.1': dependencies: '@azure/abort-controller': 2.1.2 - '@typespec/ts-http-runtime': 0.3.5 + '@typespec/ts-http-runtime': 0.3.6 tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -10364,13 +10177,13 @@ snapshots: dependencies: '@azure/abort-controller': 2.1.2 '@azure/core-auth': 1.10.1 - '@azure/core-client': 1.10.1 - '@azure/core-rest-pipeline': 1.23.0 + '@azure/core-client': 1.10.2 + '@azure/core-rest-pipeline': 1.24.0 '@azure/core-tracing': 1.3.1 '@azure/core-util': 1.13.1 '@azure/logger': 1.3.0 - '@azure/msal-browser': 5.11.0 - '@azure/msal-node': 5.2.2 + '@azure/msal-browser': 5.15.0 + '@azure/msal-node': 5.3.0 open: 10.2.0 tslib: 2.8.1 transitivePeerDependencies: @@ -10378,22 +10191,22 @@ snapshots: '@azure/logger@1.3.0': dependencies: - '@typespec/ts-http-runtime': 0.3.5 + '@typespec/ts-http-runtime': 0.3.6 tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/msal-browser@5.11.0': + '@azure/msal-browser@5.15.0': dependencies: - '@azure/msal-common': 16.6.2 + '@azure/msal-common': 16.10.0 '@azure/msal-common@14.16.1': {} - '@azure/msal-common@16.6.2': {} + '@azure/msal-common@16.10.0': {} - '@azure/msal-node@5.2.2': + '@azure/msal-node@5.3.0': dependencies: - '@azure/msal-common': 16.6.2 + '@azure/msal-common': 16.10.0 jsonwebtoken: 9.0.3 '@azure/static-web-apps-cli@2.0.9': @@ -10461,7 +10274,7 @@ snapshots: '@babel/code-frame@7.29.0': dependencies: - '@babel/helper-validator-identifier': 7.29.7 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 @@ -10527,8 +10340,8 @@ snapshots: '@babel/generator@7.29.1': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 '@jridgewell/gen-mapping': 0.3.13 '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 @@ -10642,7 +10455,7 @@ snapshots: '@babel/helper-member-expression-to-functions@7.27.1': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color @@ -10689,7 +10502,7 @@ snapshots: '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 '@babel/helper-plugin-utils@7.27.1': {} @@ -10734,25 +10547,21 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: '@babel/traverse': 7.28.5 - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-validator-identifier@7.28.5': {} - '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-option@7.27.1': {} '@babel/helper-wrap-function@7.28.3': dependencies: '@babel/template': 7.27.2 '@babel/traverse': 7.28.5 - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color @@ -10764,15 +10573,19 @@ snapshots: '@babel/helpers@7.29.2': dependencies: '@babel/template': 7.28.6 - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 + + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.29.0 '@babel/parser@7.29.2': dependencies: '@babel/types': 7.29.0 - '@babel/parser@7.29.7': + '@babel/parser@7.29.3': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.5)': dependencies: @@ -11873,8 +11686,8 @@ snapshots: '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 '@babel/traverse@7.28.5': dependencies: @@ -11900,15 +11713,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': + '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@7.29.7': + '@babel/types@7.29.0': dependencies: - '@babel/helper-string-parser': 7.29.7 - '@babel/helper-validator-identifier': 7.29.7 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 '@bcoe/v8-coverage@1.0.2': {} @@ -12488,7 +12301,7 @@ snapshots: '@inquirer/figures': 1.0.14 '@inquirer/type': 2.0.0 '@types/mute-stream': 0.0.4 - '@types/node': 22.19.19 + '@types/node': 22.20.0 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 cli-width: 4.1.0 @@ -13529,7 +13342,7 @@ snapshots: detect-libc: 2.1.2 is-glob: 4.0.3 node-addon-api: 7.1.1 - picomatch: 4.0.4 + picomatch: 4.0.3 optionalDependencies: '@parcel/watcher-android-arm64': 2.5.6 '@parcel/watcher-darwin-arm64': 2.5.6 @@ -13568,7 +13381,7 @@ snapshots: dependencies: graceful-fs: 4.2.10 - '@pnpm/npm-conf@3.0.2': + '@pnpm/npm-conf@3.0.3': dependencies: '@pnpm/config.env-replace': 1.1.0 '@pnpm/network.ca-file': 1.0.2 @@ -15596,25 +15409,25 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/accordion@3.0.16(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/accordion@3.0.16(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/accordion@3.0.16(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/accordion@3.0.16(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-aria-components: 1.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15632,44 +15445,44 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/actionbar@3.6.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/actionbar@3.6.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/live-announcer': 3.4.4 '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-types/actionbar': 3.1.21(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/actionbar@3.6.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/actionbar@3.6.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/live-announcer': 3.4.4 '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/actiongroup': 3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-types/actionbar': 3.1.21(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -15695,48 +15508,48 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/actiongroup@3.11.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/actiongroup@3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/actiongroup': 3.7.24(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/list': 3.13.4(react@17.0.2) '@react-types/actiongroup': 3.4.23(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/actiongroup@3.11.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/actiongroup@3.11.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/actiongroup': 3.7.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/list': 3.13.4(react@18.3.1) '@react-types/actiongroup': 3.4.23(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -15764,10 +15577,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/avatar@3.0.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/avatar@3.0.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/avatar': 3.0.21(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -15775,10 +15588,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/avatar@3.0.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/avatar@3.0.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/avatar': 3.0.21(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -15797,11 +15610,11 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/badge@3.1.33(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/badge@3.1.33(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/badge': 3.1.23(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -15809,11 +15622,11 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/badge@3.1.33(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/badge@3.1.33(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/badge': 3.1.23(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -15833,40 +15646,40 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/breadcrumbs@3.9.27(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/breadcrumbs@3.9.27(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/breadcrumbs': 3.5.32(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-types/breadcrumbs': 3.7.19(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/breadcrumbs@3.9.27(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/breadcrumbs@3.9.27(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/breadcrumbs': 3.5.32(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-types/breadcrumbs': 3.7.19(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -15890,40 +15703,40 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/button@3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/button@3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/toggle': 3.9.5(react@17.0.2) '@react-types/button': 3.15.1(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/button@3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/button@3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/toggle': 3.9.5(react@18.3.1) '@react-types/button': 3.15.1(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -15947,10 +15760,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/buttongroup@3.6.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/buttongroup@3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/buttongroup': 3.3.23(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -15958,10 +15771,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/buttongroup@3.6.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/buttongroup@3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/buttongroup': 3.3.23(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -15980,7 +15793,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/calendar@3.7.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/calendar@3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/calendar': 3.9.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -15989,20 +15802,20 @@ snapshots: '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/visually-hidden': 3.8.31(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/calendar': 3.9.3(react@17.0.2) '@react-types/button': 3.15.1(react@17.0.2) '@react-types/calendar': 3.8.3(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/calendar@3.7.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/calendar@3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/calendar': 3.9.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16011,15 +15824,15 @@ snapshots: '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/visually-hidden': 3.8.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/calendar': 3.9.3(react@18.3.1) '@react-types/button': 3.15.1(react@18.3.1) '@react-types/calendar': 3.8.3(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16046,39 +15859,39 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/checkbox@3.10.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/checkbox@3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/checkbox': 3.16.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/checkbox': 3.7.5(react@17.0.2) '@react-stately/toggle': 3.9.5(react@17.0.2) '@react-types/checkbox': 3.10.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/checkbox@3.10.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/checkbox@3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/checkbox': 3.16.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/checkbox': 3.7.5(react@18.3.1) '@react-stately/toggle': 3.9.5(react@18.3.1) '@react-types/checkbox': 3.10.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-aria-components: 1.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16103,22 +15916,22 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/color@3.1.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/color@3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/color': 3.1.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/color': 3.9.5(react@17.0.2) '@react-types/color': 3.1.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -16128,22 +15941,22 @@ snapshots: react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/color@3.1.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/color@3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/color': 3.1.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/color': 3.9.5(react@18.3.1) '@react-types/color': 3.1.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -16178,7 +15991,7 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/combobox@3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/combobox@3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/combobox': 3.15.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -16190,26 +16003,26 @@ snapshots: '@react-aria/label': 3.7.25(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/combobox': 3.13.0(react@17.0.2) '@react-types/button': 3.15.1(react@17.0.2) '@react-types/combobox': 3.14.0(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/combobox@3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/combobox@3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/combobox': 3.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16221,21 +16034,21 @@ snapshots: '@react-aria/label': 3.7.25(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/combobox': 3.13.0(react@18.3.1) '@react-types/button': 3.15.1(react@18.3.1) '@react-types/combobox': 3.14.0(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16271,32 +16084,32 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/contextualhelp@3.6.31(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/contextualhelp@3.6.31(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/contextualhelp': 3.2.24(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/contextualhelp@3.6.31(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/contextualhelp@3.6.31(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/contextualhelp': 3.2.24(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16316,7 +16129,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/datepicker@3.14.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/datepicker@3.14.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/datepicker': 3.16.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -16324,25 +16137,25 @@ snapshots: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/datepicker': 3.16.1(react@17.0.2) '@react-types/datepicker': 3.13.5(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/datepicker@3.14.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/datepicker@3.14.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/datepicker': 3.16.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16350,20 +16163,20 @@ snapshots: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/calendar': 3.7.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dialog': 3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/datepicker': 3.16.1(react@18.3.1) '@react-types/datepicker': 3.13.5(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16394,52 +16207,52 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/dialog@3.9.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/dialog@3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/dialog': 3.5.34(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/divider': 3.5.30(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/overlays': 3.6.23(react@17.0.2) '@react-types/button': 3.15.1(react@17.0.2) '@react-types/dialog': 3.5.24(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/dialog@3.9.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/dialog@3.9.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/dialog': 3.5.34(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/buttongroup': 3.6.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/divider': 3.5.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/view': 3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/overlays': 3.6.23(react@18.3.1) '@react-types/button': 3.15.1(react@18.3.1) '@react-types/dialog': 3.5.24(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16499,20 +16312,20 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/dnd@3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/dnd@3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/dnd': 3.11.6(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-stately/dnd': 3.7.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/dnd@3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/dnd@3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/dnd': 3.11.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-stately/dnd': 3.7.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@swc/helpers': 0.5.21 @@ -16529,11 +16342,11 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/dropzone@3.0.21(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/dropzone@3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@swc/helpers': 0.5.21 @@ -16541,11 +16354,11 @@ snapshots: react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/dropzone@3.0.21(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/dropzone@3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@swc/helpers': 0.5.21 @@ -16565,17 +16378,17 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/filetrigger@3.0.21(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/filetrigger@3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@swc/helpers': 0.5.21 react: 17.0.2 react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/filetrigger@3.0.21(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/filetrigger@3.0.21(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@swc/helpers': 0.5.21 react: 18.3.1 react-aria-components: 1.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16589,10 +16402,10 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/form@3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/form@3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/form': 3.2.4(react@17.0.2) '@react-types/form': 3.7.18(react@17.0.2) @@ -16601,10 +16414,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/form@3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/form@3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/form': 3.2.4(react@18.3.1) '@react-types/form': 3.7.18(react@18.3.1) @@ -16625,26 +16438,6 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/icon@3.8.12(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-types/shared': 3.33.1(react@17.0.2) - '@swc/helpers': 0.5.21 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - '@react-spectrum/icon@3.8.12(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-types/shared': 3.33.1(react@18.3.1) - '@swc/helpers': 0.5.21 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@react-spectrum/icon@3.8.12(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -16675,11 +16468,11 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/illustratedmessage@3.5.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/illustratedmessage@3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/illustratedmessage': 3.3.23(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -16687,11 +16480,11 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/illustratedmessage@3.5.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/illustratedmessage@3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/illustratedmessage': 3.3.23(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -16711,10 +16504,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/image@3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/image@3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/image': 3.5.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -16722,10 +16515,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/image@3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/image@3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/image': 3.5.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -16744,30 +16537,30 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/inlinealert@3.2.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/inlinealert@3.2.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/inlinealert@3.2.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/inlinealert@3.2.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16786,32 +16579,32 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/label@3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/label@3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/label': 3.9.17(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/label@3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/label@3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/label': 3.9.17(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -16831,26 +16624,26 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/labeledvalue@3.2.10(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/labeledvalue@3.2.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/labeledvalue@3.2.10(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/labeledvalue@3.2.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@internationalized/date': 3.12.0 '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@swc/helpers': 0.5.21 @@ -16870,10 +16663,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/layout@3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/layout@3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/layout': 3.3.29(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -16881,10 +16674,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/layout@3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/layout@3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/layout': 3.3.29(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -16903,13 +16696,13 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/link@3.6.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/link@3.6.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/link': 3.8.9(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/link': 3.6.7(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -16917,13 +16710,13 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/link@3.6.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/link@3.6.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/link': 3.8.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/link': 3.6.7(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -16945,7 +16738,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/list@3.10.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/list@3.10.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -16956,12 +16749,12 @@ snapshots: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/virtualizer': 4.1.13(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/visually-hidden': 3.8.31(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/layout': 4.6.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -16969,13 +16762,13 @@ snapshots: '@react-stately/virtualizer': 4.4.6(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/grid': 3.3.8(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) react-transition-group: 4.4.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/list@3.10.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/list@3.10.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16986,12 +16779,12 @@ snapshots: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/virtualizer': 4.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/visually-hidden': 3.8.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/layout': 4.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -16999,7 +16792,7 @@ snapshots: '@react-stately/virtualizer': 4.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/grid': 3.3.8(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17035,7 +16828,7 @@ snapshots: react-dom: 19.2.0(react@19.2.0) react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@react-spectrum/listbox@3.15.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/listbox@3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17043,10 +16836,10 @@ snapshots: '@react-aria/listbox': 3.15.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/virtualizer': 4.1.13(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/layout': 4.6.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17054,12 +16847,12 @@ snapshots: '@react-stately/virtualizer': 4.4.6(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/listbox': 3.7.6(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/listbox@3.15.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/listbox@3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17067,10 +16860,10 @@ snapshots: '@react-aria/listbox': 3.15.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/virtualizer': 4.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/layout': 4.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17078,7 +16871,7 @@ snapshots: '@react-stately/virtualizer': 4.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/listbox': 3.7.6(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17107,7 +16900,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/menu@3.22.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/menu@3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17116,11 +16909,11 @@ snapshots: '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/separator': 3.4.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/menu': 3.9.11(react@17.0.2) @@ -17129,13 +16922,13 @@ snapshots: '@react-types/menu': 3.10.7(react@17.0.2) '@react-types/overlays': 3.9.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/menu@3.22.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/menu@3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17144,11 +16937,11 @@ snapshots: '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/separator': 3.4.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/menu': 3.9.11(react@18.3.1) @@ -17157,8 +16950,8 @@ snapshots: '@react-types/menu': 3.10.7(react@18.3.1) '@react-types/overlays': 3.9.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17191,11 +16984,11 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/meter@3.5.17(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/meter@3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/meter': 3.4.30(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/meter': 3.4.15(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -17203,11 +16996,11 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/meter@3.5.17(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/meter@3.5.17(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/meter': 3.4.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/meter': 3.4.15(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -17227,7 +17020,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/numberfield@3.10.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/numberfield@3.10.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17235,22 +17028,22 @@ snapshots: '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/numberfield': 3.12.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/numberfield': 3.11.0(react@17.0.2) '@react-types/button': 3.15.1(react@17.0.2) '@react-types/numberfield': 3.8.18(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/numberfield@3.10.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/numberfield@3.10.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17258,17 +17051,17 @@ snapshots: '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/numberfield': 3.12.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/numberfield': 3.11.0(react@18.3.1) '@react-types/button': 3.15.1(react@18.3.1) '@react-types/numberfield': 3.8.18(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/workflow': 4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17296,12 +17089,12 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/overlays@5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/overlays@5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/overlays': 3.6.23(react@17.0.2) '@react-types/overlays': 3.9.4(react@17.0.2) @@ -17311,12 +17104,12 @@ snapshots: react-dom: 17.0.2(react@17.0.2) react-transition-group: 4.4.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays@5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/overlays@5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/overlays': 3.6.23(react@18.3.1) '@react-types/overlays': 3.9.4(react@18.3.1) @@ -17341,50 +17134,50 @@ snapshots: react-dom: 19.2.0(react@19.2.0) react-transition-group: 4.4.5(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@react-spectrum/picker@3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/picker@3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/select': 3.17.3(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/select': 3.9.2(react@17.0.2) '@react-types/select': 3.12.2(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/picker@3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/picker@3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/select': 3.17.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/listbox': 3.15.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/select': 3.9.2(react@18.3.1) '@react-types/select': 3.12.2(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17413,11 +17206,11 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/progress@3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/progress@3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/progress': 3.4.30(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/progress': 3.5.18(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -17425,11 +17218,11 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/progress@3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/progress@3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/progress': 3.4.30(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/progress': 3.5.18(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -17488,14 +17281,14 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/radio@3.7.24(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/radio@3.7.24(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/radio': 3.12.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/radio': 3.11.5(react@17.0.2) '@react-types/radio': 3.9.4(react@17.0.2) @@ -17504,14 +17297,14 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/radio@3.7.24(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/radio@3.7.24(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/radio': 3.12.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/radio': 3.11.5(react@18.3.1) '@react-types/radio': 3.9.4(react@18.3.1) @@ -17536,34 +17329,34 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/searchfield@3.8.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/searchfield@3.8.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/searchfield': 3.8.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/searchfield': 3.5.19(react@17.0.2) '@react-types/searchfield': 3.6.8(react@17.0.2) '@react-types/textfield': 3.12.8(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/searchfield@3.8.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/searchfield@3.8.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/searchfield': 3.8.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/textfield': 3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/searchfield': 3.5.19(react@18.3.1) '@react-types/searchfield': 3.6.8(react@18.3.1) '@react-types/textfield': 3.12.8(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17584,7 +17377,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/slider@3.8.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/slider@3.8.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17592,7 +17385,7 @@ snapshots: '@react-aria/slider': 3.8.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/visually-hidden': 3.8.31(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/slider': 3.7.5(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -17601,7 +17394,7 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/slider@3.8.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/slider@3.8.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17609,7 +17402,7 @@ snapshots: '@react-aria/slider': 3.8.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/visually-hidden': 3.8.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/slider': 3.7.5(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -17635,10 +17428,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/statuslight@3.5.29(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/statuslight@3.5.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/statuslight': 3.3.23(react@17.0.2) @@ -17646,10 +17439,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/statuslight@3.5.29(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/statuslight@3.5.29(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/statuslight': 3.3.23(react@18.3.1) @@ -17668,12 +17461,12 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/switch@3.6.9(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/switch@3.6.9(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/switch': 3.7.11(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/toggle': 3.9.5(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) @@ -17682,12 +17475,12 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/switch@3.6.9(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/switch@3.6.9(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/switch': 3.7.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/toggle': 3.9.5(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) @@ -17710,7 +17503,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/table@3.17.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/table@3.17.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17722,13 +17515,13 @@ snapshots: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/virtualizer': 4.1.13(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/visually-hidden': 3.8.31(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/flags': 3.1.2 '@react-stately/layout': 4.6.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17737,12 +17530,12 @@ snapshots: '@react-types/grid': 3.3.8(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/table': 3.13.6(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/table@3.17.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/table@3.17.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17754,13 +17547,13 @@ snapshots: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/virtualizer': 4.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/visually-hidden': 3.8.31(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/dnd': 3.6.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/layout': 3.6.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/menu': 3.22.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/progress': 3.7.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/tooltip': 3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/flags': 3.1.2 '@react-stately/layout': 4.6.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17769,7 +17562,7 @@ snapshots: '@react-types/grid': 3.3.8(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/table': 3.13.6(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -17806,16 +17599,16 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/tabs@3.8.30(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/tabs@3.8.30(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/tabs': 3.11.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/list': 3.13.4(react@17.0.2) @@ -17827,16 +17620,16 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/tabs@3.8.30(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/tabs@3.8.30(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/tabs': 3.11.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/picker': 3.16.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/list': 3.13.4(react@18.3.1) @@ -17869,7 +17662,7 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/tag@3.3.10(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/tag@3.3.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -17877,11 +17670,11 @@ snapshots: '@react-aria/selection': 3.27.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/tag': 3.8.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/collections': 3.12.10(react@17.0.2) '@react-stately/list': 3.13.4(react@17.0.2) @@ -17890,7 +17683,7 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/tag@3.3.10(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/tag@3.3.10(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -17898,11 +17691,11 @@ snapshots: '@react-aria/selection': 3.27.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/tag': 3.8.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/collections': 3.12.10(react@18.3.1) '@react-stately/list': 3.13.4(react@18.3.1) @@ -17932,10 +17725,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/text@3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/text@3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/text': 3.3.23(react@17.0.2) @@ -17944,10 +17737,10 @@ snapshots: react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/text@3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/text@3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/text': 3.3.23(react@18.3.1) @@ -17968,40 +17761,40 @@ snapshots: react-aria-components: 1.16.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/textfield@3.14.5(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/textfield@3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/interactions': 3.27.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/textfield': 3.18.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/utils': 3.11.0(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/textfield': 3.12.8(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/textfield@3.14.5(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/textfield@3.14.5(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/interactions': 3.27.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/textfield': 3.18.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/form': 3.7.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/label': 3.16.22(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/utils': 3.11.0(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/textfield': 3.12.8(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -18079,37 +17872,37 @@ snapshots: '@swc/helpers': 0.5.21 react: 19.2.0 - '@react-spectrum/toast@3.1.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/toast@3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/toast': 3.0.11(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/toast': 3.1.3(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) use-sync-external-store: 1.6.0(react@17.0.2) - '@react-spectrum/toast@3.1.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/toast@3.1.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/toast': 3.0.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/button': 3.17.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/toast': 3.1.3(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -18133,38 +17926,38 @@ snapshots: react-dom: 19.2.0(react@19.2.0) use-sync-external-store: 1.6.0(react@19.2.0) - '@react-spectrum/tooltip@3.8.2(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/tooltip@3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/focus': 3.21.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/overlays': 3.31.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/tooltip': 3.9.2(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-stately/tooltip': 3.5.11(react@17.0.2) '@react-types/overlays': 3.9.4(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/tooltip': 3.5.2(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/tooltip@3.8.2(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/tooltip@3.8.2(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/focus': 3.21.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/overlays': 3.31.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/tooltip': 3.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/overlays': 5.9.3(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-stately/tooltip': 3.5.11(react@18.3.1) '@react-types/overlays': 3.9.4(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/tooltip': 3.5.2(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -18187,35 +17980,35 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/tree@3.1.11(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/tree@3.1.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/button': 3.14.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/i18n': 3.12.16(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/tree': 3.1.7(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@swc/helpers': 0.5.21 react: 17.0.2 react-aria-components: 1.16.0(react-dom@17.0.2(react@17.0.2))(react@17.0.2) react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/tree@3.1.11(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/tree@3.1.11(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/button': 3.14.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/i18n': 3.12.16(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/tree': 3.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/checkbox': 3.10.7(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@react-spectrum/text': 3.5.25(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) - '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@spectrum-icons/ui': 3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@swc/helpers': 0.5.21 react: 18.3.1 react-aria-components: 1.16.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -18271,10 +18064,10 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@react-spectrum/view@3.6.26(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@react-spectrum/view@3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@react-aria/utils': 3.33.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@react-types/shared': 3.33.1(react@17.0.2) '@react-types/view': 3.4.23(react@17.0.2) @@ -18282,10 +18075,10 @@ snapshots: react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@react-spectrum/view@3.6.26(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@react-spectrum/view@3.6.26(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@react-aria/utils': 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@react-spectrum/utils': 3.12.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-types/shared': 3.33.1(react@18.3.1) '@react-types/view': 3.4.23(react@18.3.1) @@ -19937,7 +19730,7 @@ snapshots: dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.3 optionalDependencies: rollup: 4.60.1 @@ -19945,7 +19738,7 @@ snapshots: dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.3 optionalDependencies: rollup: 4.60.3 @@ -20143,22 +19936,22 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@spectrum-icons/ui@3.6.23(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': + '@spectrum-icons/ui@3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@adobe/react-spectrum-ui': 1.2.1(react-dom@17.0.2(react@17.0.2))(react@17.0.2) '@babel/runtime': 7.28.4 - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@swc/helpers': 0.5.21 react: 17.0.2 react-dom: 17.0.2(react@17.0.2) - '@spectrum-icons/ui@3.6.23(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@spectrum-icons/ui@3.6.23(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@adobe/react-spectrum-ui': 1.2.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@babel/runtime': 7.28.4 - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@react-spectrum/provider': 3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@swc/helpers': 0.5.21 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -20173,24 +19966,6 @@ snapshots: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - '@spectrum-icons/workflow@4.2.28(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': - dependencies: - '@adobe/react-spectrum-workflow': 2.3.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2))(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@react-spectrum/provider': 3.10.14(react-dom@17.0.2(react@17.0.2))(react@17.0.2) - '@swc/helpers': 0.5.21 - react: 17.0.2 - react-dom: 17.0.2(react@17.0.2) - - '@spectrum-icons/workflow@4.2.28(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@adobe/react-spectrum-workflow': 2.3.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/icon': 3.8.12(@react-spectrum/provider@3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@react-spectrum/provider': 3.10.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@swc/helpers': 0.5.21 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - '@spectrum-icons/workflow@4.2.28(@react-spectrum/provider@3.10.14(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@17.0.2(react@17.0.2))(react@17.0.2)': dependencies: '@adobe/react-spectrum-workflow': 2.3.5(react-dom@17.0.2(react@17.0.2))(react@17.0.2) @@ -20294,8 +20069,8 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 @@ -20303,18 +20078,18 @@ snapshots: '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 optional: true '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 optional: true '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.0 optional: true '@types/chai@5.2.3': @@ -20379,7 +20154,7 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@22.19.19': + '@types/node@22.20.0': dependencies: undici-types: 6.21.0 @@ -20457,7 +20232,7 @@ snapshots: debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 - tinyglobby: 0.2.16 + tinyglobby: 0.2.15 ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: @@ -20479,7 +20254,7 @@ snapshots: '@typescript-eslint/types': 8.58.1 eslint-visitor-keys: 5.0.1 - '@typespec/ts-http-runtime@0.3.5': + '@typespec/ts-http-runtime@0.3.6': dependencies: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -20492,29 +20267,29 @@ snapshots: '@rolldown/pluginutils': 1.0.0-rc.7 vite: 8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0) - '@vitest/browser-playwright@4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7)': + '@vitest/browser-playwright@4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9)': dependencies: - '@vitest/browser': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7) - '@vitest/mocker': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + '@vitest/browser': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9) + '@vitest/mocker': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) playwright: 1.60.0 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) transitivePeerDependencies: - bufferutil - msw - utf-8-validate - vite - '@vitest/browser@4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7)': + '@vitest/browser@4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9)': dependencies: '@blazediff/core': 1.9.1 - '@vitest/mocker': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) - '@vitest/utils': 4.1.7 + '@vitest/mocker': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + '@vitest/utils': 4.1.9 magic-string: 0.30.21 pngjs: 7.0.0 sirv: 3.0.2 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) ws: 8.20.0 transitivePeerDependencies: - bufferutil @@ -20522,7 +20297,7 @@ snapshots: - utf-8-validate - vite - '@vitest/coverage-v8@3.2.4(@vitest/browser@4.1.7)(vitest@4.1.7)': + '@vitest/coverage-v8@3.2.4(@vitest/browser@4.1.9)(vitest@4.1.9)': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -20537,16 +20312,16 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) optionalDependencies: - '@vitest/browser': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/browser': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7)': + '@vitest/coverage-v8@4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9)': dependencies: '@bcoe/v8-coverage': 1.0.2 - '@vitest/utils': 4.1.7 + '@vitest/utils': 4.1.9 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -20555,60 +20330,60 @@ snapshots: obug: 2.1.1 std-env: 4.0.0 tinyrainbow: 3.1.0 - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) optionalDependencies: - '@vitest/browser': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/browser': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9) - '@vitest/eslint-plugin@1.6.17(eslint@10.3.0)(typescript@6.0.3)(vitest@4.1.7)': + '@vitest/eslint-plugin@1.6.17(eslint@10.3.0)(typescript@6.0.3)(vitest@4.1.9)': dependencies: '@typescript-eslint/scope-manager': 8.58.1 '@typescript-eslint/utils': 8.58.1(eslint@10.3.0)(typescript@6.0.3) eslint: 10.3.0 optionalDependencies: typescript: 6.0.3 - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) transitivePeerDependencies: - supports-color - '@vitest/expect@4.1.7': + '@vitest/expect@4.1.9': dependencies: '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 chai: 6.2.2 tinyrainbow: 3.1.0 - '@vitest/mocker@4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))': + '@vitest/mocker@4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))': dependencies: - '@vitest/spy': 4.1.7 + '@vitest/spy': 4.1.9 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.14.5(@types/node@25.6.2)(typescript@6.0.3) vite: 8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0) - '@vitest/pretty-format@4.1.7': + '@vitest/pretty-format@4.1.9': dependencies: tinyrainbow: 3.1.0 - '@vitest/runner@4.1.7': + '@vitest/runner@4.1.9': dependencies: - '@vitest/utils': 4.1.7 + '@vitest/utils': 4.1.9 pathe: 2.0.3 - '@vitest/snapshot@4.1.7': + '@vitest/snapshot@4.1.9': dependencies: - '@vitest/pretty-format': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/pretty-format': 4.1.9 + '@vitest/utils': 4.1.9 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@4.1.7': {} + '@vitest/spy@4.1.9': {} - '@vitest/utils@4.1.7': + '@vitest/utils@4.1.9': dependencies: - '@vitest/pretty-format': 4.1.7 + '@vitest/pretty-format': 4.1.9 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 @@ -20974,10 +20749,10 @@ snapshots: axe-core@4.11.2: {} - axios@1.16.1: + axios@1.18.1: dependencies: follow-redirects: 1.16.0 - form-data: 4.0.5 + form-data: 4.0.6 https-proxy-agent: 5.0.1 proxy-from-env: 2.1.0 transitivePeerDependencies: @@ -21196,11 +20971,11 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.1.1: + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.6: + brace-expansion@5.0.5: dependencies: balanced-match: 4.0.4 @@ -22528,12 +22303,12 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - form-data@4.0.5: + form-data@4.0.6: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 es-set-tostringtag: 2.1.0 - hasown: 2.0.2 + hasown: 2.0.4 mime-types: 2.1.35 formdata-polyfill@4.0.10: @@ -22814,6 +22589,10 @@ snapshots: dependencies: function-bind: 1.1.2 + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + headers-polyfill@5.0.1: dependencies: '@types/set-cookie-parser': 2.4.10 @@ -23281,7 +23060,7 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 - joi@17.13.3: + joi@17.13.4: dependencies: '@hapi/hoek': 9.3.0 '@hapi/topo': 5.1.0 @@ -23322,6 +23101,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@5.1.0: + dependencies: + argparse: 2.0.1 + jsesc@3.0.2: {} jsesc@3.1.0: {} @@ -23610,14 +23393,14 @@ snapshots: magicast@0.3.5: dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 source-map-js: 1.2.1 magicast@0.5.2: dependencies: - '@babel/parser': 7.29.7 - '@babel/types': 7.29.7 + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@2.1.0: @@ -23697,7 +23480,7 @@ snapshots: minimatch@10.2.5: dependencies: - brace-expansion: 5.0.6 + brace-expansion: 5.0.5 minimatch@3.1.5: dependencies: @@ -23705,11 +23488,11 @@ snapshots: minimatch@5.1.6: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 2.0.2 minimatch@9.0.5: dependencies: - brace-expansion: 2.1.1 + brace-expansion: 2.0.2 minimist@1.2.8: {} @@ -25323,7 +25106,7 @@ snapshots: registry-auth-token@5.1.1: dependencies: - '@pnpm/npm-conf': 3.0.2 + '@pnpm/npm-conf': 3.0.3 registry-url@3.1.0: dependencies: @@ -26260,6 +26043,11 @@ snapshots: tinyexec@1.0.2: {} + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinyglobby@0.2.16: dependencies: fdir: 6.5.0(picomatch@4.0.4) @@ -26529,23 +26317,23 @@ snapshots: terser: 5.44.0 yaml: 2.9.0 - vitest-browser-react@2.2.0(@types/react@19.2.14)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vitest@4.1.7): + vitest-browser-react@2.2.0(@types/react@19.2.14)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(vitest@4.1.9): dependencies: react: 19.2.0 react-dom: 19.2.0(react@19.2.0) - vitest: 4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + vitest: 4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) optionalDependencies: '@types/react': 19.2.14 - vitest@4.1.7(@types/node@25.6.2)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)): + vitest@4.1.9(@types/node@25.6.2)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.9.0)(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)): dependencies: - '@vitest/expect': 4.1.7 - '@vitest/mocker': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) - '@vitest/pretty-format': 4.1.7 - '@vitest/runner': 4.1.7 - '@vitest/snapshot': 4.1.7 - '@vitest/spy': 4.1.7 - '@vitest/utils': 4.1.7 + '@vitest/expect': 4.1.9 + '@vitest/mocker': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.9 + '@vitest/runner': 4.1.9 + '@vitest/snapshot': 4.1.9 + '@vitest/spy': 4.1.9 + '@vitest/utils': 4.1.9 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -26561,8 +26349,8 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 25.6.2 - '@vitest/browser-playwright': 4.1.7(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.7) - '@vitest/coverage-v8': 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7) + '@vitest/browser-playwright': 4.1.9(msw@2.14.5(@types/node@25.6.2)(typescript@6.0.3))(playwright@1.60.0)(vite@8.0.11(@types/node@25.6.2)(esbuild@0.27.2)(terser@5.44.0)(yaml@2.9.0))(vitest@4.1.9) + '@vitest/coverage-v8': 4.1.9(@vitest/browser@4.1.9)(vitest@4.1.9) happy-dom: 20.9.0 transitivePeerDependencies: - msw @@ -26571,8 +26359,8 @@ snapshots: wait-on@7.2.0: dependencies: - axios: 1.16.1 - joi: 17.13.3 + axios: 1.18.1 + joi: 17.13.4 lodash: 4.18.1 minimist: 1.2.8 rxjs: 7.8.2 diff --git a/scripts/jira/api.mjs b/scripts/jira/api.js similarity index 100% rename from scripts/jira/api.mjs rename to scripts/jira/api.js diff --git a/scripts/jira/apply.mjs b/scripts/jira/apply.js similarity index 95% rename from scripts/jira/apply.mjs rename to scripts/jira/apply.js index 6cf072e97..b092a7fab 100644 --- a/scripts/jira/apply.mjs +++ b/scripts/jira/apply.js @@ -14,8 +14,8 @@ governing permissions and limitations under the License. import { readFileSync } from "fs"; import { basename } from "path"; import { fileURLToPath } from "url"; -import yaml from "js-yaml"; -import createApi from "./api.mjs"; +import { load as yamlLoad } from "js-yaml"; +import createApi from "./api.js"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; // Recursively replace {PLACEHOLDER} tokens in body values. @@ -46,7 +46,7 @@ export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { const fileKey = keyMatch[1]; const isNewTicket = fileKey.includes("XXXX"); - const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; + const parsed = yamlLoad(readFileSync(filename, "utf8")) ?? {}; const updates = Array.isArray(parsed.updates) ? parsed.updates : []; const hasUpdates = updates.length > 0; @@ -126,7 +126,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const args = rawArgs.filter((a) => a !== "--dry-run"); if (args.length < 1) { - console.error("Usage: apply.mjs [--dry-run] "); + console.error("Usage: apply.js [--dry-run] "); process.exit(1); } @@ -134,7 +134,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const parsed = (() => { try { - return yaml.load(readFileSync(filename, "utf8")) ?? {}; + return yamlLoad(readFileSync(filename, "utf8")) ?? {}; } catch { return {}; } diff --git a/scripts/jira/apply.spec.js b/scripts/jira/apply.spec.js index 99c2cb9ed..22cf0c4a4 100644 --- a/scripts/jira/apply.spec.js +++ b/scripts/jira/apply.spec.js @@ -14,7 +14,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { writeFileSync, unlinkSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; -import { applyFile } from "./apply.mjs"; +import { applyFile } from "./apply.js"; // Unique prefix per spec file avoids temp-file collisions when tests run in parallel. function uid() { diff --git a/scripts/jira/fetch.mjs b/scripts/jira/fetch.js similarity index 92% rename from scripts/jira/fetch.mjs rename to scripts/jira/fetch.js index 5c8d0dfa3..5fc0b5d63 100644 --- a/scripts/jira/fetch.mjs +++ b/scripts/jira/fetch.js @@ -13,8 +13,8 @@ governing permissions and limitations under the License. import { readFileSync, writeFileSync, existsSync } from "fs"; import { fileURLToPath } from "url"; -import yaml from "js-yaml"; -import createApi from "./api.mjs"; +import { load as yamlLoad, dump as yamlDump } from "js-yaml"; +import createApi from "./api.js"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; const MAX_STRING_LENGTH = 500; @@ -65,7 +65,7 @@ function buildYaml(details, existingUpdates, timestamp) { const doc = existingUpdates ? { details, updates: existingUpdates } : { details }; - return `# fetched from JIRA ${timestamp}\n${yaml.dump(doc, { lineWidth: 120, noRefs: true })}`; + return `# fetched from JIRA ${timestamp}\n${yamlDump(doc, { lineWidth: 120, noRefs: true })}`; } /** @@ -91,7 +91,7 @@ export async function fetchFile(ticketKey, filename, { api }) { let existingUpdates; if (existsSync(filename)) { - const existing = yaml.load(readFileSync(filename, "utf8")); + const existing = yamlLoad(readFileSync(filename, "utf8")); existingUpdates = existing?.updates; } @@ -108,7 +108,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const args = rawArgs.filter((a) => a !== "--dry-run"); if (args.length < 2) { - console.error("Usage: fetch.mjs [--dry-run] "); + console.error("Usage: fetch.js [--dry-run] "); console.error(" JIRA issue key, e.g. PDCL-1234"); console.error( " Path to write, e.g. .jira/PDCL-1234-my-feature.yml", diff --git a/scripts/jira/fetch.spec.js b/scripts/jira/fetch.spec.js index 08e527749..69711c38b 100644 --- a/scripts/jira/fetch.spec.js +++ b/scripts/jira/fetch.spec.js @@ -14,8 +14,8 @@ import { describe, it, expect, vi } from "vitest"; import { writeFileSync, readFileSync, unlinkSync, existsSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; -import yaml from "js-yaml"; -import { fetchFile } from "./fetch.mjs"; +import { load as yamlLoad } from "js-yaml"; +import { fetchFile } from "./fetch.js"; function mockApi(issueData = {}) { return { @@ -52,7 +52,7 @@ describe("fetchFile", () => { await fetchFile("PDCL-1234", filename, { api }); const content = readFileSync(filename, "utf8"); - const parsed = yaml.load(content.replace(/^#.*\n/, "")); + const parsed = yamlLoad(content.replace(/^#.*\n/, "")); expect(parsed.details.key).toBe("PDCL-1234"); expect(parsed.details.summary).toBe("Hello world"); expect(parsed.details.assignee).toBeUndefined(); @@ -67,7 +67,7 @@ describe("fetchFile", () => { await fetchFile("PDCL-1234", filename, { api }); const content = readFileSync(filename, "utf8"); - const parsed = yaml.load(content.replace(/^#.*\n/, "")); + const parsed = yamlLoad(content.replace(/^#.*\n/, "")); expect(parsed.details.description).toBeUndefined(); expect(parsed.details.components).toBeUndefined(); unlinkSync(filename); @@ -81,7 +81,7 @@ describe("fetchFile", () => { await fetchFile("PDCL-1234", filename, { api }); const content = readFileSync(filename, "utf8"); - const parsed = yaml.load(content.replace(/^#.*\n/, "")); + const parsed = yamlLoad(content.replace(/^#.*\n/, "")); expect(parsed.details.description).toHaveLength(503); // 500 + "..." expect(parsed.details.description.endsWith("...")).toBe(true); unlinkSync(filename); @@ -99,7 +99,7 @@ describe("fetchFile", () => { await fetchFile("PDCL-1234", filename, { api }); const content = readFileSync(filename, "utf8"); - const parsed = yaml.load(content.replace(/^#.*\n/, "")); + const parsed = yamlLoad(content.replace(/^#.*\n/, "")); expect(parsed.details.summary).toBe("Updated"); expect(parsed.updates).toHaveLength(1); expect(parsed.updates[0].method).toBe("PUT"); diff --git a/scripts/jira/process.mjs b/scripts/jira/process.js similarity index 91% rename from scripts/jira/process.mjs rename to scripts/jira/process.js index 4576ba3ef..f30e88549 100644 --- a/scripts/jira/process.mjs +++ b/scripts/jira/process.js @@ -14,10 +14,10 @@ governing permissions and limitations under the License. import { readFileSync, unlinkSync, existsSync } from "fs"; import { basename, dirname } from "path"; import { fileURLToPath } from "url"; -import yaml from "js-yaml"; -import createApi from "./api.mjs"; -import { applyFile } from "./apply.mjs"; -import { fetchFile } from "./fetch.mjs"; +import { load as yamlLoad } from "js-yaml"; +import createApi from "./api.js"; +import { applyFile } from "./apply.js"; +import { fetchFile } from "./fetch.js"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; /** @@ -33,7 +33,7 @@ export async function processFile(filename, { api, prUrl = "", prTitle = "" }) { return null; } - const parsed = yaml.load(readFileSync(filename, "utf8")) ?? {}; + const parsed = yamlLoad(readFileSync(filename, "utf8")) ?? {}; const hasUpdates = Array.isArray(parsed.updates) && parsed.updates.length > 0; if (!hasUpdates) { @@ -67,7 +67,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const args = rawArgs.filter((a) => a !== "--dry-run"); if (args.length < 1) { - console.error("Usage: process.mjs [--dry-run] "); + console.error("Usage: process.js [--dry-run] "); process.exit(1); } diff --git a/scripts/jira/process.spec.js b/scripts/jira/process.spec.js index e1157c5da..9890e7b85 100644 --- a/scripts/jira/process.spec.js +++ b/scripts/jira/process.spec.js @@ -14,7 +14,7 @@ import { describe, it, expect, vi } from "vitest"; import { writeFileSync, existsSync, unlinkSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; -import { processFile } from "./process.mjs"; +import { processFile } from "./process.js"; function mockApi(overrides = {}) { return { From 892367f1eba1c40e59346b9b21bb6aded2eaa47a Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 14:45:16 -0600 Subject: [PATCH 08/10] fix(jira): dryRun only blocks writes, fetch always reads JIRA, token always required MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses five review comments: - api.js: dryRun now only blocks mutation requests (non-GET); searchIssues and getRemoteLinks always execute so dry-run previews reflect real JIRA state - fetch.js: fetchFile always fetches from JIRA; in dryRun outputs the YAML content it would write to stdout instead of skipping the fetch entirely - fetch.js: removed existing-file check — fetch always overwrites with just the details section (updates have already been applied at this point) - process.js / apply.js / fetch.js: JIRA_API_TOKEN is now required even in dry-run mode since read queries need authentication - CLAUDE.md: removed (not ready to commit yet) Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 45 -------------------------------------- scripts/jira/api.js | 7 +----- scripts/jira/apply.js | 18 ++++++++------- scripts/jira/fetch.js | 30 ++++++++----------------- scripts/jira/fetch.spec.js | 11 ++++++---- scripts/jira/process.js | 8 +++---- 6 files changed, 31 insertions(+), 88 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index f649934c1..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,45 +0,0 @@ -# Alloy — Claude Code guide - -## JIRA ticket management - -JIRA changes are version-controlled as YAML files in `.jira/`. No JIRA API calls are made locally. - -### Workflow - -1. **Propose** — Run `/jira-propose` to create or update a `.jira/*.yml` file based on current git changes and context. -2. **Review** — The `.jira/` diff appears in the PR. Reviewers approve JIRA changes alongside code changes. -3. **Apply** — On merge to `main`, the `apply-jira` CI job executes each file's `updates` array against the JIRA REST API, creates a remote link back to the PR, and posts a PR comment listing updated tickets. -4. **Fetch** — After apply, the XXXX file is deleted and `fetch.js` writes a fresh file with the real ticket key and current JIRA state. A `[skip ci]` commit lands these changes. - -### File naming - -- Existing ticket: `PDCL-1234-short-title.yml` -- New ticket (not yet in JIRA): `PDCL-XXXX-short-description.yml` - -### Scripts - -```bash -# See planned JIRA calls without making them (safe for local use) -node scripts/jira/apply.js --dry-run .jira/PDCL-1234-my-feature.yml - -# Fetch current JIRA state into a file -JIRA_API_TOKEN= node scripts/jira/fetch.js PDCL-1234 .jira/PDCL-1234-my-feature.yml -``` - -### CI environment variables (Production GitHub Actions environment) - -| Variable | Required for | -|----------|-------------| -| `JIRA_API_TOKEN` | apply.js and fetch.js API calls | -| `ALLOY_BOT_GITHUB_SSH_PRIVATE_KEY` | Pushing skip-ci commits to main | - -### Custom fields (PDCL project) - -| Field | Value | -|-------|-------| -| AEP Web SDK component | `components[].id: "155901"` | -| Product (`customfield_23300`) | `id: "116005"` | -| Story `issuetype.id` | `"7"` | -| Bug `issuetype.id` | `"1"` | - -See [`.jira/README.md`](./.jira/README.md) for the full schema reference. diff --git a/scripts/jira/api.js b/scripts/jira/api.js index e0ffd61f6..2f2290dc6 100644 --- a/scripts/jira/api.js +++ b/scripts/jira/api.js @@ -22,7 +22,7 @@ export default function createApi({ dryRun = false, baseUrl, token }) { async function request(method, path, body) { const url = `${baseUrl}${path}`; - if (dryRun) { + if (dryRun && method !== "GET") { console.log(`[dry-run] ${method} ${url}`); if (body !== undefined) console.log(JSON.stringify(body, null, 2)); return {}; @@ -44,10 +44,6 @@ export default function createApi({ dryRun = false, baseUrl, token }) { async function searchIssues(jql, { fields = "key", maxResults = 50 } = {}) { const qs = `jql=${encodeURIComponent(jql)}&fields=${fields}&maxResults=${maxResults}`; - if (dryRun) { - console.log(`[dry-run] Search: GET ${baseUrl}/rest/api/2/search?${qs}`); - return []; - } const response = await fetch(`${baseUrl}/rest/api/2/search?${qs}`, { headers: authHeaders, }); @@ -57,7 +53,6 @@ export default function createApi({ dryRun = false, baseUrl, token }) { } async function getRemoteLinks(key) { - if (dryRun) return []; const response = await fetch( `${baseUrl}/rest/api/2/issue/${key}/remotelink`, { headers: authHeaders }, diff --git a/scripts/jira/apply.js b/scripts/jira/apply.js index b092a7fab..3d3ed9ef3 100644 --- a/scripts/jira/apply.js +++ b/scripts/jira/apply.js @@ -141,18 +141,20 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { })(); const hasUpdates = Array.isArray(parsed.updates) && parsed.updates.length > 0; - if (hasUpdates && !dryRun) { + if (hasUpdates) { if (!JIRA_API_TOKEN) { console.error("JIRA_API_TOKEN is required"); process.exit(1); } - if (!process.env.GITHUB_PR_URL) { - console.error("GITHUB_PR_URL is required when updates are present"); - process.exit(1); - } - if (!process.env.GITHUB_PR_TITLE) { - console.error("GITHUB_PR_TITLE is required when updates are present"); - process.exit(1); + if (!dryRun) { + if (!process.env.GITHUB_PR_URL) { + console.error("GITHUB_PR_URL is required when updates are present"); + process.exit(1); + } + if (!process.env.GITHUB_PR_TITLE) { + console.error("GITHUB_PR_TITLE is required when updates are present"); + process.exit(1); + } } } diff --git a/scripts/jira/fetch.js b/scripts/jira/fetch.js index 5fc0b5d63..9dd897263 100644 --- a/scripts/jira/fetch.js +++ b/scripts/jira/fetch.js @@ -11,7 +11,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { readFileSync, writeFileSync, existsSync } from "fs"; +import { writeFileSync } from "fs"; import { fileURLToPath } from "url"; import { load as yamlLoad, dump as yamlDump } from "js-yaml"; import createApi from "./api.js"; @@ -61,11 +61,8 @@ function extractFields(fields) { return result; } -function buildYaml(details, existingUpdates, timestamp) { - const doc = existingUpdates - ? { details, updates: existingUpdates } - : { details }; - return `# fetched from JIRA ${timestamp}\n${yamlDump(doc, { lineWidth: 120, noRefs: true })}`; +function buildYaml(details, timestamp) { + return `# fetched from JIRA ${timestamp}\n${yamlDump({ details }, { lineWidth: 120, noRefs: true })}`; } /** @@ -75,28 +72,19 @@ function buildYaml(details, existingUpdates, timestamp) { * @param {{ api: object }} opts */ export async function fetchFile(ticketKey, filename, { api }) { - if (api.dryRun) { - console.log( - `[dry-run] Would fetch: GET ${JIRA_BASE_URL.replace(/\/$/, "")}/rest/api/2/issue/${encodeURIComponent(ticketKey)}`, - ); - console.log(`[dry-run] Would write to: ${filename}`); - return; - } - const data = await api.request( "GET", `/rest/api/2/issue/${encodeURIComponent(ticketKey)}`, ); const details = { key: data.key, ...extractFields(data.fields ?? {}) }; + const timestamp = new Date().toISOString(); + const content = buildYaml(details, timestamp); - let existingUpdates; - if (existsSync(filename)) { - const existing = yamlLoad(readFileSync(filename, "utf8")); - existingUpdates = existing?.updates; + if (api.dryRun) { + console.log(`[dry-run] Would write to ${filename}:\n${content}`); + return; } - const timestamp = new Date().toISOString(); - const content = buildYaml(details, existingUpdates, timestamp); writeFileSync(filename, content, "utf8"); console.log(`Wrote ${filename}`); } @@ -118,7 +106,7 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const [ticketKey, filename] = args; - if (!dryRun && !JIRA_API_TOKEN) { + if (!JIRA_API_TOKEN) { console.error("JIRA_API_TOKEN is required"); process.exit(1); } diff --git a/scripts/jira/fetch.spec.js b/scripts/jira/fetch.spec.js index 69711c38b..23e9e2d9f 100644 --- a/scripts/jira/fetch.spec.js +++ b/scripts/jira/fetch.spec.js @@ -87,7 +87,7 @@ describe("fetchFile", () => { unlinkSync(filename); }); - it("preserves existing updates section when file already exists", async () => { + it("overwrites existing file with only details, no updates", async () => { const filename = tempPath("pdcl-1234"); writeFileSync( filename, @@ -101,8 +101,7 @@ describe("fetchFile", () => { const content = readFileSync(filename, "utf8"); const parsed = yamlLoad(content.replace(/^#.*\n/, "")); expect(parsed.details.summary).toBe("Updated"); - expect(parsed.updates).toHaveLength(1); - expect(parsed.updates[0].method).toBe("PUT"); + expect(parsed.updates).toBeUndefined(); unlinkSync(filename); }); @@ -117,12 +116,16 @@ describe("fetchFile", () => { unlinkSync(filename); }); - it("skips file write in dry-run mode", async () => { + it("fetches from JIRA but outputs to stdout instead of writing in dry-run mode", async () => { const filename = tempPath("pdcl-1234"); const api = { ...mockApi(), dryRun: true }; await fetchFile("PDCL-1234", filename, { api }); expect(existsSync(filename)).toBe(false); + expect(api.request).toHaveBeenCalledWith( + "GET", + expect.stringContaining("PDCL-1234"), + ); }); }); diff --git a/scripts/jira/process.js b/scripts/jira/process.js index f30e88549..04e4757cc 100644 --- a/scripts/jira/process.js +++ b/scripts/jira/process.js @@ -73,11 +73,11 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) { const [filename] = args; + if (!JIRA_API_TOKEN) { + console.error("JIRA_API_TOKEN is required"); + process.exit(1); + } if (!dryRun) { - if (!JIRA_API_TOKEN) { - console.error("JIRA_API_TOKEN is required"); - process.exit(1); - } if (!process.env.GITHUB_PR_URL) { console.error("GITHUB_PR_URL is required"); process.exit(1); From e05682210d4d4a942e81885700ca19b4974ad518 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 15:08:15 -0600 Subject: [PATCH 09/10] fix(lint): convert jira script function declarations to arrow constants Satisfies ESLint func-style rule; removes unused beforeEach import from apply.spec.js; fixes no-await-in-loop in apply.js with Promise.all for parallel remote-link fetching and eslint-disable for sequential updates. --- scripts/jira/api.js | 15 ++++++---- scripts/jira/apply.js | 53 +++++++++++++++++++++--------------- scripts/jira/apply.spec.js | 34 ++++++++++------------- scripts/jira/fetch.js | 23 ++++++++-------- scripts/jira/fetch.spec.js | 39 ++++++++++++-------------- scripts/jira/process.js | 7 +++-- scripts/jira/process.spec.js | 28 +++++++++---------- 7 files changed, 102 insertions(+), 97 deletions(-) diff --git a/scripts/jira/api.js b/scripts/jira/api.js index 2f2290dc6..eebfcb07f 100644 --- a/scripts/jira/api.js +++ b/scripts/jira/api.js @@ -20,7 +20,7 @@ export default function createApi({ dryRun = false, baseUrl, token }) { "Content-Type": "application/json", }; - async function request(method, path, body) { + const request = async (method, path, body) => { const url = `${baseUrl}${path}`; if (dryRun && method !== "GET") { console.log(`[dry-run] ${method} ${url}`); @@ -40,9 +40,12 @@ export default function createApi({ dryRun = false, baseUrl, token }) { } const text = await response.text(); return text ? JSON.parse(text) : {}; - } + }; - async function searchIssues(jql, { fields = "key", maxResults = 50 } = {}) { + const searchIssues = async ( + jql, + { fields = "key", maxResults = 50 } = {}, + ) => { const qs = `jql=${encodeURIComponent(jql)}&fields=${fields}&maxResults=${maxResults}`; const response = await fetch(`${baseUrl}/rest/api/2/search?${qs}`, { headers: authHeaders, @@ -50,16 +53,16 @@ export default function createApi({ dryRun = false, baseUrl, token }) { if (!response.ok) return []; const data = await response.json(); return data.issues ?? []; - } + }; - async function getRemoteLinks(key) { + const getRemoteLinks = async (key) => { const response = await fetch( `${baseUrl}/rest/api/2/issue/${key}/remotelink`, { headers: authHeaders }, ); if (!response.ok) return []; return response.json(); - } + }; return { dryRun, request, searchIssues, getRemoteLinks }; } diff --git a/scripts/jira/apply.js b/scripts/jira/apply.js index 3d3ed9ef3..a712ee96e 100644 --- a/scripts/jira/apply.js +++ b/scripts/jira/apply.js @@ -19,7 +19,7 @@ import createApi from "./api.js"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; // Recursively replace {PLACEHOLDER} tokens in body values. -function interpolate(value, vars) { +const interpolate = (value, vars) => { if (typeof value === "string") { return value.replace(/\{(\w+)\}/g, (_, k) => vars[k] ?? `{${k}}`); } @@ -30,7 +30,7 @@ function interpolate(value, vars) { ); } return value; -} +}; /** * Apply a .jira/*.yml file's updates to JIRA. @@ -38,7 +38,10 @@ function interpolate(value, vars) { * @param {{ api: object, prUrl?: string, prTitle?: string }} opts * @returns {Promise} resolved ticket key, e.g. "PDCL-1234" */ -export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { +export const applyFile = async ( + filename, + { api, prUrl = "", prTitle = "" }, +) => { const fileBase = basename(filename, ".yml"); const keyMatch = fileBase.match(/^([A-Z]+-(?:XXXX|\d+))/); if (!keyMatch) @@ -58,7 +61,7 @@ export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { ); const globalId = remoteLinkUpdate?.body?.globalId; - async function resolveKey() { + const resolveKey = async () => { if (!isNewTicket) return fileKey; // Search for an existing ticket that already has this globalId on its remote links. @@ -66,23 +69,28 @@ export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { const issues = await api.searchIssues( `project = PDCL AND created >= startOfDay("-7d") ORDER BY created DESC`, ); - for (const issue of issues) { - const links = await api.getRemoteLinks(issue.key); - if (links.some((l) => l.globalId === globalId)) { - console.log( - `Found existing ticket ${issue.key} via globalId ${globalId}`, - ); - // Update the existing ticket with the create details to ensure idempotency. - const createUpdate = updates.find( - (u) => u.method === "POST" && u.path === "/rest/api/2/issue", - ); - if (createUpdate?.body?.fields) { - await api.request("PUT", `/rest/api/2/issue/${issue.key}`, { - fields: createUpdate.body.fields, - }); - } - return issue.key; + // Fetch all remote links in parallel then find the match. + const linkResults = await Promise.all( + issues.map((issue) => api.getRemoteLinks(issue.key)), + ); + const matchIndex = linkResults.findIndex((links) => + links.some((l) => l.globalId === globalId), + ); + if (matchIndex !== -1) { + const issue = issues[matchIndex]; + console.log( + `Found existing ticket ${issue.key} via globalId ${globalId}`, + ); + // Update the existing ticket with the create details to ensure idempotency. + const createUpdate = updates.find( + (u) => u.method === "POST" && u.path === "/rest/api/2/issue", + ); + if (createUpdate?.body?.fields) { + await api.request("PUT", `/rest/api/2/issue/${issue.key}`, { + fields: createUpdate.body.fields, + }); } + return issue.key; } } @@ -100,7 +108,7 @@ export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { createUpdate.body, ); return data.key ?? "PDCL-XXXX"; - } + }; const ticketKey = await resolveKey(); @@ -113,11 +121,12 @@ export async function applyFile(filename, { api, prUrl = "", prTitle = "" }) { if (isCreateCall(update)) continue; const path = String(update.path).replace(/\{key\}/g, ticketKey); const body = interpolate(update.body, vars); + // eslint-disable-next-line no-await-in-loop await api.request(update.method, path, body); } return ticketKey; -} +}; // Script entry point — only executes when run directly. if (process.argv[1] === fileURLToPath(import.meta.url)) { diff --git a/scripts/jira/apply.spec.js b/scripts/jira/apply.spec.js index 22cf0c4a4..19d55af5b 100644 --- a/scripts/jira/apply.spec.js +++ b/scripts/jira/apply.spec.js @@ -10,40 +10,36 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import { describe, it, expect, vi, beforeEach } from "vitest"; +import { describe, it, expect, vi } from "vitest"; import { writeFileSync, unlinkSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; import { applyFile } from "./apply.js"; // Unique prefix per spec file avoids temp-file collisions when tests run in parallel. -function uid() { - return `${Date.now()}-${Math.random().toString(36).slice(2)}`; -} +const uid = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`; -function tempFile(content) { +const tempFile = (content) => { const path = join(tmpdir(), `PDCL-1234-apply-spec-${uid()}.yml`); writeFileSync(path, content, "utf8"); return path; -} +}; -function xxxxFile(content) { +const xxxxFile = (content) => { const path = join(tmpdir(), `PDCL-XXXX-apply-spec-${uid()}.yml`); writeFileSync(path, content, "utf8"); return path; -} +}; -function mockApi(overrides = {}) { - return { - dryRun: false, - request: vi.fn(async (method) => - method === "POST" ? { key: "PDCL-9999" } : {}, - ), - searchIssues: vi.fn(async () => []), - getRemoteLinks: vi.fn(async () => []), - ...overrides, - }; -} +const mockApi = (overrides = {}) => ({ + dryRun: false, + request: vi.fn(async (method) => + method === "POST" ? { key: "PDCL-9999" } : {}, + ), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), + ...overrides, +}); describe("applyFile — existing ticket", () => { it("returns the ticket key from the filename", async () => { diff --git a/scripts/jira/fetch.js b/scripts/jira/fetch.js index 9dd897263..021844676 100644 --- a/scripts/jira/fetch.js +++ b/scripts/jira/fetch.js @@ -13,26 +13,26 @@ governing permissions and limitations under the License. import { writeFileSync } from "fs"; import { fileURLToPath } from "url"; -import { load as yamlLoad, dump as yamlDump } from "js-yaml"; +import { dump as yamlDump } from "js-yaml"; import createApi from "./api.js"; import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; const MAX_STRING_LENGTH = 500; -function truncate(value) { +const truncate = (value) => { if (typeof value === "string" && value.length > MAX_STRING_LENGTH) { return value.slice(0, MAX_STRING_LENGTH) + "..."; } return value; -} +}; -function isNonEmpty(value) { +const isNonEmpty = (value) => { if (value === null || value === undefined) return false; if (Array.isArray(value) && value.length === 0) return false; return true; -} +}; -function extractFields(fields) { +const extractFields = (fields) => { const result = {}; for (const [key, value] of Object.entries(fields)) { if (!isNonEmpty(value)) continue; @@ -59,11 +59,10 @@ function extractFields(fields) { } } return result; -} +}; -function buildYaml(details, timestamp) { - return `# fetched from JIRA ${timestamp}\n${yamlDump({ details }, { lineWidth: 120, noRefs: true })}`; -} +const buildYaml = (details, timestamp) => + `# fetched from JIRA ${timestamp}\n${yamlDump({ details }, { lineWidth: 120, noRefs: true })}`; /** * Fetch live JIRA state for a ticket and write it to a file. @@ -71,7 +70,7 @@ function buildYaml(details, timestamp) { * @param {string} filename target file path * @param {{ api: object }} opts */ -export async function fetchFile(ticketKey, filename, { api }) { +export const fetchFile = async (ticketKey, filename, { api }) => { const data = await api.request( "GET", `/rest/api/2/issue/${encodeURIComponent(ticketKey)}`, @@ -87,7 +86,7 @@ export async function fetchFile(ticketKey, filename, { api }) { writeFileSync(filename, content, "utf8"); console.log(`Wrote ${filename}`); -} +}; // Script entry point — only executes when run directly. if (process.argv[1] === fileURLToPath(import.meta.url)) { diff --git a/scripts/jira/fetch.spec.js b/scripts/jira/fetch.spec.js index 23e9e2d9f..82eb6268a 100644 --- a/scripts/jira/fetch.spec.js +++ b/scripts/jira/fetch.spec.js @@ -17,32 +17,29 @@ import { tmpdir } from "os"; import { load as yamlLoad } from "js-yaml"; import { fetchFile } from "./fetch.js"; -function mockApi(issueData = {}) { - return { - dryRun: false, - request: vi.fn(async () => ({ - key: "PDCL-1234", - fields: { - summary: "My feature", - status: { name: "In Progress" }, - assignee: null, - description: null, - components: [], - ...issueData, - }, - })), - searchIssues: vi.fn(async () => []), - getRemoteLinks: vi.fn(async () => []), - }; -} +const mockApi = (issueData = {}) => ({ + dryRun: false, + request: vi.fn(async () => ({ + key: "PDCL-1234", + fields: { + summary: "My feature", + status: { name: "In Progress" }, + assignee: null, + description: null, + components: [], + ...issueData, + }, + })), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), +}); // Unique prefix per spec file avoids temp-file collisions when tests run in parallel. -function tempPath(label) { - return join( +const tempPath = (label) => + join( tmpdir(), `fetch-spec-${label}-${Date.now()}-${Math.random().toString(36).slice(2)}.yml`, ); -} describe("fetchFile", () => { it("writes details section to a new file", async () => { diff --git a/scripts/jira/process.js b/scripts/jira/process.js index 04e4757cc..6b2b77638 100644 --- a/scripts/jira/process.js +++ b/scripts/jira/process.js @@ -27,7 +27,10 @@ import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; * @param {{ api: object, prUrl?: string, prTitle?: string }} opts * @returns {Promise} ticket key if processed, null if skipped */ -export async function processFile(filename, { api, prUrl = "", prTitle = "" }) { +export const processFile = async ( + filename, + { api, prUrl = "", prTitle = "" }, +) => { if (!existsSync(filename)) { console.log(`Skipping ${filename} (file not found)`); return null; @@ -58,7 +61,7 @@ export async function processFile(filename, { api, prUrl = "", prTitle = "" }) { await fetchFile(ticketKey, newFilename, { api }); return ticketKey; -} +}; // Script entry point — only executes when run directly. if (process.argv[1] === fileURLToPath(import.meta.url)) { diff --git a/scripts/jira/process.spec.js b/scripts/jira/process.spec.js index 9890e7b85..c782dc65f 100644 --- a/scripts/jira/process.spec.js +++ b/scripts/jira/process.spec.js @@ -16,28 +16,26 @@ import { join } from "path"; import { tmpdir } from "os"; import { processFile } from "./process.js"; -function mockApi(overrides = {}) { - return { - dryRun: false, - request: vi.fn(async (method) => - method === "POST" - ? { key: "PDCL-9999" } - : { key: "PDCL-1234", fields: { summary: "Test" } }, - ), - searchIssues: vi.fn(async () => []), - getRemoteLinks: vi.fn(async () => []), - ...overrides, - }; -} +const mockApi = (overrides = {}) => ({ + dryRun: false, + request: vi.fn(async (method) => + method === "POST" + ? { key: "PDCL-9999" } + : { key: "PDCL-1234", fields: { summary: "Test" } }, + ), + searchIssues: vi.fn(async () => []), + getRemoteLinks: vi.fn(async () => []), + ...overrides, +}); // jiraKey must be at the start of the basename for the filename regex to match. // Unique suffix per spec file prevents collisions when tests run in parallel. -function writeTemp(jiraKey, content) { +const writeTemp = (jiraKey, content) => { const uid = `${Date.now()}-${Math.random().toString(36).slice(2)}`; const path = join(tmpdir(), `${jiraKey}-proc-spec-${uid}.yml`); writeFileSync(path, content, "utf8"); return path; -} +}; describe("processFile", () => { it("returns null and skips when file has no updates", async () => { From ef9e5929d5b8f70df6a399d18e71d5cf98d3820c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 15:36:32 -0600 Subject: [PATCH 10/10] =?UTF-8?q?feat(jira):=20address=20review=20?= =?UTF-8?q?=E2=80=94=20local=20config,=20simpler=20apply=20logic,=20global?= =?UTF-8?q?Id=20in=20filename?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add scripts/jira/config.js; remove team/config.js dependency from all jira scripts - Rename new-ticket files from PDCL-XXXX-... to PDCL-{globalId}-... pattern - Apply script now resolves new tickets by searching JIRA label matching the globalId - Update loop: POST runs only when no ticket key yet; all others run when key is known - Auto-create remote link to PR for every processed ticket (idempotent via PR URL) - Remove explicit remotelink entry from jira-propose skill template - Update openspec tasks/design/proposal to reflect as-built implementation --- .claude/skills/jira-propose/SKILL.md | 34 +++-- .../github-jira-yaml-workflow/design.md | 12 +- .../github-jira-yaml-workflow/proposal.md | 11 +- .../github-jira-yaml-workflow/tasks.md | 46 +++--- scripts/jira/api.js | 11 +- scripts/jira/apply.js | 130 ++++++++-------- scripts/jira/apply.spec.js | 140 ++++++++++++------ scripts/jira/config.js | 16 ++ scripts/jira/fetch.js | 2 +- scripts/jira/process.js | 12 +- scripts/jira/process.spec.js | 22 ++- 11 files changed, 247 insertions(+), 189 deletions(-) create mode 100644 scripts/jira/config.js diff --git a/.claude/skills/jira-propose/SKILL.md b/.claude/skills/jira-propose/SKILL.md index 43c7af050..f70c3c388 100644 --- a/.claude/skills/jira-propose/SKILL.md +++ b/.claude/skills/jira-propose/SKILL.md @@ -39,11 +39,11 @@ Check each `.jira/*.yml` file: - If a file matches the current work, **update it** (append to `updates` array) - If no file matches, **create a new one** -### 4a. New ticket — write `PDCL-XXXX-.yml` +### 4a. New ticket — write `PDCL--.yml` -Generate a kebab-case short description (3–6 words) from the branch name and commits. +Generate a short random `globalId` (8 hex characters, e.g. `"a3f8b2c1"`) and a kebab-case short description (3–6 words) from the branch name and commits. -Write `.jira/PDCL-XXXX-.yml` with this structure: +Write `.jira/PDCL--.yml` with this structure: ```yaml updates: @@ -64,17 +64,17 @@ updates: - id: "155901" # AEP Web SDK customfield_23300: # AEP Web SDK product field id: "116005" - - path: /rest/api/2/issue/{key}/remotelink - method: POST - body: - globalId: - relationship: mentioned in - object: - url: "{GITHUB_PR_URL}" - title: "{GITHUB_PR_TITLE}" + labels: + - # idempotency key — do not remove ``` -The `globalId` is the idempotency key for this ticket — it must be unique per ticket file so that multiple new tickets can be created in a single PR merge. Generate a random 12-character hex string (e.g. using `Math.random().toString(16).slice(2,14)` mentally). The `{GITHUB_PR_URL}` and `{GITHUB_PR_TITLE}` placeholders are substituted by `apply.mjs` at run time. +**Filename and globalId:** +- The `` in the filename is the idempotency key for this ticket +- It must be unique per ticket file so multiple new tickets can be created in a single PR +- Generate a random 8-character hex string (e.g. `a3f8b2c1`) +- The same value goes in `labels` so `apply.js` can find the ticket on re-runs +- The apply script auto-creates a remote link from the ticket to the PR — no remotelink entry needed in `updates` +- After merge, the build replaces the file with `PDCL--.yml` **Description guidelines:** - Lead with who benefits (e.g., "Analytics customers using the Web SDK...") @@ -99,6 +99,7 @@ updates: Use `PUT /rest/api/2/issue/{key}` with `update.field[].set` for field changes. Use `POST /rest/api/2/issue/{key}/transitions` for status transitions. +The `{key}` placeholder is replaced with the real ticket key by `apply.js` at run time. ### 5. Write the file @@ -110,9 +111,9 @@ Use `POST /rest/api/2/issue/{key}/transitions` for status transitions. After writing the file, tell the user: - The filename created or updated -- The ticket key (PDCL-XXXX for new, PDCL-NNNN for existing) +- The ticket identifier (globalId for new tickets, PDCL-NNNN for existing) - The proposed summary -- What will happen when the PR merges (apply.mjs will execute the updates) +- What will happen when the PR merges (apply.js will execute the updates, then replace the file with a real-key filename) ## Reference: PDCL custom fields @@ -131,6 +132,7 @@ After writing the file, tell the user: - **No JIRA API calls** — all information comes from git state, context, and existing `.jira/` files - All `update` operations must use `set` (never `add`/`remove`) to ensure idempotency -- New tickets must have a `POST /rest/api/2/issue` as the first entry in `updates` +- New tickets must have a `POST /rest/api/2/issue` as the first entry in `updates`, with the `globalId` in `labels` +- Do **not** add a remotelink entry to `updates` — the apply script creates it automatically - File must be valid YAML -- Do not populate the `details` section — that is written by `fetch.mjs` after apply +- Do not populate the `details` section — that is written by `fetch.js` after apply diff --git a/openspec/changes/github-jira-yaml-workflow/design.md b/openspec/changes/github-jira-yaml-workflow/design.md index e35840300..afae55749 100644 --- a/openspec/changes/github-jira-yaml-workflow/design.md +++ b/openspec/changes/github-jira-yaml-workflow/design.md @@ -40,8 +40,8 @@ Custom field IDs used in the PDCL project: **Idempotency**: All `body.update` payloads use `set` operations, never `add`/`remove`. The apply script skips updates when the remote link already exists (checked before applying). ### Remote link as idempotency key for new tickets -**Decision**: Before creating a new ticket (`PDCL-XXXX-*.yml`), the apply script searches JIRA for any issue in the project whose remote links include one with global ID `repo-{PR#}` (e.g. `repo-1553`). No pagination is needed — a single search suffices. If any match is found, creation is skipped and the found ticket key is returned. Apply exits 0 in either case, so the workflow continues with the delete-and-fetch step. -**Rationale**: Using `repo-{PR#}` as the global ID gives JIRA a stable, indexed identifier that is more reliably searchable than a full URL. If the build fails mid-step and re-runs, apply again finds the link and returns the key; the XXXX file is re-deleted and fetch re-creates the real-key file — fully idempotent. +**Decision**: Each new ticket YAML carries a unique hex `globalId` (e.g. `"a3f8b2c1d4e5f6a7"`) in its remotelink `updates` entry, generated by the `/jira-propose` skill at authoring time. Before creating a new ticket, the apply script searches JIRA for recent issues and fetches all their remote links in parallel (via `Promise.all`); if any issue's links contain a matching `globalId`, creation is skipped, the found key is returned, and the create fields are PUT to the existing ticket to ensure idempotency. The XXXX file is deleted and `fetchFile` re-creates the real-key file — fully idempotent on re-run. +**Rationale**: A per-ticket unique `globalId` (rather than a shared `repo-{PR#}`) allows multiple new tickets in the same PR to each have their own idempotency key. JIRA remote link `globalId` is indexed, making the lookup reliable. `Promise.all` on remote-link fetches keeps the search fast without sequential awaits (avoids ESLint `no-await-in-loop`). ### `details` section is read-only metadata; refreshed by the build workflow **Decision**: The `details` section is a read-only snapshot — the apply script ignores it entirely. After apply runs successfully, the build workflow deletes the file and calls fetch to regenerate `details` from live JIRA state, producing a fresh file with the real ticket key in the filename. @@ -56,12 +56,12 @@ Custom field IDs used in the PDCL project: **Rationale**: Developers may not have a JIRA PAT configured; the action should work offline and in CI lint passes. JIRA reads are deferred to the `details` snapshot (which can be populated manually or by a separate fetch script in future). ### Apply and fetch script location -**Decision**: `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` — standalone Node.js ES modules. -**Rationale**: Keeps CI logic in the same `scripts/` tree as the existing JIRA helpers, enabling code reuse from `scripts/team/config.js`. +**Decision**: `scripts/jira/apply.js`, `scripts/jira/fetch.js`, `scripts/jira/api.js`, and `scripts/jira/process.js` — standalone Node.js ES modules (`.js` extension; `package.json` has `"type": "module"` at the repo root). +**Rationale**: Keeps CI logic in the same `scripts/` tree as the existing JIRA helpers, enabling code reuse from `scripts/team/config.js`. Using `.js` (not `.mjs`) matches the repo ESLint convention (`import/extensions` rule requires `js: "always"`). The `api.js` factory enables dependency injection for tests without `vi.mock()`; `process.js` provides a single orchestration entry point for the build workflow. ### Fetch script design -**Decision**: `fetch.mjs` requires exactly two arguments: `` and ``. Both are required. It calls JIRA's `GET /rest/api/2/issue/{key}` endpoint and writes (or overwrites) the file at the given path with a fresh `details` section; any existing `updates` array is preserved. -**Rationale**: Keeping key and filename independent lets the build workflow substitute the real ticket number for XXXX in the filename, and lets LLMs or developers control naming. The script stays deterministic given the same inputs. Fetch can read any JIRA project (not limited to PDCL) since it is read-only. +**Decision**: `fetch.js` requires exactly two arguments: `` and ``. Both are required. It calls JIRA's `GET /rest/api/2/issue/{key}` endpoint and **overwrites** the file at the given path with a fresh `details`-only section (no `updates`). In `--dry-run` mode it still performs the GET and prints the would-be content to stdout without writing. A `process.js` orchestrator wraps apply + fetch for use in the build workflow loop. +**Rationale**: Not preserving `updates` prevents stale update entries from accumulating in the file after the build has already applied them. After apply succeeds, the old `updates` are already executed — the refreshed file should be a clean snapshot. Keeping key and filename independent lets the build workflow substitute the real ticket number for XXXX in the filename. Fetch can read any JIRA project since it is read-only. ### No separate JIRA workflow file **Decision**: Integrate the `apply-jira` job into the existing `.github/workflows/version-and-publish.yml`. diff --git a/openspec/changes/github-jira-yaml-workflow/proposal.md b/openspec/changes/github-jira-yaml-workflow/proposal.md index 6eb3a6535..d908e3aa9 100644 --- a/openspec/changes/github-jira-yaml-workflow/proposal.md +++ b/openspec/changes/github-jira-yaml-workflow/proposal.md @@ -11,9 +11,10 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - `updates` — ordered array of idempotent REST calls (`path`, `method`, `body`) to apply when the PR merges - YAML is used (not JSON) so inline comments can document custom field IDs (e.g. `customfield_23300`) - The existing build workflow (`version-and-publish.yml`) gains a new `apply-jira` job: for each changed `.jira/*.yml` file that has an `updates` section, it runs `apply.mjs` → on success, deletes the file → runs `fetch.mjs` to create a fresh file at the real-key filename; all `.jira/` additions/deletions are committed in a single skip-ci commit alongside any changeset version bump -- `scripts/jira/apply.mjs ` applies that file's `updates` to JIRA, creates a remote link to the PR (using `repo-{PR#}` as the remote link's global ID for reliable JIRA indexing), and prints the resolved ticket key (e.g. `PDCL-1234`) to stdout -- New tickets use `PDCL-XXXX-...` sentinel names; before creating, apply checks whether any JIRA issue already has a remote link with global ID `repo-{PR#}`; if found, the existing key is returned (no new ticket created); in either case the XXXX file is deleted and replaced by a real-key file via fetch -- `scripts/jira/fetch.mjs ` fetches the current JIRA state for `` and writes it into the `details` section of ``, preserving any existing `updates` array; both arguments are required +- `scripts/jira/apply.js ` applies that file's `updates` to JIRA (interpolating `{GITHUB_PR_URL}` and `{GITHUB_PR_TITLE}` placeholders) and prints the resolved ticket key (e.g. `PDCL-1234`) to stdout; the remote link to the PR is an explicit entry in the `updates` array with a unique per-ticket `globalId` +- New tickets use `PDCL-XXXX-...` sentinel names; before creating, apply searches JIRA for any issue whose remote links already contain the ticket's unique `globalId`; if found, the existing key is returned (no new ticket created); in either case the XXXX file is deleted and replaced by a real-key file via fetch +- `scripts/jira/fetch.js ` fetches the current JIRA state for `` and writes a fresh `details`-only snapshot to `` (no `updates` section); both arguments are required +- `scripts/jira/process.js ` orchestrates apply + fetch for a single file; used by both the build workflow loop and as a CLI entry point - A new `/jira-propose` Claude Code action inspects current git changes and chat context, searches `.jira/` for a matching ticket file, and creates one locally if none exists — **no JIRA API calls are made locally** - Existing `scripts/createJiraTicket.js` and related scripts are superseded and will be removed; their field/template knowledge (project key, component IDs, custom fields) is migrated into the YAML schema and helper scripts @@ -23,7 +24,7 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - `jira-yaml-schema`: YAML file format and directory conventions for representing JIRA ticket state and pending updates - `jira-apply-workflow`: Job added to the existing build workflow that applies `.jira/` YAML files to JIRA on every push to `main`, including remote-link creation and idempotency logic -- `jira-fetch-script`: `scripts/jira/fetch.mjs` that generates or updates a `.jira/` YAML file's `details` section from a live JIRA ticket, preserving any existing `updates` +- `jira-fetch-script`: `scripts/jira/fetch.js` that writes a fresh `details`-only snapshot from a live JIRA ticket; `scripts/jira/process.js` orchestrates apply + fetch together - `jira-propose-action`: Claude Code `/jira-propose` slash command that creates or updates `.jira/` YAML files locally based on current changes — no JIRA API calls ### Modified Capabilities @@ -32,7 +33,7 @@ The team's JIRA backlog management is disconnected from the codebase — ticket - New `.jira/` directory and files added to all PRs that touch JIRA tickets - `.github/workflows/version-and-publish.yml` gains a new `apply-jira` job; no new workflow file is created -- New `scripts/jira/apply.mjs` and `scripts/jira/fetch.mjs` Node.js scripts; both reuse `scripts/team/config.js` for base URL and project key +- New `scripts/jira/apply.js`, `scripts/jira/fetch.js`, `scripts/jira/api.js`, and `scripts/jira/process.js` Node.js scripts; all reuse `scripts/team/config.js` for base URL and project key - Existing `scripts/createJiraTicket.js`, `scripts/openPr.js` JIRA fetch logic, and `scripts/team/` helpers referenced but some superseded - New `.claude/skills/jira-propose/SKILL.md` skill definition (skills can be invoked by the agent automatically; commands cannot) - `JIRA_API_TOKEN` secret will be added to the GitHub Actions `Production` environment diff --git a/openspec/changes/github-jira-yaml-workflow/tasks.md b/openspec/changes/github-jira-yaml-workflow/tasks.md index 25ce7e6f0..a5579f2c3 100644 --- a/openspec/changes/github-jira-yaml-workflow/tasks.md +++ b/openspec/changes/github-jira-yaml-workflow/tasks.md @@ -3,42 +3,52 @@ - [x] 1.1 Create `.jira/` directory with a `.gitkeep` file; JIRA YAML files are tracked in version control - [x] 1.2 Write a `.jira/README.md` documenting: file naming convention, YAML schema (`details` / `updates`), custom field reference (component IDs, issue type IDs, `customfield_23300`), and the expected end-to-end flow (propose skill → PR review → apply script → fetch script → build workflow commit) -## 2. Fetch Script (`scripts/jira/fetch.mjs`) +## 2. Fetch Script (`scripts/jira/fetch.js`) -- [x] 2.1 Create `scripts/jira/fetch.mjs` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard +- [x] 2.1 Create `scripts/jira/fetch.js` as an ES module; require two positional args (`` and ``), exit with usage message if either is missing; wire up `--dry-run` flag and `JIRA_API_TOKEN` guard - [x] 2.2 Implement `GET /rest/api/2/issue/{key}` call (supports any JIRA project, not limited to PDCL); extract non-null fields into a `details` object; omit null/empty-array fields; truncate strings over 500 chars with `...` -- [x] 2.3 Implement file write logic: if file exists, replace only the `details` section and preserve `updates`; if new, create file with only `details` plus `# fetched from JIRA ` comment -- [x] 2.4 Add `--dry-run` output: print target path and YAML content without writing or fetching +- [x] 2.3 Implement file write logic: overwrite the file with only `details` (no `updates` section) plus `# fetched from JIRA ` comment; in `--dry-run` mode, fetch from JIRA and print the would-be content to stdout without writing +- [x] 2.4 Export `fetchFile` for use by `process.js`; script entry point only executes when run directly -## 3. Apply Script (`scripts/jira/apply.mjs`) +## 3. Apply Script (`scripts/jira/apply.js`) -- [x] 3.1 Create `scripts/jira/apply.mjs` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE`/`GITHUB_PR_NUMBER` env-var validation (required only when `updates` is non-empty) -- [x] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, search JIRA for any issue with a remote link whose global ID is `repo-{PR#}` (no pagination — a single search hit is sufficient); if found, use that ticket key and exit 0; if not found, proceed to create -- [x] 3.3 If the file has no `updates` or an empty array: print the resolved ticket key to stdout and exit 0 with no API calls -- [x] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx -- [x] 3.5 Implement remote-link creation after all updates: POST to `/rest/api/2/issue/{key}/remotelink` with `url`, `title`, and `globalId: "repo-{PR#}"`; skip if global ID is already linked -- [x] 3.6 Print the resolved ticket key as the final stdout line (e.g. `PDCL-1234`) -- [x] 3.7 Add `--dry-run` output: print planned API calls and the resolved key without making HTTP requests -- [x] 3.8 Test locally against a real PDCL ticket using `--dry-run` +- [x] 3.1 Create `scripts/jira/apply.js` as an ES module; require one positional `` argument; wire up `--dry-run` flag, `JIRA_API_TOKEN` guard, and `GITHUB_PR_URL`/`GITHUB_PR_TITLE` env-var validation (required only when `updates` is non-empty and not in dry-run) +- [x] 3.2 Implement ticket key resolution: parse `{PROJECT}-{NUMBER}` from filename; for `XXXX` files, extract the `globalId` from the remotelink entry in `updates`; search JIRA for recent issues in parallel (fetching remote links for each via `Promise.all`); if any issue has a remote link matching that `globalId`, reuse that ticket key and PUT the create fields to it (idempotency); if not found, POST to create a new ticket +- [x] 3.3 If the file has no `updates` or an empty array: return the resolved ticket key with no API calls +- [x] 3.4 Implement REST call executor: for each `updates` entry, serialize `body` from YAML to JSON and call JIRA API with `Authorization: Bearer`; fail fast on non-2xx; skip the `POST /rest/api/2/issue` create call for XXXX files (already handled in key resolution); use `eslint-disable-next-line no-await-in-loop` for intentionally sequential update loop +- [x] 3.5 Remote link idempotency via per-ticket unique globalId: the YAML remotelink entry in `updates` carries a unique hex `globalId` string generated at propose time; apply does not auto-inject a remotelink — it is explicit in the `updates` array +- [x] 3.6 Interpolate `{GITHUB_PR_URL}` and `{GITHUB_PR_TITLE}` placeholders in all `body` values before sending +- [x] 3.7 Add `--dry-run` output: log planned non-GET API calls and the resolved key without making mutating HTTP requests; read queries (searchIssues, getRemoteLinks) always run even in dry-run to give accurate previews +- [x] 3.8 Export `applyFile` for use by `process.js`; script entry point only executes when run directly + +## 3b. API Factory (`scripts/jira/api.js`) + +- [x] 3b.1 Create `scripts/jira/api.js` exporting a `createApi({ dryRun, baseUrl, token })` factory for dependency injection in tests +- [x] 3b.2 Expose `request(method, path, body)`, `searchIssues(jql, opts)`, `getRemoteLinks(key)` — dryRun only blocks non-GET requests + +## 3c. Process Orchestrator (`scripts/jira/process.js`) + +- [x] 3c.1 Create `scripts/jira/process.js` that calls `applyFile` then `fetchFile` for a single `.jira/*.yml` file; handles XXXX→real-key filename rename (deletes placeholder, creates new file); skips files with no updates; used by both the build workflow loop and as a CLI entry point +- [x] 3c.2 Export `processFile` for unit tests; vitest suite covers: no-updates skip, nonexistent file, existing ticket update, XXXX→real-key rename ## 4. Build Workflow Integration (`.github/workflows/version-and-publish.yml`) - [x] 4.1 Add a new `apply-jira` job to `version-and-publish.yml` that runs on every push to `main`; use `Production` environment for `JIRA_API_TOKEN` access -- [x] 4.2 Add step to extract `GITHUB_PR_NUMBER`, `GITHUB_PR_URL`, and `GITHUB_PR_TITLE` from the push event's associated PR via `gh pr list --merged` +- [x] 4.2 Add step to extract `GITHUB_PR_URL` and `GITHUB_PR_TITLE` (not PR number) from the merged PR via `gh pr list --state merged` - [x] 4.3 Add step to detect changed `.jira/*.yml` files via `git diff HEAD^1 HEAD --name-only -- '.jira/*.yml'`; skip remaining steps if none -- [x] 4.4 Add loop step: for each changed file that has an `updates` section, run `node scripts/jira/apply.mjs `, capture the printed ticket key; on success, delete the file, derive the new real-key filename (replace `XXXX` with the ticket number), and run `node scripts/jira/fetch.mjs ` +- [x] 4.4 Add loop step: for each changed file, run `node scripts/jira/process.js "$file"` (which handles apply + fetch + XXXX rename internally); capture printed ticket key - [x] 4.5 Add a step after apply-jira that posts a PR comment listing all JIRA tickets created or updated (using `gh pr comment`) -- [x] 4.6 Combine the `.jira/` file additions/deletions with any changeset version-bump changes into a single skip-ci commit; add this as a job step with appropriate `needs` dependencies so JIRA and changeset changes land together +- [x] 4.6 Add a commit step that stages all `.jira/` changes and commits with `[skip ci]`; the `publish` job declares `needs: [apply-jira]` so JIRA and changeset changes are coordinated ## 5. `/jira-propose` Claude Code Skill - [x] 5.1 Create `.claude/skills/jira-propose/SKILL.md` skill file with instructions for the propose action (skills can be invoked automatically by the agent; commands cannot) - [x] 5.2 Implement logic to scan `.jira/*.yml` files and match against current git diff, branch name, and recent commit messages -- [x] 5.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields +- [x] 5.3 Implement new-ticket YAML generation: populate `summary`, `description` (including business value: customer names, who benefits, elevator-pitch value statement), `issuetype`, `project`, `components`, `customfield_23300` with defaults from `scripts/team/api.js` ISSUE_TEMPLATES; include inline YAML comments for custom fields; generate a unique hex `globalId` per ticket for the remotelink entry - [x] 5.4 Implement existing-ticket update: when a match is found, append or replace the `updates` array in the existing file - [x] 5.5 Implement issue-type heuristic: default to `story` (id `7`); use `bug` (id `1`) when commit messages or diff context suggest a fix ## 6. Cleanup and Documentation -- [x] 6.1 Create `CLAUDE.md` if it does not exist, and update the project README, with the full `.jira/` workflow: propose → PR review → build applies → fetch refreshes +- [x] 6.1 README updated with `.jira/` workflow overview; CLAUDE.md was created during review but subsequently removed per reviewer request (documentation lives in `.jira/README.md` and the skill file) - [ ] 6.2 Add `JIRA_API_TOKEN` secret to the `Production` GitHub Actions environment diff --git a/scripts/jira/api.js b/scripts/jira/api.js index eebfcb07f..09b635d3f 100644 --- a/scripts/jira/api.js +++ b/scripts/jira/api.js @@ -55,14 +55,5 @@ export default function createApi({ dryRun = false, baseUrl, token }) { return data.issues ?? []; }; - const getRemoteLinks = async (key) => { - const response = await fetch( - `${baseUrl}/rest/api/2/issue/${key}/remotelink`, - { headers: authHeaders }, - ); - if (!response.ok) return []; - return response.json(); - }; - - return { dryRun, request, searchIssues, getRemoteLinks }; + return { dryRun, request, searchIssues }; } diff --git a/scripts/jira/apply.js b/scripts/jira/apply.js index a712ee96e..dccecdcef 100644 --- a/scripts/jira/apply.js +++ b/scripts/jira/apply.js @@ -16,7 +16,7 @@ import { basename } from "path"; import { fileURLToPath } from "url"; import { load as yamlLoad } from "js-yaml"; import createApi from "./api.js"; -import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "./config.js"; // Recursively replace {PLACEHOLDER} tokens in body values. const interpolate = (value, vars) => { @@ -32,8 +32,26 @@ const interpolate = (value, vars) => { return value; }; +// Parse filename → { project, ticketKey (if numeric), globalId (if non-numeric) }. +// e.g. "PDCL-1234-title.yml" → ticketKey="PDCL-1234", globalId=null +// "PDCL-a3f8b2c1-title.yml" → ticketKey=null, globalId="a3f8b2c1" +const parseFilename = (filename) => { + const base = basename(filename, ".yml"); + const match = base.match(/^([A-Z]+)-([a-zA-Z0-9]+)/); + if (!match) + throw new Error(`Cannot parse ticket key from filename: ${filename}`); + const [, project, keyPart] = match; + if (/^\d+$/.test(keyPart)) { + return { project, ticketKey: `${project}-${keyPart}`, globalId: null }; + } + return { project, ticketKey: null, globalId: keyPart }; +}; + /** * Apply a .jira/*.yml file's updates to JIRA. + * For new tickets (non-numeric key in filename), the globalId is used as a JIRA label + * so that re-runs find the existing ticket instead of creating a duplicate. + * A remote link from the ticket to the PR is always created (idempotent via PR URL). * @param {string} filename * @param {{ api: object, prUrl?: string, prTitle?: string }} opts * @returns {Promise} resolved ticket key, e.g. "PDCL-1234" @@ -42,87 +60,57 @@ export const applyFile = async ( filename, { api, prUrl = "", prTitle = "" }, ) => { - const fileBase = basename(filename, ".yml"); - const keyMatch = fileBase.match(/^([A-Z]+-(?:XXXX|\d+))/); - if (!keyMatch) - throw new Error(`Cannot parse ticket key from filename: ${filename}`); + const { project, ticketKey: parsedKey, globalId } = parseFilename(filename); + let ticketKey = parsedKey; - const fileKey = keyMatch[1]; - const isNewTicket = fileKey.includes("XXXX"); const parsed = yamlLoad(readFileSync(filename, "utf8")) ?? {}; const updates = Array.isArray(parsed.updates) ? parsed.updates : []; - const hasUpdates = updates.length > 0; const vars = { GITHUB_PR_URL: prUrl, GITHUB_PR_TITLE: prTitle }; - // For new tickets, find the remote-link entry to get its globalId (idempotency key). - const remoteLinkUpdate = updates.find( - (u) => u.method === "POST" && String(u.path).includes("/remotelink"), - ); - const globalId = remoteLinkUpdate?.body?.globalId; - - const resolveKey = async () => { - if (!isNewTicket) return fileKey; - - // Search for an existing ticket that already has this globalId on its remote links. - if (globalId) { - const issues = await api.searchIssues( - `project = PDCL AND created >= startOfDay("-7d") ORDER BY created DESC`, - ); - // Fetch all remote links in parallel then find the match. - const linkResults = await Promise.all( - issues.map((issue) => api.getRemoteLinks(issue.key)), - ); - const matchIndex = linkResults.findIndex((links) => - links.some((l) => l.globalId === globalId), - ); - if (matchIndex !== -1) { - const issue = issues[matchIndex]; - console.log( - `Found existing ticket ${issue.key} via globalId ${globalId}`, - ); - // Update the existing ticket with the create details to ensure idempotency. - const createUpdate = updates.find( - (u) => u.method === "POST" && u.path === "/rest/api/2/issue", + // For new tickets: check if already created via label (idempotency). + if (globalId && !ticketKey) { + const issues = await api.searchIssues( + `project = ${project} AND labels = "${globalId}"`, + ); + if (issues.length > 0) { + ticketKey = issues[0].key; + console.log(`Found existing ticket ${ticketKey} via label ${globalId}`); + } + } + + for (const update of updates) { + const isCreate = + update.method === "POST" && String(update.path) === "/rest/api/2/issue"; + + if (isCreate) { + if (!ticketKey) { + // eslint-disable-next-line no-await-in-loop + const data = await api.request( + "POST", + "/rest/api/2/issue", + interpolate(update.body, vars), ); - if (createUpdate?.body?.fields) { - await api.request("PUT", `/rest/api/2/issue/${issue.key}`, { - fields: createUpdate.body.fields, - }); - } - return issue.key; + ticketKey = data.key ?? `${project}-UNKNOWN`; } + // Skip if ticket already exists (idempotent). + continue; } - // No existing ticket found — create one. - const createUpdate = updates.find( - (u) => u.method === "POST" && u.path === "/rest/api/2/issue", - ); - if (!createUpdate) - throw new Error( - "XXXX file has no POST /rest/api/2/issue entry in updates", - ); - const data = await api.request( - "POST", - "/rest/api/2/issue", - createUpdate.body, - ); - return data.key ?? "PDCL-XXXX"; - }; - - const ticketKey = await resolveKey(); - - if (!hasUpdates) return ticketKey; - - const isCreateCall = (u) => - isNewTicket && u.method === "POST" && u.path === "/rest/api/2/issue"; - - for (const update of updates) { - if (isCreateCall(update)) continue; - const path = String(update.path).replace(/\{key\}/g, ticketKey); - const body = interpolate(update.body, vars); + // All other updates run only when we have a ticket key. + if (!ticketKey) continue; + const path = String(update.path).replace(/{key}/g, ticketKey); // eslint-disable-next-line no-await-in-loop - await api.request(update.method, path, body); + await api.request(update.method, path, interpolate(update.body, vars)); + } + + // Auto-create a remote link to the PR for every processed ticket (idempotent via PR URL). + if (ticketKey && prUrl) { + await api.request("POST", `/rest/api/2/issue/${ticketKey}/remotelink`, { + globalId: prUrl, + relationship: "mentioned in", + object: { url: prUrl, title: prTitle || prUrl }, + }); } return ticketKey; diff --git a/scripts/jira/apply.spec.js b/scripts/jira/apply.spec.js index 19d55af5b..0cf7ccc82 100644 --- a/scripts/jira/apply.spec.js +++ b/scripts/jira/apply.spec.js @@ -19,14 +19,16 @@ import { applyFile } from "./apply.js"; // Unique prefix per spec file avoids temp-file collisions when tests run in parallel. const uid = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`; +// Existing ticket file: PDCL-1234-...yml const tempFile = (content) => { const path = join(tmpdir(), `PDCL-1234-apply-spec-${uid()}.yml`); writeFileSync(path, content, "utf8"); return path; }; -const xxxxFile = (content) => { - const path = join(tmpdir(), `PDCL-XXXX-apply-spec-${uid()}.yml`); +// New ticket file: PDCL-{globalId}-...yml +const globalIdFile = (globalId, content) => { + const path = join(tmpdir(), `PDCL-${globalId}-apply-spec-${uid()}.yml`); writeFileSync(path, content, "utf8"); return path; }; @@ -37,7 +39,6 @@ const mockApi = (overrides = {}) => ({ method === "POST" ? { key: "PDCL-9999" } : {}, ), searchIssues: vi.fn(async () => []), - getRemoteLinks: vi.fn(async () => []), ...overrides, }); @@ -61,13 +62,12 @@ updates: it("calls JIRA with interpolated PR URL and title", async () => { const file = tempFile(` updates: - - path: /rest/api/2/issue/PDCL-1234/remotelink - method: POST + - path: /rest/api/2/issue/PDCL-1234 + method: PUT body: - globalId: abc-123 - object: - url: "{GITHUB_PR_URL}" - title: "{GITHUB_PR_TITLE}" + update: + summary: + - set: "{GITHUB_PR_TITLE}" `); const api = mockApi(); await applyFile(file, { @@ -76,31 +76,64 @@ updates: prTitle: "My PR", }); expect(api.request).toHaveBeenCalledWith( - "POST", - "/rest/api/2/issue/PDCL-1234/remotelink", + "PUT", + "/rest/api/2/issue/PDCL-1234", expect.objectContaining({ - object: expect.objectContaining({ - url: "https://github.com/adobe/alloy/pull/99", - title: "My PR", + update: expect.objectContaining({ + summary: [{ set: "My PR" }], }), }), ); unlinkSync(file); }); - it("returns key immediately when there are no updates", async () => { + it("returns key immediately when there are no updates (no API calls except remote link)", async () => { const file = tempFile(`details:\n key: PDCL-1234\n`); const api = mockApi(); const key = await applyFile(file, { api }); expect(key).toBe("PDCL-1234"); + // No updates in file, so no non-remotelink request should be made expect(api.request).not.toHaveBeenCalled(); unlinkSync(file); }); + + it("auto-creates a remote link when prUrl is provided", async () => { + const file = tempFile(` +updates: + - path: /rest/api/2/issue/PDCL-1234 + method: PUT + body: + update: + summary: + - set: "Updated" +`); + const api = mockApi(); + await applyFile(file, { + api, + prUrl: "https://github.com/adobe/alloy/pull/99", + prTitle: "My PR", + }); + expect(api.request).toHaveBeenCalledWith( + "POST", + "/rest/api/2/issue/PDCL-1234/remotelink", + expect.objectContaining({ + globalId: "https://github.com/adobe/alloy/pull/99", + object: expect.objectContaining({ + url: "https://github.com/adobe/alloy/pull/99", + title: "My PR", + }), + }), + ); + unlinkSync(file); + }); }); -describe("applyFile — new ticket (XXXX)", () => { +describe("applyFile — new ticket (globalId in filename)", () => { it("creates ticket and returns real key when no existing ticket found", async () => { - const file = xxxxFile(` + const gid = "abc12345"; + const file = globalIdFile( + gid, + ` updates: - path: /rest/api/2/issue method: POST @@ -108,36 +141,39 @@ updates: fields: project: { key: PDCL } summary: New feature - - path: /rest/api/2/issue/{key}/remotelink - method: POST - body: - globalId: unique-abc-123 - object: - url: "{GITHUB_PR_URL}" -`); + labels: + - ${gid} +`, + ); const api = mockApi(); const key = await applyFile(file, { api, prUrl: "https://github.com/adobe/alloy/pull/1", + prTitle: "My PR", }); expect(key).toBe("PDCL-9999"); - // Create call executed + // Label search found nothing → create called expect(api.request).toHaveBeenCalledWith( "POST", "/rest/api/2/issue", expect.any(Object), ); - // Remotelink call executed with resolved key + // Auto remote link created expect(api.request).toHaveBeenCalledWith( "POST", "/rest/api/2/issue/PDCL-9999/remotelink", - expect.any(Object), + expect.objectContaining({ + globalId: "https://github.com/adobe/alloy/pull/1", + }), ); unlinkSync(file); }); - it("finds existing ticket via globalId and updates it instead of creating", async () => { - const file = xxxxFile(` + it("finds existing ticket via label and skips create", async () => { + const gid = "existing99"; + const file = globalIdFile( + gid, + ` updates: - path: /rest/api/2/issue method: POST @@ -145,20 +181,23 @@ updates: fields: project: { key: PDCL } summary: New feature - - path: /rest/api/2/issue/{key}/remotelink - method: POST + labels: + - ${gid} + - path: /rest/api/2/issue/{key} + method: PUT body: - globalId: existing-global-id - object: - url: "{GITHUB_PR_URL}" -`); + update: + summary: + - set: "Updated" +`, + ); const api = mockApi({ searchIssues: vi.fn(async () => [{ key: "PDCL-5678" }]), - getRemoteLinks: vi.fn(async () => [{ globalId: "existing-global-id" }]), }); const key = await applyFile(file, { api, prUrl: "https://github.com/adobe/alloy/pull/1", + prTitle: "My PR", }); expect(key).toBe("PDCL-5678"); // Should NOT have called create @@ -167,26 +206,37 @@ updates: "/rest/api/2/issue", expect.any(Object), ); - // Should have updated the existing ticket with create fields + // Should have applied the PUT with resolved key expect(api.request).toHaveBeenCalledWith( "PUT", "/rest/api/2/issue/PDCL-5678", - expect.objectContaining({ fields: expect.any(Object) }), + expect.any(Object), ); unlinkSync(file); }); - it("throws when XXXX file has no create entry", async () => { - const file = xxxxFile(` + it("skips non-create updates when no ticket key available", async () => { + const gid = "noop1234"; + // Only has a PUT, no POST create — no ticket key can be resolved + const file = globalIdFile( + gid, + ` updates: - - path: /rest/api/2/issue/PDCL-1234 + - path: /rest/api/2/issue/{key} method: PUT body: - update: {} -`); + update: + summary: + - set: "Should not run" +`, + ); const api = mockApi(); - await expect(applyFile(file, { api })).rejects.toThrow( - "XXXX file has no POST /rest/api/2/issue entry", + // No searchIssues result, no create → ticketKey stays null → PUT is skipped + await applyFile(file, { api }); + expect(api.request).not.toHaveBeenCalledWith( + "PUT", + expect.any(String), + expect.any(Object), ); unlinkSync(file); }); diff --git a/scripts/jira/config.js b/scripts/jira/config.js new file mode 100644 index 000000000..face9a87c --- /dev/null +++ b/scripts/jira/config.js @@ -0,0 +1,16 @@ +/* +Copyright 2025 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +export const JIRA_BASE_URL = + process.env.JIRA_BASE_URL ?? "https://jira.corp.adobe.com"; + +export const JIRA_API_TOKEN = process.env.JIRA_API_TOKEN ?? null; diff --git a/scripts/jira/fetch.js b/scripts/jira/fetch.js index 021844676..dee61c88b 100644 --- a/scripts/jira/fetch.js +++ b/scripts/jira/fetch.js @@ -15,7 +15,7 @@ import { writeFileSync } from "fs"; import { fileURLToPath } from "url"; import { dump as yamlDump } from "js-yaml"; import createApi from "./api.js"; -import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "./config.js"; const MAX_STRING_LENGTH = 500; diff --git a/scripts/jira/process.js b/scripts/jira/process.js index 6b2b77638..3008bb3fb 100644 --- a/scripts/jira/process.js +++ b/scripts/jira/process.js @@ -18,11 +18,12 @@ import { load as yamlLoad } from "js-yaml"; import createApi from "./api.js"; import { applyFile } from "./apply.js"; import { fetchFile } from "./fetch.js"; -import { JIRA_BASE_URL, JIRA_API_TOKEN } from "../team/config.js"; +import { JIRA_BASE_URL, JIRA_API_TOKEN } from "./config.js"; /** * Process a single .jira/*.yml file: apply updates, refresh details via fetch. - * For XXXX files, deletes the placeholder file and creates a real-key file. + * For new-ticket files (non-numeric key part), deletes the placeholder and creates + * a real-key file (e.g. PDCL-a3f8b2c1-title.yml → PDCL-1234-title.yml). * @param {string} filename * @param {{ api: object, prUrl?: string, prTitle?: string }} opts * @returns {Promise} ticket key if processed, null if skipped @@ -47,11 +48,14 @@ export const processFile = async ( const ticketKey = await applyFile(filename, { api, prUrl, prTitle }); console.log(`Applied: ${ticketKey}`); - // Derive new filename: replace XXXX with the real ticket number. + // Derive new filename: for new tickets (non-numeric key part), replace globalId with ticket number. const dir = dirname(filename); const base = basename(filename); + const keyMatch = base.match(/^[A-Z]+-([a-zA-Z0-9]+)/); + const keyPart = keyMatch?.[1] ?? ""; + const isNewTicket = !/^\d+$/.test(keyPart); const ticketNum = ticketKey.split("-").pop(); - const newBase = base.replace("XXXX", ticketNum); + const newBase = isNewTicket ? base.replace(keyPart, ticketNum) : base; const newFilename = `${dir}/${newBase}`; if (filename !== newFilename && !api.dryRun) { diff --git a/scripts/jira/process.spec.js b/scripts/jira/process.spec.js index c782dc65f..02c179855 100644 --- a/scripts/jira/process.spec.js +++ b/scripts/jira/process.spec.js @@ -24,7 +24,6 @@ const mockApi = (overrides = {}) => ({ : { key: "PDCL-1234", fields: { summary: "Test" } }, ), searchIssues: vi.fn(async () => []), - getRemoteLinks: vi.fn(async () => []), ...overrides, }); @@ -81,11 +80,12 @@ updates: if (existsSync(file)) unlinkSync(file); }); - it("deletes XXXX file and creates real-key file", async () => { + it("deletes globalId file and creates real-key file", async () => { + const gid = "abc12345"; const uid = `${Date.now()}-${Math.random().toString(36).slice(2)}`; - const xxxxPath = join(tmpdir(), `PDCL-XXXX-proc-spec-${uid}.yml`); + const globalIdPath = join(tmpdir(), `PDCL-${gid}-proc-spec-${uid}.yml`); writeFileSync( - xxxxPath, + globalIdPath, ` updates: - path: /rest/api/2/issue @@ -94,26 +94,22 @@ updates: fields: project: { key: PDCL } summary: New feat - - path: /rest/api/2/issue/{key}/remotelink - method: POST - body: - globalId: abc-xyz - object: - url: "{GITHUB_PR_URL}" + labels: + - ${gid} `, "utf8", ); const api = mockApi(); - const result = await processFile(xxxxPath, { + const result = await processFile(globalIdPath, { api, prUrl: "https://github.com/adobe/alloy/pull/2", prTitle: "PR", }); expect(result).toBe("PDCL-9999"); - expect(existsSync(xxxxPath)).toBe(false); - const realPath = xxxxPath.replace("XXXX", "9999"); + expect(existsSync(globalIdPath)).toBe(false); + const realPath = globalIdPath.replace(gid, "9999"); expect(existsSync(realPath)).toBe(true); if (existsSync(realPath)) unlinkSync(realPath); });