Skip to content

feat(install): monorepo arch boundaries + R3 inertness alarm — GH #534 - #539

Merged
artyhoo merged 1 commit into
stagingfrom
fix/gh-534-arch-monorepo-boundaries
Jun 15, 2026
Merged

feat(install): monorepo arch boundaries + R3 inertness alarm — GH #534#539
artyhoo merged 1 commit into
stagingfrom
fix/gh-534-arch-monorepo-boundaries

Conversation

@artyhoo

@artyhoo artyhoo commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Fixes #534

Problem

After #508 made arch:check run on a monorepo, the shipped .dependency-cruiser.cjs still carried only layered-monolith rules (src/domain|application|infrastructure|features). For a pnpm monorepo the boundaries that matter — packages/* ↛ apps/* and apps ↔ apps — were absent, so arch:check passed green while those imports were unguarded. And unlike R2 (which has the loud check:globs inertness alarm), R3 had no detector — the inertness was silent.

Fix (two parts)

  1. Layout-agnostic boundary rules added to the shipped arch config: no-package-to-app (packages↛apps, error) and no-cross-app (apps↔apps, warn). Both key on (?:^|/)packages/ / (?:^|/)apps/inert on a flat / layered single project, active on a monorepo. No install-time layout detection needed; no risk of false-positives on non-monorepos.
  2. check:arch-boundaries (scripts/check-arch-boundaries.sh) — the R3 inertness alarm, the dependency-cruiser analog of check:globs. On an apps/+packages/ monorepo it FAILS when the arch config has no packages↛apps rule (e.g. a pre-existing config install didn't overwrite). Dependency-free bash; skips on flat / single-tree workspace.

Wiring: ship + chmod the detector; add check:arch-boundaries script + into validate; add to the CI-orphan gate-map; add a step to both shipped CI templates after arch:check.

Verification

tests/install-sh/gh-534-arch-boundaries.test.sh: config carries the rules + valid JS; behavioral regex reaches the #534 repro path (inert on flat); detector Arm A (has rule → PASS) / Arm B paired-neg (no rule → FAIL) / Arm C (flat → skip). End-to-end real install wires + ships + the detector passes. install-sh suite 31/31, principles 188/188.

Build-vs-reuse

BUILD (SSOT #119): DeepWiki sverweij/dependency-cruiser (2026-06-15) confirms it has no built-in "rule matched zero modules" report, so there's nothing to ADOPT — this is the R3 analog of the own-built check-rule-globs.sh (same family as #114/#115). The boundary rules are plain dependency-cruiser config (REUSE of its engine); only the detector is BUILD.

§1.7 Forward-check applied

Complies with active disciplines, verified against source: no-paid-llm-in-ci — the detector is dependency-free bash, no node/depcruise/LLM at runtime (packages/core/audit-self/check-arch-boundaries.sh:13); build-first-reuse-default §3 — BUILD verdict justified by the DeepWiki+WebSearch negative-existence sweep recorded as SSOT #119 at docs/meta-factory/prior-art-evaluations.md:190, and the boundary rules are REUSE of dependency-cruiser's own engine (config-only); capability-commit gatePrior-art: trailer cites #119, landed in this same commit (§1.9 existence-check passes); doc-authority — new .sh/.cjs are code (no prose header), the SSOT row keeps the 8-column register format; non-duplicative wiring into the validate chain at install.sh:877.

§1.7 Backward-check applied

Swept all surfaces under the new gate's scope (R3 architecture-boundary enforcement): modelled the detector and its messaging on the existing R2 sibling packages/core/audit-self/check-rule-globs.sh:5 (the "silently inert" alarm), so R2 and R3 now have parallel liveness gates. The boundary rules were added to the single shipped arch config at templates/ts-server/dependency-cruiser.cjs:145 (shipped to both stacks). Wired the detector into every surface that already references arch:check — the validate chain, the CI-orphan gate-map, and both shipped CI templates (templates/ts-server/github-actions-ci.yml:80 + the react-next ui template). Regression coverage with a paired-negative in tests/install-sh/gh-534-arch-boundaries.test.sh:50. Verified no existing install-sh test asserts an exclusive gate list (full suite 31/31); the detector skips cleanly on flat/single-tree layouts so existing non-monorepo consumers keep passing.

…#534

After #508 made arch:check RUN on a monorepo, the shipped .dependency-cruiser.cjs
still carried only layered-monolith rules (src/domain|application|infrastructure|
features). For a pnpm monorepo the boundaries that matter — packages/* ↛ apps/*
and apps ↔ apps — were absent, so arch:check passed green while those imports were
unguarded; and unlike R2 (check:globs) there was NO inertness detector, so the gap
was silent.

Two parts:
1. Add layout-agnostic boundary rules to the shipped arch config: no-package-to-app
   (packages↛apps, error) and no-cross-app (apps↔apps, warn). Both key on (?:^|/)
   packages/ and (?:^|/)apps/ → INERT on a flat/layered single project, ACTIVE on a
   monorepo. No install-time layout detection needed.
2. check:arch-boundaries (scripts/check-arch-boundaries.sh) — the R3 inertness alarm,
   the dependency-cruiser analog of check:globs. On an apps/+packages/ monorepo it
   FAILS when the arch config has no packages↛apps rule (e.g. a pre-existing config
   install did not overwrite). Dependency-free bash; skips on flat / single-tree
   workspace. dependency-cruiser has no built-in "rule matched nothing" report
   (DeepWiki sverweij/dependency-cruiser 2026-06-15), so this is BUILD, the R3 analog
   of the own-built check-rule-globs.sh.

Wiring: ship + chmod the detector; add check:arch-boundaries script + into validate;
add to the CI-orphan gate-map; add a step to both shipped CI templates after arch:check.

Regression: tests/install-sh/gh-534-arch-boundaries.test.sh — config carries the
rules + valid JS; behavioral regex reaches the #534 repro path (inert on flat);
detector Arm A (has rule → PASS) / Arm B paired-neg (no rule → FAIL) / Arm C (flat →
skip). install-sh suite 31/31, principles 188/188.

Prior-art: prior-art-evaluations.md#119 (BUILD — no upstream: dependency-cruiser has no inert-rule report per DeepWiki+WebSearch 2026-06-15; R3 analog of the own-built check-rule-globs.sh, same family as #114/#115. Boundary rules themselves are plain dependency-cruiser config = REUSE of its engine; only the detector is BUILD.)
@artyhoo
artyhoo merged commit 51dd82f into staging Jun 15, 2026
25 checks passed
@artyhoo
artyhoo deleted the fix/gh-534-arch-monorepo-boundaries branch June 15, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

arch:check (R3) ships no monorepo boundaries and is silently inert — no inertness detector (unlike R2/check:globs)

1 participant