From 6febf93449033c03152ab5c1888a1190d8ba588e Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 27 Jul 2026 22:05:31 +0200 Subject: [PATCH] docs: mirror the quoted-lint-glob convention into AGENTS.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AGENTS.md already mirrors the neighbouring max-lines/baseline paragraph from CLAUDE.md, and it requires coding conventions to stay in sync between the two files. The quoted-glob rule landed only in CLAUDE.md, so agents bootstrapping from AGENTS.md could reintroduce a host-dependent lint target. Also corrects the wording in both copies: the shallow expansion happens on macOS as well as Linux — /bin/sh has no globstar on either — and the target still exits 0 with a broken glob, which is why this went unnoticed. Adds the file-count check that catches it. Co-Authored-By: Claude Opus 5 --- AGENTS.md | 1 + CLAUDE.md | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cdf03a35e..eb424f72b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,6 +17,7 @@ This file provides guidance to coding agents working in this repository. - Every Nx project should keep `scope:*`, `domain:*`, and `type:*` tags in `project.json` so `@nx/enforce-module-boundaries` remains useful for humans and agents. - See `docs/architecture/nx-workspace-boundaries.md` for the current Nx tag and alias policy. - ESLint enforces `max-lines` on TypeScript files (target under 300, hard maximum 400). Files that predate the rule are baselined in `tools/eslint/max-lines-baseline.mjs`; after splitting a file, regenerate it with `node tools/eslint/generate-max-lines-baseline.mjs`. Never add new files to the baseline — the list must only shrink. A new file that genuinely cannot be split (for example a function serialized into another process) instead carries its own file-wide `/* eslint-disable max-lines -- */`; the generator skips those files, so a justified exemption never lands in the baseline. +- Project `lint` targets that shell out to eslint must quote the glob, e.g. `eslint "apps//**/*.ts"`. An unquoted `**` is expanded by the POSIX shell on Linux and macOS (which has no `globstar`, so it matches only a shallow subset of files) while Windows passes the literal pattern to ESLint, which expands it recursively — the two hosts then lint different file sets. The target still reports success either way, so a broken glob hides missing coverage instead of failing. After changing such a target, compare the linted file count against `find -name '*.ts' | wc -l`. - Repository-specific skills are committed under `.codex/skills/`. Claude Code only discovers skills under `.claude/skills/`, so `release-notes` and `release-cut` are mirrored there and the two copies must be kept in sync; every other entry in `.claude/skills/` is personal and stays gitignored. If an external agent does not support skills, treat those files as concise ownership docs. ## Documentation After Changes diff --git a/CLAUDE.md b/CLAUDE.md index 223d8db5d..23ba46552 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -229,9 +229,12 @@ a justified exemption never lands in the baseline. Project `lint` targets that shell out to eslint must quote the glob, e.g. `eslint "apps//**/*.ts"`. An unquoted `**` is expanded by the POSIX -shell on Linux (matching only a shallow subset of files) while Windows passes -the literal pattern to ESLint, which expands it recursively — the two hosts -then lint different file sets. +shell on Linux and macOS (which has no `globstar`, so it matches only a +shallow subset of files) while Windows passes the literal pattern to ESLint, +which expands it recursively — the two hosts then lint different file sets. +The target still reports success either way, so a broken glob hides missing +coverage instead of failing. After changing such a target, compare the linted +file count against `find -name '*.ts' | wc -l`. ## Architecture