Skip to content

Commit a1abef1

Browse files
fix(mise): unblock check in fresh worktrees, plus domain-architecture doc refresh (#514)
* fix(mise): keep proto tools off the non-proto critical path api-linter sat in mise.dev.toml's [tools], so it was provisioned for every dev-env task. Its install fails behind a proxy, which aborted format, analyze, test and check — none of which need proto tooling. On Claude Code Web .miserc.toml auto-selects the dev env, so this broke plain `./bin/mise run check` outright. Declare buf and api-linter as task-scoped tools on the proto:* tasks that invoke them. Note what this does NOT fix, since the issue proposes it: pinning. Both tools were already pinned and locked — mise.dev.lock carried buf 1.70.0 and api-linter 2.3.1 with checksums and asset URLs, and the failure happened anyway. Verified on mise 2026.5.8 that a lockfile entry does not suppress api-linter's SLSA provenance call: download and checksum both succeed, only the provenance lookup 403s, and MISE_SLSA_VERIFY=0 does not disable it. mise had recorded github_attestations = "unavailable" and still attempted verification. What scoping buys is blast radius, which is the actual complaint in #510. Also set lockfile = true so mise maintains mise.lock/mise.dev.lock on install rather than only when regenerated by hand (#454). Known trade-off: task-scoped tools are not in a config's [tools] set, so `mise lock` drops them from mise.dev.lock and they re-resolve on a fresh worktree. Moving them to a MISE_ENV=dev,proto env file would keep both properties, at the cost of changing the proto:* invocation. Verified: `./bin/mise run check` completes (1313 tests pass) where it previously died during tool provisioning. Fixes #510 * fix(mise): exclude nested .mise and worktrees from shell file discovery The find in shell/check.sh and shell/format.sh excluded "./.mise/*", anchored at the repo root, so it did not match a *nested* .mise inside an agent worktree. Each worktree under .claude/worktrees/ carries its own extracted Flutter SDK — thousands of vendored .sh files, some of which shfmt rejects — so check aborted before analyze or test ran, pointing at vendored SDK code rather than anything the developer changed. This broke the pre-commit gate for the repo's own documented parallel-agent workflow, whose whole mechanism is agent worktrees. Make the exclusions unanchored and skip worktrees explicitly. Verified against a synthetic worktree tree: the old pattern picks up its scripts, the new one excludes them, and shell:check passes with it present. Fixes #509 * docs: rewrite domain-architecture filter sections against current code Every symbol the filter sections named was removed when filter state moved into DrinkFilterController, and the drift widened with #505/#506. The worked example did not compile against the current code. - applyAllFilters -> filterDrinks, with its real named parameters - BeerProvider._applyFiltersAndSort() -> DrinkFilterController.recompute() as the single recompute path - category: String? -> categories: Set; hideUnavailable: bool -> visibilityFilters: Set - add the missing facet-scoping rule and its two invariants (an active filter is never hidden; allergens must be non-zero-present), plus the deliberate exclusion of free-text search from facet scoping Also correct references to FavoritesService/RatingsService, removed in #391/#395 in favour of UserDataStore, and add the controllers layer to the architecture diagram. Leaving those would have shipped a doc fix that still pointed at deleted classes. Fixes #511 * docs(mise): clarify that scoping contains the failure, not fixes it The comment said a task-scoped tool that fails to provision degrades to a warning and "the task body still runs", which reads as though the task succeeds. It doesn't: proto:* will run its body and fail on `buf: command not found` unless the binary is already on PATH. Spell out that the win is check/test no longer being collateral damage, not that proto linting works without buf. Raised in review on #514. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent af30dc0 commit a1abef1

7 files changed

Lines changed: 297 additions & 91 deletions

File tree

.claude/skills/api-contract/SKILL.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,27 @@ stabilises.
8080

8181
`buf`, `watchexec`, and `github:googleapis/api-linter` are all installed via
8282
GitHub release downloads (aqua backend). In this sandbox the outbound proxy
83-
returned `403 Forbidden` for all three when tested live:
83+
returned `403 Forbidden` for all three when tested live.
84+
85+
> **Since #510**, `buf` (pinned `1.70.0`) and `api-linter` (pinned `2.3.1`) are
86+
> declared as *task-scoped* tools on the `proto:*` tasks rather than in
87+
> `mise.dev.toml`'s `[tools]`. Non-proto tasks (`check`, `test`, `analyze`) no
88+
> longer resolve them at all, so the 403 can't block a Dart test run any more.
89+
> For the `proto:*` tasks themselves the 403 still applies — but as a `WARN`
90+
> rather than a fatal install error.
91+
>
92+
> A lockfile does **not** rescue this, despite being the right mechanism in
93+
> general. Both tools were already pinned and locked in `mise.dev.lock` (mise
94+
> keeps one lockfile per config file — don't check only `mise.lock`), and the
95+
> 403 happened regardless. Verified on mise 2026.5.8: the failing call is SLSA
96+
> provenance verification, download and checksum both succeed, a lock entry
97+
> does not suppress it, and `MISE_SLSA_VERIFY=0` does not disable it.
98+
>
99+
> So proto tooling in this sandbox remains best-effort — push and let
100+
> `ci.yml`'s `proto` job (which installs buf via `buf-action`, a different code
101+
> path) be the first real lint.
102+
103+
The original failure mode:
84104

85105
```
86106
mise ERROR Failed to install tools: aqua:bufbuild/buf@latest, aqua:watchexec/watchexec@2.5.1, github:googleapis/api-linter@latest

.claude/skills/build-and-env/SKILL.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ uses four, plus a Tera-templated auto-selector:
6060
| File | Selected by | Tools / tasks it adds | Audience |
6161
|---|---|---|---|
6262
| `mise.toml` | always (base) | `flutter=3.44.0`, `node=22`, `shellcheck=0.9.0`, `shfmt=3.8.0`; tasks: `generate`, `dart:format*`, `prettier:*`, `fmt:check`, `mise:format`, `format`, `check`, `goldens:update`, `validate:festivals`, `test:worker`, `analyze`, `test`, `coverage` | CI and everyone |
63-
| `mise.dev.toml` | `MISE_ENV=dev` | `watchexec=2.5.1`, `buf=latest`, `github:googleapis/api-linter=latest`; tasks: all `proto:*`, plus file-tasks in `mise-tasks/``dev`, `dev:tunnel`, `build:web`, `build:web:prod`, `serve:release`, `test:e2e*`, `setup:playwright`, `setup:tunnel`, `screenshots:batch`, `test:check-page` | Building/running/proto work |
63+
| `mise.dev.toml` | `MISE_ENV=dev` | env-level: `watchexec=2.5.1` only. `buf=1.70.0` and `github:googleapis/api-linter=2.3.1` are **task-scoped** on the `proto:*` tasks that use them (#510), so they can't block non-proto tasks; tasks: all `proto:*`, plus file-tasks in `mise-tasks/``dev`, `dev:tunnel`, `build:web`, `build:web:prod`, `serve:release`, `test:e2e*`, `setup:playwright`, `setup:tunnel`, `screenshots:batch`, `test:check-page` | Building/running/proto work |
6464
| `mise.human.toml` | `MISE_ENV=dev,human` | `claude`, `cloudflared`, `gh`, `npm:firebase-tools` | Human machines only — never load on an agent |
6565
| `mise.claude-code-web.toml` | `.miserc.toml` auto-select, or explicit `MISE_ENV=claude-code-web` | `[settings] libgit2=false, gix=false` (git-transport fix, §3b); `node=path:/opt/node22`, `python=path:/usr`, `jq=path:/usr` (reuse sandbox-baked binaries instead of downloading) | Claude Code Web sandbox only |
6666

@@ -93,12 +93,40 @@ out `MISE_ENV=claude-code-web,dev`.
9393

9494
The agent proxy in this sandbox returns 403 for direct GitHub release-asset
9595
downloads. `buf`, `watchexec`, and `github:googleapis/api-linter` are all
96-
installed via aqua/GitHub-release backends (`mise.dev.toml:18-26`), so the
97-
**first** task that needs any of them fails mid-install — and because
98-
`.miserc.toml` auto-selects `dev` on Claude Code Web, this means **any**
99-
`./bin/mise run <task>` can trip it, even for a task that itself doesn't need
100-
those tools, if mise decides to resolve/install the full active toolset.
101-
Reproduced live in this session:
96+
installed via aqua/GitHub-release backends, so the **first** task that needs
97+
any of them fails mid-install.
98+
99+
> **Addressed by #510 — and read this before theorising about lockfiles.**
100+
>
101+
> mise keeps **one lockfile per config file**: `mise.toml``mise.lock`,
102+
> `mise.dev.toml``mise.dev.lock`. Both are committed. Checking only
103+
> `mise.lock` and concluding the dev tools are unlocked is a trap — they live
104+
> in `mise.dev.lock`.
105+
>
106+
> `buf` (1.70.0) and `api-linter` (2.3.1) were **already pinned and locked**,
107+
> with checksums and asset URLs, and the 403 happened anyway. **Verified on
108+
> mise 2026.5.8: a lockfile entry does not suppress api-linter's SLSA
109+
> provenance call.** Download and checksum both succeed; only the provenance
110+
> lookup against `api.github.com` 403s, and `MISE_SLSA_VERIFY=0` does not
111+
> disable it. mise had even recorded `github_attestations = "unavailable"` in
112+
> the lock and still attempted verification — likely a mise bug.
113+
>
114+
> So #510 attacks blast radius, not the fetch: `buf` and `api-linter` are now
115+
> *task-scoped* to the `proto:*` tasks, so a non-proto task (`check`, `test`,
116+
> `analyze`) never resolves them, and a scoped tool that fails to fetch emits a
117+
> `WARN` and still runs the task body. `lockfile = true` is set so the locks
118+
> stay maintained. Only `watchexec` remains env-level.
119+
>
120+
> **Trade-off to know:** task-scoped tools aren't in a config's `[tools]` set,
121+
> so `mise lock` drops them from `mise.dev.lock` — those two lose lock coverage
122+
> and re-resolve on a fresh worktree. A `MISE_ENV=dev,proto` env file would
123+
> keep both properties at the cost of changing the `proto:*` invocation.
124+
>
125+
> The history below is retained because it explains the trap.
126+
127+
Historically, because `.miserc.toml` auto-selects `dev` on Claude Code Web,
128+
**any** `./bin/mise run <task>` could trip this, even a task that itself
129+
didn't need those tools. Reproduced live:
102130

103131
```
104132
mise buf@1.70.0 [1/3] download buf-Linux-x86_64.tar.gz

0 commit comments

Comments
 (0)