Skip to content

Toolchain Profiles

NewMe505 edited this page Oct 12, 2026 · 1 revision

Toolchain Profiles

ADR 0009. The graph names what it needs; a profile says how for one stack.

The protocol

scio.toolchain.Toolchain covers, for one stack:

  • files: source suffixes, test-path rules, cache excludes (also the .git/info/exclude text), dependency files, a syntax check
  • commands: the test command and the meaning of its exit codes (passed, failed, no tests collected, runner broken), failure-only filtering of test output, path-selector semantics (path::name versus a filter expression), the lint command and how to read its exit codes, the script runner
  • parsers: the error signature (which failure is "the same" as last time) and the removed-public-symbol detector used by the high-impact flag
  • prompt phrases: how a model should name tests (selector_help) and filters (filter_help)

Profiles are frozen dataclasses; the protocol exposes read-only properties. Data lives in configs/profiles/<name>.yaml, parsers in scio/toolchain/<name>.py. Settings.toolchain (SCIO_TOOLCHAIN) picks the profile for a run; RunContext.toolchain carries it to every node and tool.

The python profile

Reproduces the pre-M6 behaviour byte for byte: python -m pytest -q --tb=short -p no:cacheprovider -rfE --no-header, ruff check --no-cache --select E9,F63,F7,F82,F821 --output-format concise, __pycache__, *.pyc, .pytest_cache, .ruff_cache, .mypy_cache, test paths under tests/ or named test_*, pytest exit codes 0, 5 and 2 to 4, Python tracebacks for signatures, def/class removals for the public-API flag. tests/unit/test_toolchain.py asserts the equality against the old literals copied into the test.

The boundary

test_no_stack_specific_command_outside_the_toolchain_package scans scio/ for command tokens ("pytest",, "ruff",, "npm", ...) and cache literals outside scio/toolchain/ and fails on any hit. The only Python facts left elsewhere are about SCIO's own runtime, not the target stack: the local sandbox rewrites argv python to its own interpreter and sets PYTHONUTF8=1 and PIP_NO_INDEX=1 offline.

Adding a stack (M10 does this for node-ts)

  1. configs/profiles/<name>.yaml: test argv and filter flag, exit codes, lint argv and exit codes, source suffixes, test dirs and prefix, cache excludes, dependency files, environment, script runner, the two prompt phrases.
  2. scio/toolchain/<name>.py: the failure-only filter, the error-signature parser, the removed-public-symbol detector, loaded from the YAML into a frozen dataclass that satisfies the protocol.
  3. Register it in scio/toolchain/__init__.py::get_toolchain.
  4. A scaffold for product mode in scio/product/scaffold.py (package, smoke test, CI running the profile's commands).
  5. Tests mirroring test_toolchain.py for the new profile; the regression suite stays at pass^5 = 1.00 for python.

Detection of an existing repository's stack is also M10; until then python is the only accepted value.

Clone this wiki locally