Repository navigation
Description
Problem
The bootstrap entry point must work before mise or a Go toolchain is installed, but its installation logic remains shell. It selects a cached version and installation path, resolves platform/archive/checksum inputs, installs mise and invokes it (tools/mise-bootstrap:4, tools/mise-bootstrap:56, tools/mise-bootstrap:142, tools/mise-bootstrap:254, tools/mise-bootstrap:294, tools/mise-bootstrap:402), on origin/main at a0347a715fab580ece45edfcb3d13509620459a8.
This split chooses Go migration with a temporary frozen compatibility path, rather than a permanent bootstrap exception to the shell rule. It must preserve the first-run path when the replacement binary is not yet available.
This is the bootstrap split of #332. Part of #588.
Acceptance criteria
- AC1: Version and installation-path selection equal the frozen command's under the existing defaults and environment overrides.
- AC2: An existing file at the selected installation path takes the same cache-hit path as today, without downloading or silently enforcing a different version policy.
- AC3: Platform and archive selection preserve the frozen command's supported OS/architecture/libc outcomes and unsupported-platform refusals.
- AC4: Download-source and checksum selection honor the same configuration precedence and requested version as the frozen command.
- AC5: Failed download, checksum retrieval or checksum validation never results in a newly installed executable or successful bootstrap result.
- AC6: A successful installation produces the same executable bytes, mode decisions, diagnostics and temporary-artifact cleanup as the frozen command for equivalent inputs.
- AC7: Failed platform, installed-version, archive-capability, checksum-tool, cache-path or user-ID probes remain failures even after printing plausible output.
- AC8: Invoking the installed mise preserves the caller's invocation name, arguments, input/output streams, working directory and terminal exit status.
- AC9: Non-functional: when the released replacement command is already available, bootstrap works without a Go toolchain or an existing mise installation.
- AC10: The existing entry point ends as a thin shell wrapper that probes the Go subcommand without side effects and falls back to the frozen shell only when that capability is absent, including first run without any replacement binary.
- AC11: A supported Go failure never triggers shell fallback, repeated installation or a repeated installed-command invocation.
- AC12: Non-functional: release N-2 bootstrap invocations and environment settings remain supported without a raised binary floor, new required configuration or loss of an existing platform's fallback path.
Scope and non-goals
Preserve cache/version/path precedence and leading-version normalization (tools/mise-bootstrap:5); Linux/Darwin, existing architecture and musl selection (tools/mise-bootstrap:56, tools/mise-bootstrap:67); explicit archive format and older-version format behavior (tools/mise-bootstrap:99); archive capability decisions (tools/mise-bootstrap:112); checksum-tool selection and pinned/dynamic checksums (tools/mise-bootstrap:132, tools/mise-bootstrap:142); download alternatives and error reporting (tools/mise-bootstrap:254); installed-version parsing and opt-in matching-version skip behavior within installation (tools/mise-bootstrap:285, tools/mise-bootstrap:309); requested-source precedence (tools/mise-bootstrap:319); extraction, directory-path refusal, root-specific mode/ownership behavior, final move and success cleanup (tools/mise-bootstrap:327); debug/quiet diagnostics (tools/mise-bootstrap:14); and returning to the invoking directory before forwarding (tools/mise-bootstrap:396).
The public entry point currently skips installation whenever the selected path is already a file (tools/mise-bootstrap:399). Do not confuse that contract with the installation helper's narrower optional version check. Keep the helper's failed-version-probe behavior covered without changing the public cache policy.
The entry point suppresses shell-activation help (tools/mise-bootstrap:398). Migrating the unused activation-help variants at tools/mise-bootstrap:365 is a non-goal: this entry point exposes none of them. Preserve the suppression rather than adding activation instructions or editing shell startup files.
Non-goals: a permanent shell exemption, new supported platforms, expanding #333's release-target inventory, a new binary-acquisition mechanism, changing the pinned mise version, stronger cache-version policy, new checksum trust policy, automatic retries, atomic-install redesign, or adding failure cleanup promises beyond the frozen command's behavior. The existing thin compatibility paths for unrelated helpers remain outside this split. Fallback retirement is separate D9 work and must wait until every supported bootstrap environment has a viable replacement path.
Approach
Write failed-probe and no-install-on-invalid-input checks first. Move the installation and selection behavior to Go and compare it against frozen shell using local fixture archives and controlled platform responses. Existing first-run callers must still bootstrap when no replacement command is available. The pull request decides implementation details; it does not introduce a permanent exception or another release distribution interface.
Dependencies
Depends on #542, following #333 → #544 → #382 → #545 → #546 and the #359 release chain. #333 and #544 establish released binaries and normal installation; this split must not assume those installations already exist on first bootstrap. #332 records this migration decision for #334, which owns later shell-limit enforcement. Part of #588.
Size
M. One pull request for the bootstrap behavior, thin compatibility entry point and installation fixtures.
Verify plan
- AC7: first port all bootstrap regressions in
tests/tools/masked-status.bats:123,tests/tools/masked-status.bats:137,tests/tools/masked-status.bats:168,tests/tools/masked-status.bats:177andtests/tools/masked-status.bats:195. For each probe, return plausible output then fail; assert the failure propagates, no untrusted value is accepted and no new executable is installed after the failure. - AC5: first test failed downloads, empty/failed checksum retrieval and mismatched checksums against fixture archives; assert nonzero status, no success diagnostic and no newly installed executable. No test contacts a real download service.
- AC1: default/overridden version, leading
v, cache-root and explicit-install-path fixtures compare selected paths and versions with frozen shell. - AC2: existing-file, absent-file and nonexecutable-cache fixtures compare whether installation runs and the final invocation outcome. Separately cover the helper's optional matching-version branch and rejected failed-version probe; do not add version enforcement to the public cache hit.
- AC3: enumerate every current OS/architecture/libc outcome, explicit OS/architecture/archive overrides, older-version archive behavior and unavailable archive capability. Compare selected artifacts and unsupported-platform refusals; verify existing platforms outside the released replacement inventory still take the frozen fallback when needed.
- AC4: default-source, source override, explicit alternate-source request, alternate-version request, pinned and fetched checksum fixtures compare request selection and precedence. Cover both existing download alternatives and both checksum-tool alternatives, with missing-tool refusals.
- AC6: local archive fixtures cover both supported formats, native and alternate extraction paths, directory-valued destination refusal and root/nonroot mode decisions. Compare installed bytes/modes, stdout/stderr, status and residue after success. Compare failure behavior without inventing rollback or cleanup guarantees.
- AC8: a recording fake installed command checks invocation name, spaced arguments, stdin, separate output streams, working directory and nonzero exit propagation. Successful installation and cache-hit paths emit no activation-help output.
- AC9: provide the released replacement command while making Go and mise unavailable; install and invoke only a fixture mise. Assert neither build tooling nor mise is needed to execute bootstrap selection/installation.
- AC10: no replacement binary, an older binary without the capability and a supported replacement each take the expected path once; assert the read-only probe neither downloads nor installs.
- AC11: supported failure, failure after partial installation and an indeterminate capability probe all return failure with zero shell fallback, zero repeated installation and zero repeated installed-command invocation.
- AC12: compare N-2 environment/argument fixtures on absent, older and new binary paths. Run Go tests for the platform-selection matrix on Linux, macOS and Windows, with native fixture installation and wrapper smoke coverage on supported bootstrap systems. Run focused tests,
mise run lintandmise run teston the reviewed head. All subprocesses, downloads and ownership-sensitive operations are isolated fixtures or stubs. - Definition of done: D1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification. D2 an independent review approves the exact merged head, and every finding has a recorded disposition. D3 required checks pass with no gate loosened. D4 the leak scans the repository specifies are clean, and every post made for this work (comments, descriptions) passes the per-post leak review before it is posted. D5 every commit is signed. D6 the documentation matches, or the description says
No doc impactwith the reason. D7 every commit carries anAssisted-bytrailer and the pull request carries theprovenance:agent-assistedlabel. D8 the change stays within the pull request size limits. D9 follow-up work, including deferred review findings, is filed as issues, each with a Problem section and numbered acceptance criteria and linking this issue; the pull request's Related section lists them, and any code that defers work links its issue. D10 the merge closes this issue through a closing reference, the project board shows the state Done, and a finalStatus:comment names the merge commit.
Risks
A replacement that requires mise to launch cannot bootstrap mise. First-run and absent-binary fixtures prevent that cycle. Cache reuse, musl/archive selection and failure handling can also drift; the frozen matrix covers them. Undo: revert the port. Keep the fallback frozen until N-2 support and bootstrap availability permit separate retirement.
Operator authority
None.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 26, 2026
Refinement: READY — #813 accurately specifies the Go bootstrap port and frozen shell fallback contract
Model: gemini-4-argon-high
Checked
tbhb-dev/devtools#813(0 comments) and referenced issues#332,#588,#333,#542,#544,#382,#545,#546,#359, and#334. Verifiedorigin/mainis ata0347a715fab580ece45edfcb3d13509620459a8.origin/main:tools/mise-bootstrap:4(__mise_bootstrapentry point) andtools/mise-bootstrap:5(XDG_CACHE_HOMEdefault,MISE_VERSIONdefault2026.8.0, leading-vstrip attools/mise-bootstrap:7, andMISE_INSTALL_PATHexport attools/mise-bootstrap:8).tools/mise-bootstrap:14(MISE_DEBUGandMISE_QUIETlogging functionsdebug,info,warn,error, andunsupported_archthroughtools/mise-bootstrap:53).tools/mise-bootstrap:56(get_osmappingDarwintomacosandLinuxtolinux) andtools/mise-bootstrap:67(get_archhandlingMISE_INSTALL_MUSL,uname -oAndroid,ldd /bin/lsmusl detection,x86_64/aarch64/arm64/armv7l, andunsupported_arch).tools/mise-bootstrap:99(get_exthonoringMISE_INSTALL_EXT,^v2024tar.gzfallback, andtar_supports_zstd) andtools/mise-bootstrap:112(tar_supports_zstdcheckingtar --version,zstd,bsdtar,busybox, and GNU tar>= 1.31).tools/mise-bootstrap:132(shasum_binselectingshasumorsha256sum) andtools/mise-bootstrap:142(get_checksumusing static SHA-256 checksums forv2026.8.0or fetchingSHASUMS256.txtviacurl/wget).tools/mise-bootstrap:254(download_fileusingcurlorwgetwith error reporting).tools/mise-bootstrap:285(installed_mise_versionparsing the first field ofmise versionand stripping leadingv),tools/mise-bootstrap:294(install_mise), andtools/mise-bootstrap:309(MISE_INSTALL_SKIP_IF_EXISTSopt-in version-matching skip).tools/mise-bootstrap:319(tarball source precedence across non-current version,MISE_INSTALL_FROM_GITHUB,MISE_TARBALL_URL, and defaulthttps://mise.jdx.dev).tools/mise-bootstrap:327(temporary download/extract directories, checksum validation, directory-valuedMISE_INSTALL_PATHrefusal attools/mise-bootstrap:338, extraction withzstdpipe fallback attools/mise-bootstrap:345,id -urootchown 0:0/chmod 755attools/mise-bootstrap:350, move toMISE_INSTALL_PATH, and cleanup throughtools/mise-bootstrap:360).tools/mise-bootstrap:365(after_finish_help),tools/mise-bootstrap:396(cd -- "$initial_working_dir"),tools/mise-bootstrap:398(local MISE_INSTALL_HELP=0suppressing activation help),tools/mise-bootstrap:399(test -f "$MISE_INSTALL_PATH" || install), andtools/mise-bootstrap:402(exec -a "$0" "$MISE_INSTALL_PATH" "$@").origin/main:tests/tools/masked-status.bats:123(get_osandget_archfailing after printing validuname/lddoutput).tests/tools/masked-status.bats:137(installed_mise_versionrejecting output from a failing binary).tests/tools/masked-status.bats:168(tar_supports_zstdrejecting output from a failingtar).tests/tools/masked-status.bats:177(install_misestopping beforeget_checksumwhenshasum_binfails).tests/tools/masked-status.bats:195(install_misestopping whendirnameorid -uprints output and fails).AC10,AC11, andAC12match the shared thin-wrapper contract across#332and#329: side-effect-free capability probe (no downloads or writes during probing), fallback to the frozen shell implementation only when the Go capability or binary is absent (including first run and platforms outside#333's four release targetslinux/amd64,linux/arm64,darwin/arm64,windows/amd64), and zero shell fallback or repeated execution after any supported Go failure or indeterminate probe.docs/compatibility.md:3) without prescribing package/file layout or implementation details.#542and#333 → #544 → #382 → #545 → #546along the#359chain, parent#332, downstream gate#334, and epic#588are all real and accurately classified.tools/mise-bootstrap, Go command/internal packages, andtests/tools/masked-status.bats) are outsidegolden_paths,constitutional_paths,gate_config_paths, andowner_pathsin.agents/agent-skills.conf:4-9, soOperator authority: None.is accurate.Gaps
None.
Split
No further split needed; size
Mfits one pull request covering the bootstrap logic, thin wrapper entry point, and offline fixtures.Definition of done
The definition of done for #813 (Feature). Tick each item and give its evidence.
## Verify planspecifies concrete offline checks forAC1–AC12and explicitly requires citing each AC ID with commands and results in the pull request's Verification section (D1).## Verify plan(D2) requires independent reviewer approval of the exact merged head and a recorded disposition for every finding.## Verify plan(AC12,D3) requiresmise run lint,mise run test, and required checks to pass with no gate loosened.check-leaks.shwith the repository's private-strings list, and the leak review of each post. — Planning coverage only, not completed work:## Verify plan(D4) requires clean repository leak scans and per-post leak review before any comment or description is posted.## Verify plan(D5) requires every commit to be signed.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why. — Planning coverage only, not completed work:## Verify plan(D6) requires matching documentation orNo doc impactwith the reason.provenance:agent-assistedlabel. — Planning coverage only, not completed work:## Verify plan(D7) requiresAssisted-bytrailers on every commit and theprovenance:agent-assistedlabel on the pull request.## Sizebounds the work to oneMpull request and## Verify plan(D8) requires staying within pull request size limits.## Scope and non-goalsdesignates fallback retirement as separateD9work and## Verify plan(D9) requires filing follow-up and deferred-finding issues with aProblemsection and numbered acceptance criteria linked inRelated.Status:comment names the merge commit. — Planning coverage only, not completed work:## Verify plan(D10) requires closing the issue via a merge closing reference, project board stateDone, and a finalStatus:comment naming the merge commit.Round: 1 of 3
tbhb-agent commentedon Oct 31, 2026
Status: build attempt returned without a patch, 2026-10-31.
Done: a build of this issue stopped at the 800-line cap. The new Go files and wrapper measure 815 code lines (scc 4.1.0), with acceptance coverage incomplete (AC1 to AC12 only partly covered), and the change edits the existing shell file tools/mise-bootstrap, which the shell allowlist checks as a whole file.
Next: the issue needs a split into smaller pull requests or a redesign that avoids editing the existing shell script. It is not a retry.
Blocked on: a refinement decision by the issue's owner.