Consolidate tool catalog and pinned delivery contracts before adding uv delivery
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 30/100
- issue の種類
- リファクタリング
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 領域
- build-system, tooling
調査の方向性
Start with the linked tooling-status-quo inventory, then inspect tools/lockfiles/python_tools.bzl and tools/internal/devcontainer/install.py to trace catalog loading and delivery registrations. Review tools/run-tool and the related feature version declarations to understand the current execution and pinning behavior. Done means the acceptance criteria are met, including focused regression coverage and documentation that matches the resulting catalog and delivery contracts.
索引モデルが issue の本文から書いたものです。
説明
What problem are we trying to solve?
SCORE provides development tools such as Ruff and pre-commit. Developers can get them through the Dev Container (our prepared development environment) or Bazel. We want developers and CI to use the versions chosen for the same SCORE release.
Today, the information needed to choose and install those tools is spread across several files and scripts. Adding a tool or changing its version can require edits in several places. It is easy to miss one.
#189 would let people get SCORE's Python tools directly through uv/uvx, without a container or Bazel. For example, a project should be able to select a SCORE release and receive its Ruff version, rather than copying that version into its own configuration. Before adding this route, we should make sure it uses the same version choices as the others.
What should become simpler?
- For developers: choose the SCORE release, get its tools and run them normally. Starting an installed tool should not require Bazel or another tool manager to start first.
- For maintainers: choose each tool's version in one place. Use that information to prepare the container, keep the supported Bazel tools available and provide the Python tools through uv/uvx.
- When dropping a tool: stop offering it in new releases. We do not need to uninstall old copies from developers' machines or change previously published releases.
We will improve and consolidate our existing scripts to do this.
Decision
We will consolidate and develop our own tool provisioning. We will not introduce mise, Aqua or Nix as an additional tool manager for this scope. Existing uv, Bazel and OS package managers keep their roles.
Where a design choice can follow patterns from Aqua or mise without additional implementation or maintenance effort, we prefer that direction. Examples are clear declarative tool definitions, explicit version/download information and a clean separation between definitions and installation. This preference guides equally simple choices; it does not create extra format, adapter or feature requirements. SCORE's actual needs determine the scope.
The own implementation is the working target. The other implementations remain evaluation evidence; we will not maintain four production alternatives. The remaining work is to finish validation and land the chosen implementation in reviewable changes.
Why did we consider another tool manager?
We currently maintain code and instructions for downloading, checking and unpacking tools. External projects already maintain installation instructions for many of these tools. Reusing that work could reduce ours.
But we would also have to learn, configure and connect the new manager to SCORE. Some tools would still need our own installation instructions. The question is whether it saves more maintenance than it adds. Supporting uv/uvx alone does not require another manager.
Which options did we compare?
| Option | Basic idea | Main trade-off |
|---|---|---|
| 1. mise | Use its existing installers for many tools, including Python tools. | Less installation code of our own; we maintain the connection to SCORE and handle gaps. |
| 2. Aqua + uv | Let Aqua install other tools and uv install Python tools. | Keep that split explicit; maintain the SCORE connection and installation instructions missing from Aqua. |
| 3. Nix | Provide tools together with the libraries and other programs they need to run. | Nix handles more of the complete setup, but introduces more to learn and operate. |
| 4. Our own installer | Organize and improve the scripts we already have; continue using uv for Python tools. | Fewer new concepts; downloading and installation remain our responsibility. |
All four were evaluated against the same user-facing behavior. The selected option improves the current setup and consolidates its scattered version choices.
Complexity at a glance
We need to distinguish how complicated the finished solution is to maintain from how much work it takes to get there from today's setup. Today's code is unfamiliar to most contributors too. Keeping it does not make it easy to learn.
Every option still needs version choices, tool selections, container setup, supported Bazel commands, Python release metadata and checks that these agree. That is the shared base complexity. Each option keeps, replaces or adds different parts around it: its variant-specific ongoing complexity. Neither is the same as the one-time work of migrating.
Ongoing maintenance after the migration: 🟩 5/5 = very little complexity · 🟦 4/5 = little · 🟨 3/5 = moderate · 🟧 2/5 = substantial · 🟥 1/5 = broad operating machinery. These are review judgments about each duty, not measured working hours or a total score.
| Everyday maintenance question | Our own installer | mise | Aqua + uv | Nix |
|---|---|---|---|---|
| How little download/unpacking code do we maintain ourselves? | 🟨 3/5 | 🟦 4/5 | 🟦 4/5 | 🟦 4/5 |
| How easy is changing one tool's version without changing the others? | 🟦 4/5 | 🟦 4/5 | 🟦 4/5 | 🟧 2/5 |
| How few tool-specific installation exceptions do we maintain for the tools tested? | 🟦 4/5 | 🟦 4/5 | 🟨 3/5 | 🟨 3/5 |
| How easy is keeping Bazel's tool downloads in sync with the installer? | 🟩 5/5 | 🟨 3/5 | 🟨 3/5 | 🟧 2/5 |
| How simple is the machinery we operate to deliver tools to containers and developers? | 🟦 4/5 | 🟨 3/5 | 🟨 3/5 | 🟥 1/5 |
The separate migration question: our own variant consolidates existing code; mise/Aqua replace that installer and connect another configuration format to the existing consumers; Nix additionally introduces closure/store delivery. All four need cleanup, caller changes and tests. A smaller migration is not proof of the simplest finished system.
→ Rating reasons, retained complexity and migration changes. No familiarity bonus is given to existing code, and the ratings are not added together.
Why this choice?
The own implementation now passes the core release/update, uv/uvx, repository setup, fresh amd64 build and prepared ARM64 tool checks. It uses the same portable download definitions as Bazel and one shared installation engine across host and container.
External managers can reduce installation-recipe work, but their integration, additional configuration and Bazel exports do not provide enough demonstrated benefit for our current needs. Nix solves a broader runtime-management problem than we have chosen to take on here.
This choice still leaves us responsible for our installer, its prepared state and artifact/layout upkeep. Existing code must be understandable to contributors who do not know it today. The reason is the resulting ownership and structure, not familiarity or a sum of ratings.
What happens next?
Use the own implementation as the target. Complete the remaining ARM64 container and real macOS ARM checks, decide how releases are distributed, simplify the maintained code/documentation and split it into small reviewable changes.
Current status (2026-11-02): the own variant now has the core release, container and prepared-ARM checks too. Its full ARM64 image remains unproven after a timeout and a download failure. The own, Aqua and mise source snapshots and checked-in comparison evidence are archived upstream below; caches, images and additional runtime payloads remain local. The architecture choice is recorded here; the implementation has not been merged upstream. The shared version choices must be in place before rolling out #189; we can develop and test its uv/uvx support alongside that work.
Frozen implementation references
The implementation and comparison snapshots are now preserved upstream, not just in local worktrees. Each branch has a REFERENCE-190.md entry point. The fixed commit links identify the archived state even if a branch is accidentally moved later.
| Reference | Branch | Fixed snapshot and entry point |
|---|---|---|
| Own provisioning — selected target | reference/190-own-provisioning |
cd7196e0bf86 |
| Aqua — comparison alternative | reference/190-aqua |
4deccd8dafe1 |
| mise — comparison alternative | reference/190-mise |
551cb7f4f5da |
| Decision, comparison and evidence | reference/190-decision-and-evidence |
71b26eb3bb13 |
How the next PRs use these: start from current main (or an explicitly dependent PR), extract one coherent behavior from the own-provisioning reference, adapt it to landed changes and validate that PR. Cite the reference commit and the extracted part. Aqua/mise provide comparison evidence; they are not additional production tracks. Do not merge the reference branches wholesale, rebase or force-push them during the migration. Create a separately named successor if a revised reference becomes necessary.
First extraction: #196 shares catalog reading at tools/internal/catalog.py while leaving definitions in place. The references retain historical experimental names such as tools/score_tools/; subsequent PRs follow the structure landed upstream. The old tooling-pr-sequence.md is a historical breakdown, not a commitment to exact PR count or paths.
The decision-and-evidence branch holds the latest cross-variant documentation; variant-local copies can be older. Git includes source and checked-in evidence, not all local caches, images or runtime payloads. Archiving does not establish a public package release, full ARM64 image success or actual macOS ARM validation.
Details and evidence
The summaries above explain the decision; expand these sections for the requirements, implementation reasoning and evidence.
1. Agreed requirements and target architecture
Author versions once in the own provisioner's portable artifact and Python definitions. Derive or check public delivery metadata from those owners. Provision tools before use, then execute their prepared commands directly.
Several configuration files in one understandable directory are acceptable. We do not require a universal manifest or identical formats for native tools and Python dependencies.
| Boundary | Required behavior |
|---|---|
| Version ownership | One authoritative version decision per tool. Generated locks, inventory rows and dependency metadata are outputs, not additional authored pins. |
| Dependency scope | Describe deliberately selected tools and their direct dependencies. Resolvers may own transitive dependency locks; we do not hand-maintain a complete transitive inventory. |
| Consistency | Supported delivery paths select the same declared tool version. They need not use byte-identical binaries, interpreters or transitive environments. Runtime compatibility still has to work. |
| Container | Keep the published Ubuntu-based Dev Container and feature model. Install tools during setup/build; make them usable by the non-root user and IDE. Trust the prepared container's pins. |
| Host: convenience | May use an existing command from PATH. |
| Host: strict | Select the provisioned pinned command. Preserve the existing applicable Bazel fallback for missing prepared tools. Preserve cwd, arguments and exit status. |
| Prepared execution | Provide a direct executable path. No mandatory manager invocation, synchronization, dependency resolution, Bazel analysis or network check on every ordinary tool call. Explicit uv/uvx resolution remains normal uv/uvx behavior. |
| Python consumers (#189) | A consumer selects a SCORE release and optional tool extras through ordinary Python dependency metadata. uv/uvx resolves the tool pin from that metadata; the consumer does not repeat it. No hidden second environment or mandatory SCORE launcher. |
| Bazel compatibility | Keep supported public labels for simple, self-contained CLI delivery. Do not invent complex Bazel packaging for tools requiring substantial runtime assembly; those may use the other paths. Build-toolchain integration is a separate concern. |
| Selections | Distinguish the published tool selection from the smaller repository build/test selection. Generate or check their registrations and inventory against the owners. |
| Platforms | Linux amd64 and arm64, with explicit per-tool exceptions. Support macOS ARM hosts as far as practical, backed by actual validation before claiming support. |
| Release identity | Bind the related image, tool definitions and Python metadata to a release. Reproducible consumers need immutable references. Public package name and artifact hosting remain to be chosen. |
This is the shared architecture. The provisioning choice determines how the producer realizes and maintains it; it should not leak into every consumer invocation.
Complexity assessment: implementation structure versus operating cost
Shared complexity, finished-system complexity and migration delta
The existing implementation is not a free or universally understood baseline. Most contributors must learn it before changing it. The same applies to its custom scripts, artifact layout assumptions and version/update behavior, not only to a new manager.
We therefore ask two separate questions:
- Finished-system complexity: after cleanup, what must someone understand, maintain and operate? Count existing code retained by the own variant as fully as new manager integration.
- Migration delta: what must we add, change and remove relative to today's setup? Reuse helps here, but this one-time advantage is not a permanent maintenance score.
Common duties are version ownership, selections, Ubuntu/providers, public compatibility, release binding, normal Python dependency metadata and drift checks. Their implementations can change; they cannot simply be declared absent because a manager is used. Conversely, a manager can remove an existing duty by genuinely replacing its mechanism.
Final responsibilities and concrete evidence
| Duty after migration | Own installer | mise | Aqua + uv | Nix |
|---|---|---|---|---|
| Download/unpacking engine | One generic shared custom engine, including checksums, file/archive layouts and failure handling | Backend engine; SCORE bootstrap/exposure glue remains | Registry engine plus uv; SCORE bootstrap/exposure glue remains | Package/store machinery; custom derivations/integration remain |
| Tool-specific installation exceptions in this inventory | Generic file/member/tree handling, shared-archive grouping; per-platform artifact data remains | Generic GitHub backend covers Starpls/APM; backend and portable-layout mappings remain | Local Starpls/APM recipes and APM adjacent-runtime handling | Existing Starpls/APM packages; local OpenCode derivation/runtime handling |
| One isolated Ruff version change | One exact owner edit plus normal refresh/check | One exact owner edit plus normal lock/export/check | One exact owner edit plus normal checksum/export/check | Find/select a suitable separately locked package input to keep unrelated pins unchanged |
| Installer/Bazel alignment | Same portable owner feeds both directly | Maintained backend-lock-to-portable adapter | Maintained registry/checksum-to-portable adapter | Separately obtain portable upstream assets; package/store hashes do not provide them |
| Native delivery state | Prepared trees, completion markers, locking, uv environments and additive direct links | Manager install trees/bootstrap and SCORE command exposure | Manager native trees, uv environments/bootstrap and SCORE selected-output handling | Package realization, store closures, producer/target transfer and activation |
| Python consumer release | SCORE-owned ordinary dependency metadata and release binding | Same duty | Same duty | Same duty; Python consumers need no Nix/closure |
Basis and corrections for the 1–5 ratings
Higher numbers mean less SCORE complexity for that row. They are ordinal assessments, not measurements of hours, learning speed or lifetime defect rates. The two best scores differ: 5 directly reuses a shared mechanism with almost no extra layer for the duty; 4 still needs setup/integration. The middle score means bounded custom logic; 2 means additional representations/input coordination; 1 means broad operating machinery. Colors are only visual aids.
- Download/unpacking: 3 / 4 / 4 / 4. The own option retains the engine, which contributors must understand. Managers delegate it; they still need setup and integration. Existing code receives no discount for being old.
- Version change: 4 / 4 / 4 / 2. The executed own/mise/Aqua updates were one intended version decision followed by normal refresh/check operations. The previous own score of 3 was insufficiently justified and is corrected. All retain portable archive-layout assumptions. The tested Nix isolated change required finding/selecting an independent package input; that discovery was supplied, not automated.
- Current inventory exceptions: 4 / 4 / 3 / 3. Own's generic extraction/adjacent-command handling covers the tested inputs without additional per-tool installer code; its artifact descriptions are still maintained. mise's backend coverage avoids the local registry recipes needed by Aqua. Nix has a custom OpenCode derivation. This is a narrow inventory observation, not evidence about every future tool or registry.
- Bazel alignment: 5 / 3 / 3 / 2. Own directly reuses the existing portable owner. mise/Aqua maintain translation from manager records. Nix needs portable information separately from its package/store metadata. All still maintain public selection/label policy.
- Delivery machinery: 4 / 3 / 3 / 1. Own has prepared-state/link machinery, not zero infrastructure. mise/Aqua also operate manager preparation/bootstrap and expose selected output. The current Nix implementation realizes/transfers/activates closures beside Ubuntu providers. This row judges delivery state/operations, not contributor familiarity or one-time migration cost. Nix's runtime composition is a benefit of its broader model.
The old “new knowledge” row is removed: it mixed migration with ongoing complexity and favored the own solution because it already existed. We have not measured contributor onboarding for any option. Learning existing custom code and learning an external model both count.
Migration delta: additions and deletions
| Option | What changes from today's setup? | What disappears or stays? |
|---|---|---|
| Own installer | Share one provisioner across host/container; add prepared trees/links and ordinary Python release output; derive/check registrations | Remove duplicate container extraction/discovery. Keep portable owners and maintain their shared install engine |
| mise | Introduce manager owners/bootstrap/provisioning and portable/Python exports; move callers and update automation | Remove old native/Python install engine; retain Ubuntu providers and SCORE selection/release/compatibility glue |
| Aqua + uv | Introduce native registry owners/bootstrap, Python group integration, missing recipes and portable/Python exports; move callers/automation | Remove old native/Python install engine; retain Ubuntu providers and SCORE selection/release/compatibility glue |
| Nix | Introduce package inputs/derivations and closure production/transfer/activation plus portable/Python exports; move callers/automation | Replace old installer/runtime composition with Nix mechanisms; retain Ubuntu providers and SCORE selection/release/compatibility glue |
These changes were implemented locally, not estimated from manager marketing. They do not establish person-hours. Automatic host uninstall/repair/rollback is out of scope; optional prototype mechanisms do not create adoption gates.
Recorded decision and implementation principle
We choose consolidated own provisioning. Its direct reuse of Bazel artifact definitions and one shared installer fit the confirmed scope better than the demonstrated extra integration of another manager. This does not make its custom engine/state free to maintain or imply that it wins every dimension.
Where equally simple choices are available, prefer patterns and conventions similar to Aqua/mise. Clear declarative definitions and separation of definitions from installation are useful examples. Extra schemas, adapters or feature work solely to resemble those tools are outside that preference.
Use the own implementation as the target; retain other variants as historical evaluation, not ongoing production alternatives. The main remaining validation boundaries are full ARM64 image, actual macOS use and public release distribution. Peer Codespell selection/initial pins differ from the own baseline; the comparison covers common contracts.
2. Option 4: what is already demonstrated, and what remains ours
Option 4 is now a maintained local implementation, not only the earlier small control. It uses the existing native artifact files and literal Python catalog as owners. The native definition also feeds the ordinary Ruff dependency extra; uv/uvx supplies Ruff without a SCORE launcher.
Implemented boundaries:
- One shared downloader/checksum/file/archive installer used by both container and host. The old duplicate container extraction path was removed; APT/npm/provider setup remains.
- Commands from the same archive are prepared together so uvx can find adjacent uv. Python environments use ordinary uv and retain their interpreter dependency; they are not relocatable Nix-like closures.
- Content-keyed prepared trees, completion markers, a prefix lock and direct links. Updates preserve unrelated files and reject user-replaced command conflicts. Existing installations are not automatically adopted; migration uses a fresh prefix.
- Generated/checkable inventory and native Bazel registrations. Removing an owner and its selections stops offering it in new outputs. No automatic host uninstall or ownership database.
- Ordinary release build/check with explicit identity/version, owner hashes, wheel binding and exact generated dependencies. Stale owners/metadata, old-release/new-owner mismatch and changed wheel bytes are rejected.
Executed release proof: A is facade 0.8.0 / Ruff 0.11.13; B is 0.8.1 / Ruff 0.14.6. The same uv project changes only its facade release; real uv and uvx resolve Ruff. The same native prefix updates Ruff while preserving Buildifier and a user file. The public //tools:ruff executes B, preserves a relative spaced filename and returns the expected lint failure. Production owner pins were not changed.
The installer retains archive/platform upkeep. Incomplete Python preparation requires a fresh data directory; prepared trees are trusted rather than rehashed on every call. No whole-profile transaction, rollback or garbage collection is promised. These limits should be judged against the agreed scope, not expanded into requirements merely because another prototype implements them.
The earlier ShellCheck update/control and local mirror recovery are historical supporting experiments. The current report additionally includes actual complete amd64-image and ARM64 prepared-tool execution on original artifact URLs.
3. Manager-specific recipes, removal and recovery
All three manager implementations remove the old native archive installation and Python tool installation paths from tools/internal/devcontainer/install.py, including its install and install-python subcommands. Production code no longer depends on experimental paths.
The remaining module is not metadata-only: it still performs selected APT/npm provider setup and supplies selection/metadata queries and verification. Ubuntu/APT lifecycle, Java, CodeQL and specialized features remain intentional responsibilities.
Every candidate still needs:
- Public tool, command and Python-extra identities; published/repository selections and any alias policy.
- Generated or checked inventory, registrations and drift detection.
- Portable upstream URL/hash/archive-layout metadata for existing simple Bazel targets.
- Release binding and ordinary Python dependency-package generation/checking.
- Bootstrap, platform exceptions and integration with container setup, repository post-create and updates.
Historical extra functionality, not a requirement: mise and Aqua additionally retain SCORE-owned prefix reconciliation. This protects other selections and user-owned files when commands are removed. Nix supplies the profile membership replacement mechanism; SCORE still chooses the profile contents and maintains compatibility exports. These are different responsibility boundaries. This cleanup functionality must not count as a mandatory feature or penalize an option that does not implement it. Existing prototype code can be simplified accordingly.
The comparison also led to concrete fixes: mise stale-lock rejection now survives optimized Python, its uv backend resolves the actual prepared uv executable, and Aqua promotes only selected commands so a transitive gh executable does not shadow the existing system command. Nix gained explicit producer/target handling and removed an obsolete standalone comparison Dockerfile. Those completed fixes should not be counted as work recurring on every version update.
Inventory examples
Starpls at the selected release was covered by mise's generic GitHub backend and the locked Nixpkgs package, but required a local Aqua registry recipe. APM required preserving its adjacent runtime/data tree; Aqua uses a local recipe for that layout. The selected OpenCode needed a custom Nix derivation/runtime handling. These are observations about this inventory, not claims about universal registry coverage.
The command-removal and recovery investigations explored additional behavior. Neither automatic uninstall of existing host tools nor installed-tree repair is a prerequisite for offering the tools.
Historical bounded recovery comparison
A separate single-tool Linux amd64 probe distinguishes optional recovery capabilities from the core requirements:
| Operation | mise | Aqua + uv | Nix | Earlier own-installer control |
|---|---|---|---|---|
| Reinstall the deleted Starpls package offline | Passed with separately prepared checked-download lock/cache; the original metadata-supplied-checksum lock was insufficient | Normal retained state did not recover the removed package; attempted upstream access | Passed after explicit closure export to a local file cache | Normal state did not recover it; an explicit local artifact mirror worked |
| Detect changed installed bytes while version output still matches | Normal installation did not detect them | Normal installation did not detect them | Native store verification detected them | Version probe did not detect them |
| Repair changed bytes without upstream | Forced install from the prepared cached archive worked | Normal reinstall did not restore them in this probe | Native repair from the prepared local cache worked | Explicit checksum-verified local mirror restored them |
These are historical bounded experiments, not current end-to-end recovery guarantees for every tool or tests of the later maintained own implementation. All options still need a deliberate cache/mirror retention and distribution policy. Nix's installed-tree verification is a distinct benefit; it is not required on every tool call. The trusted-container execution contract remains unchanged.
The following deletion observations concern optional cleanup, not removing a tool from our offering. Earlier fixed-directory deletion probes exposed stale commands in mise/Aqua copied exports. Later implementations added SCORE prefix reconciliation; those early failures must not be presented as their final status. Nix already supplies native profile membership replacement.
4. Actual version authoring, release and user-update workflow
All four candidates completed the following local sequence through maintained tooling:
- Produce release A from its current owners.
- Change the Ruff version in an isolated source copy; demonstrate rejection of stale generated data.
- Use the normal refresh/export/inventory operations and produce owner-bound release B.
- Reject the A artifact against the B owners.
- Update the same independent uv project from A to B by changing only its SCORE dependency release. Resolve and run Ruff through ordinary uv and uvx, with no consumer-authored Ruff pin.
- Update the same native prefix/profile, preserving an unrelated selected tool and a user-owned sentinel.
- Run the updated public
//tools:rufftarget, including a relative filename containing spaces and an expected nonzero lint exit.
The local facade releases were 0.8.0 and 0.8.1; B selected Ruff 0.14.6. The starting versions differed: own/mise 0.11.13, Aqua 0.11.12 and Nix 0.17.2. The Nix case was therefore a downgrade, not an upgrade. These were fixtures, not a chosen public package API. The target version and historical Nix input were already known; this was not arbitrary version discovery.
| Maintenance step | Own installer | mise | Aqua + uv | Nix |
|---|---|---|---|---|
| Author | Exact version in the portable artifact owner | Exact backend version | Exact registry tag | Select a separately locked package input |
| Refresh/check | Refresh URLs/hashes/archive members and generated inventory/registrations | Resolve lock and compatibility export/check | Resolve checksums and compatibility export/check | Lock/evaluate package selection and portable metadata/check |
| Ordinary Python release | Build/check wheel and owner-bound manifest | Same class of artifact | Same class of artifact plus fresh smoke consumer | Generate/check facade from release; ordinary wheel build. Native closure generation serves a separate delivery output |
| Same native installation | Update direct Ruff link; selected Buildifier/user file preserved | Install new Ruff; unrelated selected paths/hashes preserved | Recopy selected native commands and reinstall Python through caches; recorded unrelated output preserved | Replace profile entry; selected Buildifier/fixed-store user entry preserved |
Aqua's recopy/reinstall behavior is the current SCORE adapter's implementation, not an inherent Aqua limitation or a performance measurement. Nix's tested profile update also considers independently updatable foreign entries; preservation of every possible foreign flake entry was not established.
The native updates and ordinary uv consumers are separate outputs from the same authority. Installing the dependency facade is not the mechanism for installing a native manager profile.
5. Integration and platform results, including their limits
All four have substantial local implementations. None is a completed upstream production migration. Tests are bound to recorded source snapshots; the table does not assert identical inventories, initial versions or transitive environments.
| Boundary | mise / Aqua / Nix | Own installer | Important limit |
|---|---|---|---|
| Generic Node repository Dev Container | Passed | Passed | Real post-create, later non-root terminal, hooks, DinD and tools; source snapshots recorded |
| Fresh complete Linux amd64 image and existing feature tests | Passed at the recorded integration checkpoint | Passed on current implementation source; 79 unchanged assertions as vscode, original artifact URLs | Cache-only build output; no separately loaded/launched/published full image |
| ARM64 prepared tool execution | Passed under QEMU | Passed under QEMU, original URLs, 14 tools/16 exposed names | New prepared output on cached OS substrate; non-root/offline/read-only; not native ARM hardware |
| Direct/strict execution | Five common prepared cases per candidate passed | 16 paired calls and two behavior cases passed, plus three language-server exchanges | Prepared execution avoids manager/Bazel launch resolution; not a latency benchmark |
| Release/version/user update | Two bound releases, same uv project/native installation, uvx and actual updated Bazel Ruff passed | Same core sequence passed | Local fixtures/acquisition; no public hosted release |
| Full ARM64 image | No completed full-image proof in the comparison | Two incomplete attempts | First reached 16 assertions then hit 30-minute QEMU cap; retry failed downloading Bazel with a peer connection reset |
| Actual macOS ARM use | Not run | Not run | Static asset/package declarations are not execution evidence |
The retained ARM Bazel provider was separately exercised after the download failure: real Bazel 8.6.0 downloaded and ran under ARM QEMU, then ran again offline from its cache. That diagnoses the failure without claiming a complete image or suite pass.
The peers' ARM selection also included Codespell; it was not silently added to the own baseline. Their full integration checkpoint predates later targeted fixes, which received affected regressions rather than a full repeated image suite. Own's new amd64 gate is bound to its current implementation. These source boundaries remain explicit.
Parent review, separately from Copilot's report
The parent inspected the maintained provisioning, package build/check, catalog/registration code and relevant regressions. It independently:
- Reran 45 unit tests and generated inventory/registration checking: passed.
- Verified 99 archived file hashes/sizes and 48 current-source hashes, source snapshots and recorded integration bindings: passed.
- Inspected both actual wheel dependency records: A selects Ruff 0.11.13, B 0.14.6, with explicit facade identities/releases.
- Reran the prepared amd64 runtime as uid 1000, network disabled, read-only root/prefix: 16 direct/strict pairs, two behavior tests and three LSP exchanges passed, with no manager/Bazel interception.
This is focused independent review, not a second full build, an exhaustive audit or native hardware validation. Source and checked-in evidence snapshots are linked above; additional full logs/runtime payloads remain local. This issue does not imply published reproducibility. No hosted release, full offline acquisition or fully locked build toolchain is established.
6. Upstream acceptance checklist
The architecture decision is recorded below. The remaining boxes track landed and supported upstream behavior, not whether an equivalent local experiment passed. The foundation must land before downstream adoption of #189; consumer validation can proceed in parallel.
- Choose consolidated own provisioning; prefer Aqua/mise-like design patterns when they add no implementation or maintenance effort.
- Land the authoritative own-provisioning definitions and explicit delivery/platform boundaries.
- Land shared metadata/selection boundaries and drift checks; preserve existing public compatibility while removing competing authored pins.
- Integrate the own provisioning path into both the published image and repository setup, including non-root command/IDE exposure and the supported provisioning/update path. Removing a tool from the offering must remove it from generated metadata/targets and newly built images; automatic cleanup of existing developer installations is out of scope.
- Remove superseded/duplicate installation code and obsolete configuration, while retaining deliberate OS/feature providers. The own option keeps one shared native installer; it does not keep a duplicate container engine.
- Keep generated portable metadata for supported simple Bazel labels; explicitly exclude complex runtime packaging from that promise.
- Land release-bound ordinary Python dependency metadata and direct uv/uvx consumer checks for #189, without requiring the producer manager or a SCORE launcher.
- Select immutable release references, public package/artifact identity and hosting; automate owner refresh, export checks, release binding and publication.
- Run full amd64 integration gates on the final source, full ARM64 image/feature gates, and representative actual macOS ARM host checks; document per-tool exceptions.
- Replace prototype documentation with one supported operator/consumer guide and publish reviewable evidence with the implementation changes.
The implementation should be split from the own working local target into small coherent PRs. Each PR needs a usable boundary and preserved callers; this is not a plan to merge four parallel provisioners or defer cleanup until after #189.
7. Scope, related issues and architecture references
#189 motivates release-selected Python delivery; #155 covers broader version ownership/locking concerns; #115 concerns inventory. This issue defines a bounded foundation rather than requiring all of those issues to be solved.
Two clarifications supersede the earlier issue text: a prepared container is trusted to contain its pins, and direct uv/uvx dependency resolution is a first-class interface. A custom SCORE launcher may be optional, but cannot be the only path.
Not required by this issue:
- A universal configuration format or identical artifacts across every delivery path.
- Handwritten transitive dependency descriptions, APT snapshotting, full reproducible builds or a general SBOM project. Additional locking work remains separately discussable under #155.
- Packaging complex, runtime-heavy tools in Bazel merely to make every CLI reachable through it.
- Requiring a manager, container or custom wrapper for an ordinary Python consumer.
- Moving every OS package or specialized feature into the selected manager.
- Promising Windows or Intel macOS support.
- Centrally replacing consumer-owned hook revisions just because the pre-commit executable is pinned.
Historical baseline: tool inventory, version sources and delivery paths on docs/tooling-status-quo. It describes the starting implementation, not the completed local experiments summarized above.
Architecture context: Infrastructure DR-001, Infrastructure DR-003. Implementation must respect those decisions. Build integration and the delivery of interactive CLI tools should remain explicitly distinguished.
- 主要言語
- Shell
- スター
- 5
- フォーク
- 10
- 平均マージ
- 23時間 5分
- マージ済み PR(30日)
- 29
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
eclipse-score/devcontainer のほかの issue
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
eclipse-score/devcontainer#213 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
eclipse-score/devcontainer#189 ·
メンテナーはふだん 1 日以内に返信
-
bug: github releases without devcontainer releases対応中かも @vibhoraggarwal が 39 日前に担当しました。 オープンbug
難易度 3/5 1〜2日 初心者へのやさしさ 55/100
eclipse-score/devcontainer#162 ·
メンテナーはふだん 1 日以内に返信
-
Versioning messオープン
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
eclipse-score/devcontainer#155 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 52/100
eclipse-score/devcontainer#115 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
eclipse-score/devcontainer の issue をすべて見る
似ている issue
-
bug priority-low to-agent
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
IngvarConsulting/unica#2807 ·
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 73/100
-
DeclareMiningJob.wtxid_list should be specified to be in block order対応中かも このイシューにリンクされたプルリクエストがオープン中、またはマージ済みです。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 84/100
stratum-mining/sv2-spec#253 ·
-
area:linux source:reader type:content-error
難易度 1/5 1時間未満 初心者へのやさしさ 84/100
stephrobert/blog-roadmap#169 ·