Doctor Finding IDs

September 12, 2026 ยท View on GitHub

basectl doctor emits stable finding identifiers in both text and JSON output. Automation, runbooks, and suppression policies should match on id instead of human-readable messages. Findings that intentionally emit multiple instances of the same rule should match on the tuple of id and name.

Finding IDs are never reused after they ship. A finding may change its message, fix text, or severity over time, but its ID keeps the same meaning. Every doctor finding implementation must provide an explicit ID; placeholder IDs such as BASE-P000 are invalid because they cannot support automation or suppression policies.

Principles

Doctor findings should be specific, actionable, and non-alarming. Text output is for humans who need a safe next step; JSON output is for automation that needs stable IDs, statuses, names, messages, and fix guidance.

Text and JSON doctor findings are primary command output and are written to stdout. Usage and validation errors, including unsupported --format values, are diagnostics and must be written to stderr so scripts can safely parse machine-readable stdout.

basectl doctor should not mutate local state. A future fix path must be explicit, reviewable, and paired with dry-run behavior before Base offers it as part of the doctor workflow.

Local Explanations

basectl doctor explain <finding-id> prints local, deterministic guidance for selected high-frequency finding IDs:

basectl doctor explain BASE-P050
basectl doctor explain BASE-D001 --format json

The explanation catalog is provider-neutral and local-only. It includes a summary, why the finding matters, likely causes, concrete fix steps, related commands, and documentation links. Unknown IDs fail clearly and point back to this reference. The first catalog slice intentionally covers frequent Base runtime and project-readiness findings rather than every documented ID.

Future AI-assisted doctor features should build on this local catalog as the ground truth. Optional provider amplification may add richer phrasing or context later, but it must not replace the local explanation data, require a provider for deterministic guidance, or change the stable finding-ID contract.

Diagnostic JSON Contract

Base diagnostic JSON uses schema_version: 1 for object-shaped payloads. This contract was introduced before Base 1.0 and intentionally replaces the earlier experimental check JSON shape that used per-item ok booleans.

Every diagnostic item emitted by basectl check --format json and basectl doctor --format json has the same fields:

FieldMeaning
idStable finding ID, such as BASE-D001 or BASE-P050
statusOne of ok, warn, or error
nameShort machine-readable finding subject
messageHuman-readable diagnostic detail
fixSuggested remediation, or an empty string when no fix is needed
detailsOptional structured context for findings that can report machine-readable detail

Check commands that return an object include an aggregate status and a checks array of diagnostic items:

{
  "schema_version": 1,
  "status": "ok",
  "checks": []
}

basectl check <project> --format json and basectl check --profile <list> --format json embed project/profile layer results as nested diagnostic payload objects under project_checks and profile_checks. Workspace check and doctor JSON keep their workspace/project object shape and use the same diagnostic item fields inside each project's checks array.

When a project check cannot persist its optional latest-check record, the check payload may also include a top-level record object with status: "warn", a stable message, a suggested fix, and the attempted path. This warning does not change the aggregate diagnostic status or exit code; workspace status explicitly treats the missing record as unavailable state.

Doctor commands use the same diagnostic item fields. The top-level basectl doctor --format json wrapper includes schema_version and aggregate status, and keeps doctor-specific arrays named findings, profile_findings, and project_findings.

Namespaces

PrefixScope
BASE-DBase runtime and developer-prerequisite findings
BASE-PProject manifest, artifact, IDE, and command-delegation findings
BASE-HProject health declaration findings
BASE-WWorkspace manifest and multi-repository findings

Base Runtime Findings

IDFinding
BASE-D001Homebrew availability and PATH refresh
BASE-D002Xcode Command Line Tools availability and Homebrew freshness
BASE-D003Base Python runtime availability
BASE-D004Base virtual environment integrity
BASE-D005Base PyYAML package availability
BASE-D006Base click package availability
BASE-D007Base reusable Bash library source readiness
BASE-D008Bash runtime version support
BASE-D009Python venv module support
BASE-D010Git CLI availability
BASE-D011GitHub CLI availability on Ubuntu/Debian
BASE-D012BATS availability on Ubuntu/Debian
BASE-D013ShellCheck availability on Ubuntu/Debian
BASE-D014jq availability on Ubuntu/Debian
BASE-D015Go availability on Ubuntu/Debian source checkouts
BASE-D101Unsupported prerequisite profile manager
BASE-D102Unsupported prerequisite profile version
BASE-D103Homebrew unavailable for prerequisite profile checks
BASE-D104Prerequisite profile Homebrew package presence and freshness
BASE-D105GitHub CLI executable availability for authentication checks
BASE-D106GitHub CLI authentication status
BASE-D107AI developer tool availability and version status
BASE-D108Multipass availability and version status for the linux-lab profile

Project Findings

IDFinding
BASE-P001Empty project manifest artifact set
BASE-P002Project manifest validity
BASE-P010Brewfile path validity
BASE-P011Brewfile platform or Homebrew availability
BASE-P012Brewfile dependency status
BASE-P020mise config path validity
BASE-P021mise CLI availability and setup bootstrap guidance
BASE-P022mise trust and missing-tool status
BASE-P030Unsupported artifact manager
BASE-P031Unsupported Homebrew artifact version
BASE-P032Homebrew unavailable for artifact checks
BASE-P033Homebrew artifact package presence and freshness
BASE-P034Platform system-package artifact presence
BASE-P040Python package artifact status in the project virtual environment
BASE-P050Project virtual environment readiness
BASE-P060Project demo declaration
BASE-P061Project demo script path and executable status
BASE-P070Build target working directory status
BASE-P080Project Git repository status
BASE-P081Project Git origin remote status
BASE-P082GitHub CLI authentication status for a GitHub-hosted project remote
BASE-P083Opt-in project Git origin remote reachability status
BASE-P100User config disables all IDE setup and checks
BASE-P101User config disables setup and checks for one IDE
BASE-P102User IDE setting conflicts with a project manifest setting
BASE-P110IDE CLI unavailable for extension checks
BASE-P111IDE extension listing failure
BASE-P112IDE extension install status
BASE-P120IDE settings file validity
BASE-P121IDE setting presence
BASE-P122IDE setting expected-value match
BASE-P123IDE setting value differs from the Base manifest
BASE-P130Homebrew unavailable for IDE app checks
BASE-P131IDE app install status
BASE-P132IDE CLI PATH status
BASE-P140pyproject.toml presence and metadata summary
BASE-P141pyproject.toml readability
BASE-P142pyproject.toml dependency metadata observed without an explicit supported Python manager
BASE-P143Unsupported [tool.base] configuration
BASE-P150uv CLI availability for uv-managed projects or uv command runners
BASE-P151uv-managed project pyproject.toml presence
BASE-P152uv-managed project uv.lock presence
BASE-P153Stale Base-managed project virtual environment ignored by a uv-managed project
BASE-P154uv-managed project virtual environment readiness
BASE-P155uv-managed project virtual environment synchronization
BASE-P160Manifest command executable availability
BASE-P161Manifest command project script path readiness
BASE-P170Project Python version requirement support window
BASE-P171Selected project Python interpreter availability
BASE-P172Actual inspectable project Python runtime: environment manager, virtualenv path, interpreter path, and Python minor version
BASE-P180Declared project test requirements file
BASE-P181Project test requirements environment

BASE-P050 is the stable project virtual-environment readiness finding. The Bash setup/check path reports detailed venv health messages when a project venv is missing, incomplete, or has a broken Python executable. Workspace-level project discovery verifies that the expected project venv Python executable can start. The finding should be treated as the project-venv readiness contract, not as a guarantee that every project dependency import succeeds.

BASE-P140 through BASE-P143 are read-only pyproject.toml diagnostics. Base only inspects the pyproject.toml file beside the active base_manifest.yaml. These findings do not make pyproject.toml a Base configuration source and do not cause Base to install Python dependencies. BASE-P142 applies when dependency metadata is present without an explicit supported Python manager; projects declaring python.manager: uv use the dedicated uv diagnostics instead. Warnings in this range should guide users toward a valid Python project file without failing the Base manifest check by themselves.

BASE-P150 through BASE-P155 are uv support diagnostics. They are warnings when uv tooling or expected uv project files are missing, because check/doctor should explain readiness without mutating the project. When the project has a usable pyproject.toml, uv.lock, and .venv, BASE-P155 runs uv's offline sync --check probe and reports an error when the environment is not synchronized. When uv provides structured changes, the finding message and optional details.package_changes identify missing, unexpected, or version-mismatched packages. Command invocation still fails hard when a command declares runner: uv and the uv executable is unavailable. On Ubuntu/Debian, BASE-P150 recovery should point users to basectl setup <project> --dry-run followed by --yes when the manifest has explicitly opted into uv. For the full uv manifest contract, migration paths, and runner configuration, see Python Manifest.

BASE-P160 and BASE-P161 are advisory manifest command-lint diagnostics for test.command, commands.*.command, and build.targets.*.command. They look for obvious missing executables or missing/non-executable project script paths without executing command strings or treating the manifest as safe. They should not reject complex shell syntax or replace human review of unfamiliar repositories. For uv-backed command execution and runner: uv examples, see Python Manifest - Command Runners.

BASE-P170 and BASE-P171 are project Python runtime diagnostics for python.requires_python. BASE-P170 validates the request against Base's supported Python 3.10 through 3.13 window. BASE-P171 reports whether the selected supported interpreter is available locally. Setup uses the selected interpreter when it creates a Base-managed project virtual environment and requires --recreate-venv before replacing an existing venv with a different Python minor.

BASE-P172 reports the actual inspectable project Python runtime: environment manager, virtualenv path, interpreter path, and Python minor version. Missing or broken virtual environments continue to use their existing readiness findings instead of emitting runtime version data.

BASE-P080 through BASE-P083 are read-only project Git remote diagnostics. They report whether the project directory is inside a Git repository, whether origin is configured and parseable, and whether GitHub CLI authentication is ready when origin points at GitHub. Default project check and doctor do not probe network remote reachability. The GitHub CLI authentication diagnostic is bounded so a slow gh auth status call reports a warning instead of blocking the check indefinitely.

BASE-P083 appears only when the user explicitly opts in with --remote-network. It delegates reachability to Git with a bounded git ls-remote call, reports sanitized provider and transport details, and does not print credential-bearing remote URLs.

Workspace Findings

IDFinding
BASE-W010Expected workspace repository presence
BASE-W011Discovered Base-managed project outside the workspace manifest
BASE-W012Present expected repository without a Base project manifest
BASE-W013Git repository present under the workspace root but absent from the workspace manifest

BASE-W010 is emitted for every expected repository when workspace check or doctor runs with --manifest <path>. It is error when a required repository is missing, warn when an optional repository is missing, and ok when the repository is present.

BASE-W011 reports local Base-managed projects that were discovered under the workspace root but are not listed in the supplied workspace manifest.

BASE-W012 reports expected repositories that are present locally but do not contain base_manifest.yaml. This is an ok finding because workspace manifests do not require every repository to be Base-managed.

BASE-W013 reports each direct-child Git repository that is present under the workspace root but is not listed in the workspace manifest. It is a warn finding and does not fail workspace check or doctor. Add a repos[] name entry to inventory the repository, even when it has no Base manifest (for example, repos: [{name: scratch-tools}]), or move it outside the workspace root. The schema has no ignore or unmanaged flag. Declaring a non-Base repository is supported and produces the non-failing BASE-W012 finding.

Health Findings

IDFinding
BASE-H001Required environment variable presence; each variable is keyed by (id, name).
BASE-H002Required TCP port listening/free state

For BASE-H001, id is always BASE-H001 and name is the environment variable name from health.required_env. A suppression targeting a specific missing-variable finding would match values such as id: BASE-H001 and name: DATABASE_URL.