diff --git a/bin/gstack-diff-scope b/bin/gstack-diff-scope index 36918381c..7e37d3a21 100755 --- a/bin/gstack-diff-scope +++ b/bin/gstack-diff-scope @@ -75,7 +75,7 @@ while IFS= read -r f; do # Backend: everything else that's code (excluding views/components already matched) *.rb|*.py|*.go|*.rs|*.java|*.php|*.ex|*.exs) BACKEND=true ;; - *.ts|*.js) BACKEND=true ;; # Non-component TS/JS is backend + *.ts|*.mts|*.cts|*.js|*.mjs|*.cjs) BACKEND=true ;; # Non-component TS/JS is backend (incl. ESM .mjs/.mts + CJS .cjs/.cts) esac done <<< "$FILES" diff --git a/test/diff-scope.test.ts b/test/diff-scope.test.ts index 2130a3e57..5cb67c310 100644 --- a/test/diff-scope.test.ts +++ b/test/diff-scope.test.ts @@ -84,6 +84,17 @@ describe('gstack-diff-scope', () => { expect(scope.SCOPE_TESTS).toBe('true'); }); + test('detects backend via ESM/CJS extensions (.mjs/.cjs/.mts/.cts)', () => { + // Pure-ESM Node projects ship backend code as .mjs/.cjs (and explicit-module + // TypeScript as .mts/.cts). These must register as backend so the review + // army's backend/security reviewers fire on such changes. + for (const f of ['server.mjs', 'helper.cjs', 'mod.mts', 'legacy.cts']) { + const dir = createRepo([f]); + const scope = runScope(dir); + expect(scope.SCOPE_BACKEND).toBe('true'); + } + }); + // --- New scope signals (Review Army) --- test('detects migrations via db/migrate/', () => {