Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ jobs:
run: |
for tool in mbake; do uv tool install ${tool}; done
# ty is not installed here: `make typecheck` runs it via
# `uv tool run ty@$(TY_VERSION)`. TY_VERSION in the Makefile is the
# sole ty version declaration; update it there.
# `uv tool run --from ty==$(TY_VERSION) ty`. TY_VERSION in the
# Makefile is the sole ty version declaration; update it there.
# Pin ruff to the version the Makefile invokes (RUFF_VERSION) so the
# linter behaves identically across the uv tool, the synced
# virtualenv, and developer PATH; bump both sites together.
Expand Down
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ UV ?= $(shell command -v uv 2>/dev/null || printf '%s/.local/bin/uv' "$$HOME")
RUFF_VERSION ?= 0.15.12
RUFF ?= $(UV) tool run --from ruff==$(RUFF_VERSION) ruff
TYPOS_VERSION ?= 1.48.0
# Pin ty. `make typecheck` invokes it via `uv tool run ty@$(TY_VERSION)`, so
# TY_VERSION is the sole ty version declaration (CI runs `make typecheck` and
# installs no separate ty). Bump it here to move local and CI checks together.
TY_VERSION ?= 0.0.32
TY ?= $(UV) tool run ty@$(TY_VERSION)
# Pin ty so `make` and CI invoke the same typechecker release. ty is
# pre-1.0 and diagnostics shift between releases, so an unpinned install
# breaks the typecheck gate without any code change. Bump deliberately and
# fix new diagnostics in the same commit.
TY_VERSION ?= 0.0.56
TY ?= $(UV) tool run --from ty==$(TY_VERSION) ty
UV_ENV = UV_CACHE_DIR=.uv-cache UV_TOOL_DIR=.uv-tools
TOOLS = $(MDFORMAT_ALL) $(MDLINT) $(NIXIE) $(UV)
PY_SOURCES := $(sort $(shell find lading scripts -type f -name '*.py' -print))
Expand Down
9 changes: 9 additions & 0 deletions docs/contents.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ looking for project guidance, then follow the link that matches the task.
- [Roadmap](roadmap.md) - phased delivery plan and tracked implementation
tasks.

## Execution plans

Living delivery documents under `execplans/`, one per branch, recording the
plan, progress, decisions, and retrospective for a change.

- [Regenerate discovered nested lockfiles][execplan-regenerate-lockfiles] -
completed plan for discovery-driven lockfile regeneration in the bump command.

## Decision records

- [ADR-003: Use three-tier Python linting][adr-003] - accepted linting policy
Expand All @@ -38,3 +46,4 @@ looking for project guidance, then follow the link that matches the task.

[adr-003]: adr/003-three-tier-python-linting.md
[adr-004]: adr/004-in-process-metrics-backend.md
[execplan-regenerate-lockfiles]: execplans/regenerate-lockfiles.md
46 changes: 32 additions & 14 deletions docs/developers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ The relevant Makefile variables are:
- `RUFF` — the pinned Ruff command
(`uv tool run --from ruff==$(RUFF_VERSION) ruff`) that the `fmt`,
`check-fmt`, and `lint` targets invoke.
- `TY_VERSION` — pinned ty version used by `make typecheck`; defaults to
`0.0.56`. ty is pre-1.0 and diagnostics shift between releases, so bump it
deliberately and fix any new diagnostics in the same commit. CI does not
install ty separately; it runs whatever `TY_VERSION` pins.
- `TY` — the pinned ty command (`uv tool run --from ty==$(TY_VERSION) ty`)
that the `typecheck` target invokes.
- `PYLINT_PYTHON` — Python executable used by `uv tool run`; defaults to `pypy`.
- `PYLINT_TARGETS` — directories passed to Pylint; defaults to
`lading scripts tests`.
Expand Down Expand Up @@ -203,10 +209,15 @@ resolve from the crate directory, and leaves absolute URI targets unchanged.
Markdown links in fenced code blocks, indented code blocks, and inline code
spans are preserved verbatim.

`lading.commands.bump_lockfiles` owns Cargo lockfile discovery and regeneration
after manifest changes. It always includes the workspace root `Cargo.toml`,
validates configured nested manifests before invoking Cargo, and de-duplicates
resolved manifest paths.
`lading.commands.bump_lockfiles` owns bump-side manifest merging and Cargo
lockfile regeneration after manifest changes. `merge_discovered_manifests`
unions the configured `bump.lockfile_manifests` entries with manifests implied
by git-tracked `Cargo.lock` files (reusing
`lading.commands.lockfile.discover_tracked_lockfiles`); configured entries keep
their order and discovered entries follow in sorted order.
`regenerate_lockfiles` always includes the workspace root `Cargo.toml`,
validates nested manifests before invoking Cargo, and de-duplicates resolved
manifest paths.

For screen readers: the following flowchart traces `regenerate_lockfiles`. It
resolves the manifest list, then initializes empty `lockfiles` and `failures`
Expand Down Expand Up @@ -258,14 +269,16 @@ the original cargo error rather than wrapped in the aggregate message.
`lockfile_repository` field, a `bump_lockfiles.LockfileRepository` port
introduced by issue #82: the bump domain never holds a raw command runner. When
the field is `None`, bump uses `bump_lockfiles.CargoLockfileRepository`, the
cargo-backed adapter bound to the default subprocess runner; the CLI binds the
adapter to its selected runner. Tests inject a repository (or bind the adapter
to a recording runner) so lockfile commands can be observed without invoking
real Cargo processes. The port's scope is bump-side lockfile projection and
regeneration; publish-side discovery and validation go through the sibling
`lockfile.LockfileInspectionRepository` port (see the Lockfile helpers section
below), so neither the bump nor the publish lockfile domain holds a raw
`CommandRunner` (issue #82).
cargo- and git-backed adapter bound to the default subprocess runner; the CLI
binds the adapter to its selected runner. The adapter merges configured
manifests with manifests discovered from tracked lockfiles before either
projecting dry-run paths or regenerating live lockfiles. Tests inject a
repository (or bind the adapter to a recording runner) so lockfile commands can
be observed without invoking real processes. The port's scope is bump-side
lockfile projection and regeneration; publish-side discovery and validation go
through the sibling `lockfile.LockfileInspectionRepository` port (see the
Lockfile helpers section below), so neither the bump nor the publish lockfile
domain holds a raw `CommandRunner` (issue #82).

Bump-time crate-set derivation is centralized in the bump context: the
`excluded` and `updated_crate_names` sets are computed exactly once in
Expand Down Expand Up @@ -369,8 +382,11 @@ Private helpers `_handle_git_ls_files_failure` and `_lockfiles_with_manifests`
perform the error-handling and path-filtering passes respectively.

Lockfile regeneration after `lading bump` is owned by
`lading.commands.bump_lockfiles.regenerate_lockfiles`, which runs
`cargo update --workspace` per configured manifest. The two cargo strategies
`lading.commands.bump_lockfiles.CargoLockfileRepository`. The adapter uses
`bump_lockfiles.merge_discovered_manifests` to union the configured
`bump.lockfile_manifests` entries with manifests implied by
`discover_tracked_lockfiles`, then delegates to `regenerate_lockfiles`, which
runs `cargo update --workspace` per merged manifest. The two cargo strategies
differ deliberately: bump refreshes existing pinned versions in place after
manifest rewrites, while publish only probes freshness read-only via
`cargo metadata --locked` and never regenerates.
Expand Down Expand Up @@ -593,6 +609,8 @@ canonical replacement callers and tests now use directly:
| Private `_append_section` / `_format_plan` | `publish_plan.py` | renamed to public `append_section` / `format_plan` |
| `split_command` / `_split_command` wrapper | `publish_execution.py` | `lading.runtime.subprocess_runner.split_command` |

_Table 1: Compatibility shims removed by the issue #163 sweep._

#### Retained boundaries

Not every module-level indirection is a compatibility shim. The following
Expand Down
Loading
Loading