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
21 changes: 21 additions & 0 deletions .github/workflows/lint.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -2233,6 +2233,27 @@ jobs:
node scripts/check-declaration-mirrors.mjs --self-test
node scripts/check-declaration-mirrors.mjs

# Published list mirrors (#10855). The cross-package gate above is a SOURCE
# SCAN: a path spelling it does not know yields no flag, so the escaping read
# goes undeclared SILENTLY. That is why its recognised set is published in
# AGENTS.md instead of living only in the implementation — and nothing held the
# two copies in step. It drifted three times (#10163, #10854, #10855); measured
# on 1a47a5368 the published block was short by 13 of the 24 lines, the two
# findUp ANCHOR seeds among them. ⭐ Twice the stale line was the stated REASON
# FOR A PROHIBITION, so a rotting mirror does not merely misinform — it launders
# an obsolete rule into a live one, and the fix has to derive a new true reason.
# This asserts line-for-line EQUALITY (not containment: a comment-only drift is
# invisible to containment, and the comments are where the prohibitions live),
# locates the block by heading + fence rather than line number, and REFUSES
# rather than passing empty when it cannot find it. ⛔ It can only ever go RED:
# AGENTS.md is governed (human-merge-only), so it prints the block to paste and
# never repairs. Invoked as `node` rather than a `pnpm check:*` alias for the
# same reason as the step above (#9465). Reads two files; milliseconds.
- name: Published list mirrors
run: |
node scripts/check-published-list-mirrors.mjs --self-test
node scripts/check-published-list-mirrors.mjs

# The inventory of `packages/**` tests coupled to `examples/**` (#8754).
# Sibling of the cross-package gate above, on the axis that gate does not
# own. ⚠️ The line that used to stand here — "that one detects tests whose
Expand Down
34 changes: 21 additions & 13 deletions AGENTS.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -87,26 +87,34 @@ deliberately: a detector with no dependencies cannot itself fail to resolve in C
The price of a source scan is that it sees only the spellings it knows, and an
unrecognised one produces no flag — which means no declaration, **silently**. So the
recognised list is published rather than left inside the implementation. Seed from
`import.meta.url`or `__dirname`, and write the escaping path as one of:
`import.meta.url`, `__dirname` or a `findUp` walk, and write the escaping path as one of:

```ts
const HERE = dirname(fileURLToPath(import.meta.url)); // seed (ESM)
const HERE = __dirname; // seed (CJS)
const HERE = import.meta.dirname; // and dirname(import.meta.filename)
const HERE = resolve(fileURLToPath(import.meta.url), '..'); // seed walked from the
// FILE rather than named;
// import.meta.filename too
const P = resolve(HERE, '<rel>'); // join() and path.* too
const HERE = __dirname; // seed (CJS)
const HERE = import.meta.dirname; // and dirname(import.meta.filename)
const HERE = resolve(fileURLToPath(import.meta.url), '..'); // seed, walked
// from the FILE instead of named;
// import.meta.filename works too
const P = resolve(HERE, '<rel>'); // join() and the path.* forms too
const P = fileURLToPath(new URL('<rel>', import.meta.url));
const P = new URL('<rel>', import.meta.url);
readFileSync(resolve(HERE, '<rel>')) // the same expressions
readFileSync(new URL('<rel>', import.meta.url)) // in argument position
readFileSync(resolve(HERE, '<rel>')) // the same expressions in argument
readFileSync(new URL('<rel>', import.meta.url)) // position
const PKG = findUp((dir) => JSON.parse(readFileSync(join(dir, 'package.json'))).name
=== '<the name of THIS package>'); // -> package root
const REPO = findUp((dir) => existsSync(join(dir, 'pnpm-workspace.yaml')));
// -> repo root
⛔ NOT a manifest name belonging to some OTHER package -- that root cannot
be located from here, so the escape is flagged and the path is NOT named
```

The gate prints this list in its failure text too, and `--self-test` pins every entry.
Reaching for a spelling that is not here? **Extend the detector and add a `--self-test`
case in the same edit** — never route around it. An unseen read is the defect above, not
a style question, and a newly recognised shape with no pin is the next silent regression.
The gate prints this list in its failure text, where the notes that go with the spellings
live too, and `check-published-list-mirrors` holds the block above equal to it. That gate
can only ever go RED — this file is governed, so nothing repairs it for you. Reaching for
a spelling that is not here? **Extend the detector, add a `--self-test` case, and correct
the block in the same edit** — never route around it. An unseen read is the defect above,
and a newly recognised shape with no pin is the next silent regression.

Two things it deliberately does not flag: a path that climbs out and lands in
`node_modules` (an installed dependency is not a repo source input, and no turbo glob can
Expand Down
8 changes: 8 additions & 0 deletions scripts/check-cross-package-test-inputs.mjs
Original file line numberDiff line numberDiff line change
Expand Up@@ -312,6 +312,14 @@ const PATH_ARG_READS = ['readFileSync', 'readdirSync', 'statSync', 'lstatSync',
* a source scan: a spelling that is not on this list yields no flag, so a read
* written that way goes undeclared silently. Anything added here needs a
* `--self-test` case in the same edit, or the next refactor drops it unnoticed.
*
* The AGENTS.md copy is held BYTE-IDENTICAL to this array by
* `scripts/check-published-list-mirrors.mjs` (#10855), comments included: twice the
* stale line over there was the stated REASON FOR A PROHIBITION (#10163, #10854), so
* a containment check would have missed exactly the drift that cost the most. Editing
* this array therefore means editing that block in the SAME PR -- and AGENTS.md is
* governed, human-merge-only, so that gate can only ever go RED. It prints the block
* to paste.
*/
export const RECOGNISED_PATH_SPELLINGS = [
"const HERE = dirname(fileURLToPath(import.meta.url)); // seed (ESM)",
Expand Down
Loading