fix(lint): drop stale variants.py refs + ignore vendored skills in lint walks

Two follow-ups after c7bacbab5 removed `inventory/variants.py`:

* docs/contributing/design/variants.md and docs/requirements/020-*.md
  still referenced the deleted submodule, breaking
  `test_markdown_relative_links_resolve`. The design doc drops the
  removed entries from the reference table; the postmortem turns the
  historical mention into plaintext with a pointer to the removal
  commit and the current package layout.

* tests/lint/repository/test_markdown_links.py and
  test_project_root_import.py walked the worktree via
  `iter_project_files`, which does NOT honour `.gitignore`. In the
  `make exec` container path the markdown lint's primary
  `git ls-files` codepath fails and falls back to that walker, surfacing
  19 broken links inside vendored skill READMEs under `.agents/` and
  `.claude/skills/` plus 2 `parents[N]` violations in installed skill
  scripts. Both lints now use `iter_non_ignored_files` so gitignored
  trees (skills install output, build artefacts) are skipped in every
  environment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
kevinveenbirkenbachandClaude Opus 4.7 committed 2026-05-13 04:25:07 +02:00
1 parent a2b5269244
commit 115196f28f
4 files changed
+13 -7

No files matched your search

+2 -2
View File
@@ -32,10 +32,10 @@ The in-play loader (`utils.cache.applications.get_merged_applications`) always u
|---|---|
| [variants.md](../artefact/files/role/variants.md) | File-structure rules for `roles/<role>/meta/variants.yml`. |
| [applications.py (cache)](../../../utils/cache/applications.py) | Loader and cache for `_build_variants` (`get_variants` is the public Python entry point). The merged-applications path stays variant-agnostic; variant payloads reach it as inventory-level `applications.<app>` overrides. |
| [inventory/](../../../cli/administration/deploy/development/inventory/__init__.py) | Dev inventory build package. Per-submodule split: [`spec.py`](../../../cli/administration/deploy/development/inventory/spec.py) (`DevInventorySpec`), [`builder.py`](../../../cli/administration/deploy/development/inventory/builder.py) (`build_dev_inventory` variant baking + `build_dev_inventory_matrix` per-round driver), [`planner.py`](../../../cli/administration/deploy/development/inventory/planner.py) (`plan_dev_inventory_matrix` pure planner shared with the deploy wrapper), [`variants.py`](../../../cli/administration/deploy/development/inventory/variants.py) (strict variant-only include rule), [`legacy_resolver.py`](../../../cli/administration/deploy/development/inventory/legacy_resolver.py) (`CombinedResolver` fallback for apps without `variants.yml`). |
| [inventory/](../../../cli/administration/deploy/development/inventory/__init__.py) | Dev inventory build package. Per-submodule split: [`spec.py`](../../../cli/administration/deploy/development/inventory/spec.py) (`DevInventorySpec`), [`builder.py`](../../../cli/administration/deploy/development/inventory/builder.py) (`build_dev_inventory` variant baking + `build_dev_inventory_matrix` per-round driver), [`planner.py`](../../../cli/administration/deploy/development/inventory/planner.py) (`plan_dev_inventory_matrix` pure planner shared with the deploy wrapper), [`legacy_resolver.py`](../../../cli/administration/deploy/development/inventory/legacy_resolver.py) (`CombinedResolver`-driven include resolution). |
| [init.py](../../../cli/administration/deploy/development/init.py) | Dev CLI entry that drives `build_dev_inventory_matrix` to materialise `<inventory-dir>-<round>` folders. |
| [deploy.py](../../../cli/administration/deploy/development/deploy.py) | Dev CLI entry that re-derives the matrix plan and iterates one deploy per folder, with per-app cleanup between rounds. |
| [entity.sh](../../../scripts/tests/deploy/local/purge/entity.sh) | Cleanup script invoked between rounds for every app in the previous round's include set. |
| [test_variants.py](../../../tests/unit/utils/cache/test_variants.py) | Unit tests covering parser edge cases, deep-merge semantics, caching, and the variant-zero default path. |
| [tests/.../inventory/](../../../tests/unit/cli/administration/deploy/development/inventory/__init__.py) | Unit-test package mirroring the source split: [`test_spec.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_spec.py), [`test_payload.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_payload.py), [`test_planner.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_planner.py), [`test_builder.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_builder.py), [`test_variants.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_variants.py). |
| [tests/.../inventory/](../../../tests/unit/cli/administration/deploy/development/inventory/__init__.py) | Unit-test package mirroring the source split: [`test_spec.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_spec.py), [`test_payload.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_payload.py), [`test_planner.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_planner.py), [`test_builder.py`](../../../tests/unit/cli/administration/deploy/development/inventory/test_builder.py). |
| [test_matrix_deploy.py](../../../tests/unit/cli/administration/deploy/development/test_matrix_deploy.py) | Wrapper-level tests covering the per-round folder iteration and cleanup logic. |
@@ -152,7 +152,7 @@ Sorted DESC by `total` (carried over from [019](019-playwright-meta-services-par
Two recent change-sets interact:
1. `820fb0a22 fix(purge): clear stale nginx vhosts between matrix-deploy rounds` — extends the inter-round purge with an nginx-vhost primitive. The purge is correct in intent.
2. `f102c229f refactor(inventory): split monolith into SRP submodules + variant-only mode` — the new variant-only resolver in [cli/administration/deploy/development/inventory/variants.py](../../cli/administration/deploy/development/inventory/variants.py) builds each round's include list strictly from the variant's pinned `services:` block. Roles whose variants pin `postgres: shared: false` (25 `variants.yml` files do this for variant 1) drop their postgres dependency from the round.
2. `f102c229f refactor(inventory): split monolith into SRP submodules + variant-only mode` — the new variant-only resolver added in `cli/administration/deploy/development/inventory/variants.py` (removed again in commit `c7bacbab5`; see [inventory/](../../cli/administration/deploy/development/inventory/__init__.py) for the current package layout) built each round's include list strictly from the variant's pinned `services:` block. Roles whose variants pin `postgres: shared: false` (25 `variants.yml` files do this for variant 1) dropped their postgres dependency from the round.
Effect in CI Run 25705903504, round 1 for any postgres consumer:
+5 -2
View File
@@ -16,7 +16,7 @@ import unittest
from pathlib import Path
from typing import NamedTuple
from utils.cache.files import iter_project_files, read_text
from utils.cache.files import iter_non_ignored_files, read_text
from . import PROJECT_ROOT
@@ -54,7 +54,10 @@ def _tracked_md_files(root: Path) -> list[Path]:
rel_paths = [p for p in out.decode("utf-8", errors="replace").split("\0") if p]
return [root / rel for rel in rel_paths if rel.endswith(".md")]
except Exception:
return [Path(p) for p in iter_project_files(extensions=(".md",))]
# Fallback path (e.g. sandbox without git subprocess): walk the
# worktree but skip gitignored files so vendored skill packages
# under `.agents/` and `.claude/skills/` do NOT count.
return [Path(p) for p in iter_non_ignored_files(extensions=(".md",))]
def _is_checkable_link(target: str) -> bool:
@@ -52,7 +52,7 @@ import unittest
from pathlib import Path
from utils.annotations.suppress import is_suppressed_at
from utils.cache.files import iter_project_files, read_text
from utils.cache.files import iter_non_ignored_files, read_text
SUPPRESS_RULE: str = "project-root-import"
@@ -303,8 +303,11 @@ def _check_init_project_root(path: Path) -> list[str]:
class TestProjectRootImport(unittest.TestCase):
def test_no_local_project_root_computation(self):
# Walk only non-gitignored files so vendored skill packages under
# `.agents/` and `.claude/skills/` (which carry their own
# `parents[N]` boilerplate by upstream design) do NOT count.
offenders: list[str] = []
for path_str in iter_project_files(extensions=(".py",)):
for path_str in iter_non_ignored_files(extensions=(".py",)):
path = Path(path_str)
offenders.extend(_scan_file(path))
offenders.extend(_check_init_project_root(path))