Skip to content

fix(schema): replace unevaluatedProperties with additionalProperties#8285

Merged
jdx merged 1 commit intomainfrom
fix/schema-unevaluated-properties
Feb 21, 2026
Merged

fix(schema): replace unevaluatedProperties with additionalProperties#8285
jdx merged 1 commit intomainfrom
fix/schema-unevaluated-properties

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Feb 21, 2026

Summary

  • Replace unevaluatedProperties with additionalProperties in the task/task_template JSON schema definitions to fix Tombi TOML LSP compatibility
  • Move extends property into task_props so allOf/$ref indirection is no longer needed
  • Add e2e test validating the schema with tombi lint in strict mode

Fixes #8254

Context

PR #8145 refactored the task schema to use allOf + $ref + unevaluatedProperties: false. While valid JSON Schema 2019-09, Tombi doesn't support unevaluatedProperties with allOf/$ref, causing it to reject valid task properties (description, depends, run, dir, quiet, usage, etc.) in strict mode.

The fix moves extends into task_props directly and uses additionalProperties: false, eliminating the need for allOf wrappers entirely. This also means task_template gains an extends property, which as noted in the discussion is a natural feature (templates extending other templates).

Test plan

  • Verified with tombi lint --strict that valid task properties are accepted
  • Verified that invalid properties are still rejected
  • Verified against upstream schema that the original bug reproduces
  • mise run lint passes
  • e2e test config/test_schema_tombi passes
  • Schema lint passes (schema/mise.json and schema/mise-task.json valid)

🤖 Generated with Claude Code


Note

Low Risk
Schema-only changes plus a new e2e check; main risk is inadvertently tightening/loosening task validation for editors/LSPs due to the schema shape rewrite.

Overview
Fixes Tombi strict-mode compatibility for task schemas by replacing the allOf + unevaluatedProperties pattern with fully inlined task/task_template properties and additionalProperties: false, ensuring valid task fields are accepted while unknown fields are rejected.

Updates xtasks/render/schema.ts to synthesize task_template from task_props and rewrite the object variant of task to include extends without schema indirection, and adds e2e/config/test_schema_tombi to regression-test both the valid and invalid cases with tombi lint.

Written by Cursor Bugbot for commit 9d64bb5. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings February 21, 2026 17:00
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical compatibility issue with the Tombi TOML LSP when validating mise configuration files. The previous schema design, utilizing unevaluatedProperties in conjunction with allOf and $ref, caused Tombi to incorrectly reject valid task properties. The solution involves refactoring the schema to use additionalProperties and simplifying the inheritance mechanism for task properties, thereby ensuring correct validation behavior and improving schema clarity. A new e2e test has been added to prevent future regressions.

Highlights

  • Schema Compatibility Fix: Replaced unevaluatedProperties with additionalProperties in the task and task_template JSON schema definitions to resolve compatibility issues with Tombi TOML LSP in strict mode.
  • Schema Structure Simplification: Moved the extends property directly into task_props, eliminating the need for allOf and $ref indirection, and allowing task templates to also use extends.
  • New End-to-End Test: Added an end-to-end test to validate the updated schema's compatibility with tombi lint in strict mode, ensuring both valid and invalid properties are correctly handled.
Changelog
  • e2e/config/test_schema_tombi
    • Added a new end-to-end test script to verify tombi lint compatibility.
    • Configured tombi.toml to use the local mise.json schema in strict mode.
    • Included a mise.toml example with valid task properties to confirm successful linting.
    • Included a mise-bad.toml example with an invalid property to confirm linting failure.
  • schema/mise-task.json
    • Removed allOf and unevaluatedProperties: false from the task definition, replacing it with a direct $ref to task_props.
    • Removed allOf and unevaluatedProperties: false from the task_template definition, replacing it with a direct $ref to task_props.
    • Moved the extends property definition from the task definition into task_props.
    • Added additionalProperties: false to task_props.
  • schema/mise.json
    • Removed allOf and unevaluatedProperties: false from the task definition, replacing it with a direct $ref to task_props.
    • Removed allOf and unevaluatedProperties: false from the task_template definition, replacing it with a direct $ref to task_props.
    • Moved the extends property definition from the task definition into task_props.
    • Added additionalProperties: false to task_props.
Activity
  • No human activity was detected on this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively resolves the JSON schema compatibility issue with Tombi by replacing unevaluatedProperties with the more widely supported additionalProperties. The refactoring to move the extends property into task_props and remove the allOf wrappers is a clean solution that simplifies the schema. I appreciate the addition of the e2e test, which provides good coverage for this fix and helps prevent future regressions. The changes look good to me.

Comment on lines +56 to +66
cat >"$HOME/tombi.toml" <<EOF
toml-version = "v1.0.0"

[schema]
enabled = true
strict = true

[[schemas]]
path = "file://$SCHEMA_PATH"
include = ["mise-bad.toml"]
EOF
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This block of code to create tombi.toml is very similar to the one on lines 12-22. To avoid duplication and improve maintainability, consider extracting this logic into a shell function that accepts the include file as a parameter.

For example:

setup_tombi_config() {
  local include_file="$1"
  cat >"$HOME/tombi.toml" <<EOF
toml-version = "v1.0.0"

[schema]
enabled = true
strict = true

[[schemas]]
path = "file://$SCHEMA_PATH"
include = ["$include_file"]
EOF
}

You could then call this function like setup_tombi_config "mise.toml" and setup_tombi_config "mise-bad.toml".

@jdx jdx force-pushed the fix/schema-unevaluated-properties branch from 4c93170 to 30ab75c Compare February 21, 2026 17:06
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a JSON schema compatibility issue with Tombi TOML LSP by replacing unevaluatedProperties with additionalProperties and simplifying the task schema structure. While unevaluatedProperties is valid in JSON Schema 2019-09, Tombi doesn't support it with allOf/$ref, causing valid task properties to be rejected in strict mode.

Changes:

  • Simplified task schema by moving extends property into task_props definition, eliminating need for allOf wrappers
  • Replaced unevaluatedProperties: false with additionalProperties: false throughout task schemas
  • Added e2e test to validate schema compatibility with Tombi in strict mode

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
schema/mise.json Simplified task schema by moving extends into task_props and using additionalProperties
schema/mise-task.json Applied same schema changes as mise.json for consistency
e2e/config/test_schema_tombi Added regression test validating Tombi strict mode compatibility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@jdx jdx force-pushed the fix/schema-unevaluated-properties branch from 30ab75c to 8eea061 Compare February 21, 2026 17:10
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is ON, but a Cloud Agent failed to start.

Tombi TOML LSP doesn't support `unevaluatedProperties` with
`allOf`/`$ref`, causing it to reject valid task properties like
`description`, `depends`, `run`, etc. in strict mode.

Fix by moving `extends` into `task_props` and using
`additionalProperties: false` directly, eliminating the need for
`allOf` wrappers and `unevaluatedProperties` entirely.

Fixes #8254

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the fix/schema-unevaluated-properties branch from 8eea061 to 9d64bb5 Compare February 21, 2026 17:22
@jdx jdx enabled auto-merge (squash) February 21, 2026 17:37
@jdx jdx merged commit 4245750 into main Feb 21, 2026
35 checks passed
@jdx jdx deleted the fix/schema-unevaluated-properties branch February 21, 2026 17:38
@github-actions
Copy link

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.17 x -- echo 18.0 ± 0.5 16.7 20.1 1.00
mise x -- echo 18.8 ± 0.6 17.3 20.3 1.04 ± 0.05

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.17 env 17.7 ± 0.8 16.4 31.7 1.00
mise env 18.3 ± 1.0 16.7 29.0 1.03 ± 0.07

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.17 hook-env 18.1 ± 0.5 16.9 19.8 1.00
mise hook-env 18.6 ± 0.6 17.4 20.4 1.03 ± 0.04

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.17 ls 16.9 ± 0.5 15.6 19.0 1.00
mise ls 17.5 ± 0.6 16.0 19.6 1.03 ± 0.05

xtasks/test/perf

Command mise-2026.2.17 mise Variance
install (cached) 94ms 93ms +1%
ls (cached) 63ms 63ms +0%
bin-paths (cached) 67ms 65ms +3%
task-ls (cached) 691ms 695ms +0%

jdx pushed a commit that referenced this pull request Feb 21, 2026
### 🚀 Features

- **(install)** auto-lock all platforms after tool installation by @jdx
in [#8277](#8277)

### 🐛 Bug Fixes

- **(config)** respect --yes flag for config trust prompts by @jdx in
[#8288](#8288)
- **(exec)** strip shims from PATH on Unix to prevent infinite recursion
by @jdx in [#8276](#8276)
- **(install)** validate --locked before --dry-run short-circuit by
@altendky in [#8290](#8290)
- **(release)** refresh PATH after mise up in release-plz by @jdx in
[#8292](#8292)
- **(schema)** replace unevaluatedProperties with additionalProperties
by @jdx in [#8285](#8285)
- **(task)** avoid duplicated stderr on task failure in replacing mode
by @jdx in [#8275](#8275)
- **(task)** use process groups to kill child process trees on Unix by
@jdx in [#8279](#8279)
- **(task)** run depends_post tasks even when parent task fails by @jdx
in [#8274](#8274)
- **(task)** suggest similar commands when mistyping a CLI subcommand by
@jdx in [#8286](#8286)
- **(task)** execute monorepo subdirectory prepare steps from root by
@jdx in [#8291](#8291)
- **(upgrade)** don't force-reinstall already installed versions by @jdx
in [#8282](#8282)
- **(watch)** restore terminal state after watchexec exits by @jdx in
[#8273](#8273)

### 📚 Documentation

- clarify that MISE_CEILING_PATHS excludes the ceiling directory itself
by @jdx in [#8283](#8283)

### Chore

- replace gen-release-notes script with communique by @jdx in
[#8289](#8289)

### New Contributors

- @altendky made their first contribution in
[#8290](#8290)

## 📦 Aqua Registry Updates

#### New Packages (4)

-
[`Skarlso/crd-to-sample-yaml`](https://github.com/Skarlso/crd-to-sample-yaml)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
-
[`swanysimon/markdownlint-rs`](https://github.com/swanysimon/markdownlint-rs)
- [`tmux/tmux-builds`](https://github.com/tmux/tmux-builds)

#### Updated Packages (2)

-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`k1LoW/runn`](https://github.com/k1LoW/runn)
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Feb 22, 2026
## [2026.2.18](https://github.com/jdx/mise/compare/v2026.2.17..v2026.2.18) - 2026-02-21

### 🚀 Features

- **(install)** auto-lock all platforms after tool installation by @jdx in [#8277](jdx/mise#8277)

### 🐛 Bug Fixes

- **(config)** respect --yes flag for config trust prompts by @jdx in [#8288](jdx/mise#8288)
- **(exec)** strip shims from PATH on Unix to prevent infinite recursion by @jdx in [#8276](jdx/mise#8276)
- **(install)** validate --locked before --dry-run short-circuit by @altendky in [#8290](jdx/mise#8290)
- **(release)** refresh PATH after mise up in release-plz by @jdx in [#8292](jdx/mise#8292)
- **(schema)** replace unevaluatedProperties with additionalProperties by @jdx in [#8285](jdx/mise#8285)
- **(task)** avoid duplicated stderr on task failure in replacing mode by @jdx in [#8275](jdx/mise#8275)
- **(task)** use process groups to kill child process trees on Unix by @jdx in [#8279](jdx/mise#8279)
- **(task)** run depends_post tasks even when parent task fails by @jdx in [#8274](jdx/mise#8274)
- **(task)** suggest similar commands when mistyping a CLI subcommand by @jdx in [#8286](jdx/mise#8286)
- **(task)** execute monorepo subdirectory prepare steps from root by @jdx in [#8291](jdx/mise#8291)
- **(upgrade)** don't force-reinstall already installed versions by @jdx in [#8282](jdx/mise#8282)
- **(watch)** restore terminal state after watchexec exits by @jdx in [#8273](jdx/mise#8273)

### 📚 Documentation

- clarify that MISE_CEILING_PATHS excludes the ceiling directory itself by @jdx in [#8283](jdx/mise#8283)

### Chore

- replace gen-release-notes script with communique by @jdx in [#8289](jdx/mise#8289)

### New Contributors

- @altendky made their first contribution in [#8290](jdx/mise#8290)

### 📦 Aqua Registry Updates

#### New Packages (4)

- [`Skarlso/crd-to-sample-yaml`](https://github.com/Skarlso/crd-to-sample-yaml)
- [`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
- [`swanysimon/markdownlint-rs`](https://github.com/swanysimon/markdownlint-rs)
- [`tmux/tmux-builds`](https://github.com/tmux/tmux-builds)

#### Updated Packages (2)

- [`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`k1LoW/runn`](https://github.com/k1LoW/runn)

## [2026.2.17](https://github.com/jdx/mise/compare/v2026.2.16..v2026.2.17) - 2026-02-19

### 🚀 Features

- **(prepare)** update mtime of outputs after command is run by @halms in [#8243](jdx/mise#8243)

### 🐛 Bug Fixes

- **(install)** use backend bin paths for per-tool postinstall hooks by @jdx in [#8234](jdx/mise#8234)
- **(use)** write to config.toml instead of config.local.toml by @jdx in [#8240](jdx/mise#8240)
- default legacy .mise.backend installs to non-explicit by @jean-humann in [#8245](jdx/mise#8245)

### 🚜 Refactor

- **(config)** consolidate flat task_* settings into nested task.* by @jdx in [#8239](jdx/mise#8239)

### Chore

- **(prepare)** refactor common code into ProviderBase by @halms in [#8246](jdx/mise#8246)

### 📦 Aqua Registry Updates

#### Updated Packages (1)

- [`namespacelabs/foundation/nsc`](https://github.com/namespacelabs/foundation/nsc)
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
…dx#8285)

## Summary

- Replace `unevaluatedProperties` with `additionalProperties` in the
task/task_template JSON schema definitions to fix Tombi TOML LSP
compatibility
- Move `extends` property into `task_props` so `allOf`/`$ref`
indirection is no longer needed
- Add e2e test validating the schema with `tombi lint` in strict mode

Fixes jdx#8254

## Context

PR jdx#8145 refactored the task schema to use `allOf` + `$ref` +
`unevaluatedProperties: false`. While valid JSON Schema 2019-09, Tombi
doesn't support `unevaluatedProperties` with `allOf`/`$ref`, causing it
to reject valid task properties (`description`, `depends`, `run`, `dir`,
`quiet`, `usage`, etc.) in strict mode.

The fix moves `extends` into `task_props` directly and uses
`additionalProperties: false`, eliminating the need for `allOf` wrappers
entirely. This also means `task_template` gains an `extends` property,
which as noted in the discussion is a natural feature (templates
extending other templates).

## Test plan

- [x] Verified with `tombi lint --strict` that valid task properties are
accepted
- [x] Verified that invalid properties are still rejected  
- [x] Verified against upstream schema that the original bug reproduces
- [x] `mise run lint` passes
- [x] e2e test `config/test_schema_tombi` passes
- [x] Schema lint passes (`schema/mise.json` and `schema/mise-task.json`
valid)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Schema-only changes plus a new e2e check; main risk is inadvertently
tightening/loosening task validation for editors/LSPs due to the schema
shape rewrite.
> 
> **Overview**
> Fixes Tombi strict-mode compatibility for task schemas by replacing
the `allOf` + `unevaluatedProperties` pattern with fully inlined
task/task_template `properties` and `additionalProperties: false`,
ensuring valid task fields are accepted while unknown fields are
rejected.
> 
> Updates `xtasks/render/schema.ts` to synthesize `task_template` from
`task_props` and rewrite the object variant of `task` to include
`extends` without schema indirection, and adds
`e2e/config/test_schema_tombi` to regression-test both the valid and
invalid cases with `tombi lint`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
9d64bb5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
risu729 pushed a commit to risu729/mise that referenced this pull request Feb 27, 2026
### 🚀 Features

- **(install)** auto-lock all platforms after tool installation by @jdx
in [jdx#8277](jdx#8277)

### 🐛 Bug Fixes

- **(config)** respect --yes flag for config trust prompts by @jdx in
[jdx#8288](jdx#8288)
- **(exec)** strip shims from PATH on Unix to prevent infinite recursion
by @jdx in [jdx#8276](jdx#8276)
- **(install)** validate --locked before --dry-run short-circuit by
@altendky in [jdx#8290](jdx#8290)
- **(release)** refresh PATH after mise up in release-plz by @jdx in
[jdx#8292](jdx#8292)
- **(schema)** replace unevaluatedProperties with additionalProperties
by @jdx in [jdx#8285](jdx#8285)
- **(task)** avoid duplicated stderr on task failure in replacing mode
by @jdx in [jdx#8275](jdx#8275)
- **(task)** use process groups to kill child process trees on Unix by
@jdx in [jdx#8279](jdx#8279)
- **(task)** run depends_post tasks even when parent task fails by @jdx
in [jdx#8274](jdx#8274)
- **(task)** suggest similar commands when mistyping a CLI subcommand by
@jdx in [jdx#8286](jdx#8286)
- **(task)** execute monorepo subdirectory prepare steps from root by
@jdx in [jdx#8291](jdx#8291)
- **(upgrade)** don't force-reinstall already installed versions by @jdx
in [jdx#8282](jdx#8282)
- **(watch)** restore terminal state after watchexec exits by @jdx in
[jdx#8273](jdx#8273)

### 📚 Documentation

- clarify that MISE_CEILING_PATHS excludes the ceiling directory itself
by @jdx in [jdx#8283](jdx#8283)

### Chore

- replace gen-release-notes script with communique by @jdx in
[jdx#8289](jdx#8289)

### New Contributors

- @altendky made their first contribution in
[jdx#8290](jdx#8290)

## 📦 Aqua Registry Updates

#### New Packages (4)

-
[`Skarlso/crd-to-sample-yaml`](https://github.com/Skarlso/crd-to-sample-yaml)
-
[`kunobi-ninja/kunobi-releases`](https://github.com/kunobi-ninja/kunobi-releases)
-
[`swanysimon/markdownlint-rs`](https://github.com/swanysimon/markdownlint-rs)
- [`tmux/tmux-builds`](https://github.com/tmux/tmux-builds)

#### Updated Packages (2)

-
[`firecow/gitlab-ci-local`](https://github.com/firecow/gitlab-ci-local)
- [`k1LoW/runn`](https://github.com/k1LoW/runn)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants