From f395cc595da0cf6a25bb95666bab6293470fdaec Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Wed, 11 Mar 2026 07:37:58 -0600 Subject: [PATCH 1/4] fix: address feedback on domain discovery and monorepo setup commands - Add hard rule #3 to domain-discovery: never ask factual questions the agent can answer by searching the codebase. Distinguishes factual questions (grep it) from judgment questions (ask the maintainer). - Expand Phase 1a to read all in-repo markdown docs before the first interview, preventing the agent from asking questions docs already answer. - Make edit-package-json and add-library-bin monorepo-aware: when run from a monorepo root, they find all workspace packages containing SKILL.md files and apply changes to each package's package.json. Co-Authored-By: Claude Opus 4.6 --- .../intent/meta/domain-discovery/SKILL.md | 29 ++- packages/intent/src/cli.ts | 8 +- packages/intent/src/setup.ts | 174 +++++++++++++++++- 3 files changed, 201 insertions(+), 10 deletions(-) diff --git a/packages/intent/meta/domain-discovery/SKILL.md b/packages/intent/meta/domain-discovery/SKILL.md index bf9f529..fdfee28 100644 --- a/packages/intent/meta/domain-discovery/SKILL.md +++ b/packages/intent/meta/domain-discovery/SKILL.md @@ -76,23 +76,33 @@ These rules override any other reasoning. No exceptions. STOP and WAIT for their reply. Do not answer your own questions. Do not infer answers from documentation. Do not skip questions because you believe you already know the answer. -3. **Do not convert open-ended questions into multiple-choice, +3. **Never ask factual questions you can answer by searching the + codebase.** Before asking any question, determine whether the answer + is a deterministic fact (how many X exist, what versions are + supported, which files implement Y) or a judgment call (which ones + matter, what should we prioritize, what do developers struggle with). + Factual questions must be answered by searching the code — grep, + glob, read files. Only ask the maintainer for priorities, opinions, + trade-offs, and implicit knowledge that cannot be found in code or + docs. Asking the maintainer a question whose answer is sitting in + the codebase wastes their time and erodes trust in the process. +4. **Do not convert open-ended questions into multiple-choice, yes/no, or confirmation prompts.** The question templates in each sub-section are open-ended by design. Present them as open-ended questions. The maintainer's unprompted answers surface knowledge that pre-structured options suppress. -4. **Minimum question counts are enforced.** Each sub-section specifies +5. **Minimum question counts are enforced.** Each sub-section specifies a question count range (e.g. "2–4 questions"). You must ask at least the minimum number. Asking zero questions in any sub-section is a protocol violation. -5. **STOP gates are mandatory.** At the boundaries marked `── STOP ──` +6. **STOP gates are mandatory.** At the boundaries marked `── STOP ──` below, you must halt execution and wait for the maintainer's response or acknowledgment before proceeding. Do not continue past a STOP gate in the same message. -6. **If the maintainer asks to skip an interview phase**, explain the +7. **If the maintainer asks to skip an interview phase**, explain the value of the phase and what will be lost. Proceed with skipping only if they confirm a second time. -7. **Rich documentation makes interviews MORE valuable, not less.** +8. **Rich documentation makes interviews MORE valuable, not less.** When docs are comprehensive, the interview surfaces what docs miss: implicit knowledge, AI-specific failure modes, undocumented tradeoffs, and the maintainer's prioritization of what matters most. Never @@ -115,6 +125,15 @@ reading exhaustively yet. 4. **AGENTS.md or .cursorrules** — if the library already has agent guidance, read it. This is high-signal for what the maintainer considers important +5. **All in-repo documentation** — list every `.md` file in the `docs/` + directory (and any other documentation directories like `guides/`, + `reference/`, `wiki/`). Read every file. This is NOT the exhaustive + external doc reading from Phase 3 — this is reading what the + maintainer committed to the repository, which is fast and + high-signal. In-repo docs often contain migration guides, backward + compatibility notes, architecture decisions, and other context that + prevents you from asking factual questions the docs already answer. + Do not sample a subset — read them all before the first interview. ### 1b — Read peer dependency constraints diff --git a/packages/intent/src/cli.ts b/packages/intent/src/cli.ts index f1af60b..5599ad8 100644 --- a/packages/intent/src/cli.ts +++ b/packages/intent/src/cli.ts @@ -565,13 +565,13 @@ skills: break } case 'add-library-bin': { - const { runAddLibraryBin } = await import('./setup.js') - runAddLibraryBin(process.cwd()) + const { runAddLibraryBinAll } = await import('./setup.js') + runAddLibraryBinAll(process.cwd()) break } case 'edit-package-json': { - const { runEditPackageJson } = await import('./setup.js') - runEditPackageJson(process.cwd()) + const { runEditPackageJsonAll } = await import('./setup.js') + runEditPackageJsonAll(process.cwd()) break } case 'setup-github-actions': { diff --git a/packages/intent/src/setup.ts b/packages/intent/src/setup.ts index be31874..381ab11 100644 --- a/packages/intent/src/setup.ts +++ b/packages/intent/src/setup.ts @@ -5,7 +5,9 @@ import { readdirSync, writeFileSync, } from 'node:fs' -import { join } from 'node:path' +import { join, relative } from 'node:path' +import { parse as parseYaml } from 'yaml' +import { findSkillFiles } from './utils.js' // --------------------------------------------------------------------------- // Types @@ -26,6 +28,16 @@ export interface SetupGithubActionsResult { skipped: Array } +export interface MonorepoEditResult { + package: string + result: EditPackageJsonResult +} + +export interface MonorepoBinResult { + package: string + result: AddLibraryBinResult +} + interface TemplateVars { PACKAGE_NAME: string REPO: string @@ -337,6 +349,166 @@ export function runEditPackageJson(root: string): EditPackageJsonResult { return result } +// --------------------------------------------------------------------------- +// Monorepo workspace resolution +// --------------------------------------------------------------------------- + +interface WorkspaceConfig { + patterns: Array +} + +function readWorkspaceConfig(root: string): WorkspaceConfig | null { + // pnpm-workspace.yaml + const pnpmWs = join(root, 'pnpm-workspace.yaml') + if (existsSync(pnpmWs)) { + try { + const config = parseYaml(readFileSync(pnpmWs, 'utf8')) as Record< + string, + unknown + > + if (Array.isArray(config.packages)) { + return { patterns: config.packages as Array } + } + } catch {} + } + + // package.json workspaces + const pkgPath = join(root, 'package.json') + if (existsSync(pkgPath)) { + try { + const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) + if (Array.isArray(pkg.workspaces)) { + return { patterns: pkg.workspaces } + } + if (Array.isArray(pkg.workspaces?.packages)) { + return { patterns: pkg.workspaces.packages } + } + } catch {} + } + + return null +} + +/** + * Resolve workspace glob patterns to actual package directories. + * Handles simple patterns like "packages/*" and "packages/**". + * Each resolved directory must contain a package.json. + */ +function resolveWorkspacePackages( + root: string, + patterns: Array, +): Array { + const dirs: Array = [] + + for (const pattern of patterns) { + // Strip trailing /* or /**/* for directory resolution + const base = pattern.replace(/\/\*\*?(\/\*)?$/, '') + const baseDir = join(root, base) + if (!existsSync(baseDir)) continue + + if (pattern.includes('**')) { + // Recursive: walk all subdirectories + collectPackageDirs(baseDir, dirs) + } else if (pattern.endsWith('/*')) { + // Single level: direct children + for (const entry of readdirSync(baseDir, { withFileTypes: true })) { + if (!entry.isDirectory()) continue + const dir = join(baseDir, entry.name) + if (existsSync(join(dir, 'package.json'))) { + dirs.push(dir) + } + } + } else { + // Exact path + const dir = join(root, pattern) + if (existsSync(join(dir, 'package.json'))) { + dirs.push(dir) + } + } + } + + return dirs +} + +function collectPackageDirs(dir: string, result: Array): void { + if (existsSync(join(dir, 'package.json'))) { + result.push(dir) + } + for (const entry of readdirSync(dir, { withFileTypes: true })) { + if (!entry.isDirectory() || entry.name === 'node_modules') continue + collectPackageDirs(join(dir, entry.name), result) + } +} + +/** + * Find workspace packages that contain at least one SKILL.md file. + */ +function findPackagesWithSkills(root: string): Array { + const config = readWorkspaceConfig(root) + if (!config) return [] + + const allPkgs = resolveWorkspacePackages(root, config.patterns) + return allPkgs.filter((dir) => { + const skillsDir = join(dir, 'skills') + return existsSync(skillsDir) && findSkillFiles(skillsDir).length > 0 + }) +} + +// --------------------------------------------------------------------------- +// Command: edit-package-json (monorepo-aware) +// --------------------------------------------------------------------------- + +/** + * When run from a monorepo root, finds all workspace packages with SKILL.md + * files and runs edit-package-json on each. When run from a non-root + * directory, falls back to single-package behavior. + */ +export function runEditPackageJsonAll( + root: string, +): Array | EditPackageJsonResult { + const pkgsWithSkills = findPackagesWithSkills(root) + + if (pkgsWithSkills.length === 0) { + return runEditPackageJson(root) + } + + const results: Array = [] + for (const pkgDir of pkgsWithSkills) { + const rel = relative(root, pkgDir) || '.' + console.log(`\n── ${rel} ──`) + const result = runEditPackageJson(pkgDir) + results.push({ package: rel, result }) + } + return results +} + +// --------------------------------------------------------------------------- +// Command: add-library-bin (monorepo-aware) +// --------------------------------------------------------------------------- + +/** + * When run from a monorepo root, finds all workspace packages with SKILL.md + * files and runs add-library-bin on each. + */ +export function runAddLibraryBinAll( + root: string, +): Array | AddLibraryBinResult { + const pkgsWithSkills = findPackagesWithSkills(root) + + if (pkgsWithSkills.length === 0) { + return runAddLibraryBin(root) + } + + const results: Array = [] + for (const pkgDir of pkgsWithSkills) { + const rel = relative(root, pkgDir) || '.' + console.log(`\n── ${rel} ──`) + const result = runAddLibraryBin(pkgDir) + results.push({ package: rel, result }) + } + return results +} + // --------------------------------------------------------------------------- // Command: setup-github-actions // --------------------------------------------------------------------------- From 38d6860191a651e1b2677890f33447d7116fa672 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Wed, 11 Mar 2026 07:53:39 -0600 Subject: [PATCH 2/4] refactor: apply code simplification and review fixes - Unify MonorepoEditResult/MonorepoBinResult into generic MonorepoResult - Extract runForEachPackage to deduplicate monorepo-aware wrappers - Add warning logs to empty catch blocks in readWorkspacePatterns - Add error handling for readdirSync in collectPackageDirs - Skip hidden directories during recursive workspace walks - Distinguish "not a monorepo" from "monorepo with no skill packages" to avoid modifying root package.json incorrectly - Add tests for monorepo-aware edit-package-json and add-library-bin Co-Authored-By: Claude Opus 4.6 --- packages/intent/src/setup.ts | 113 +++++++++---------- packages/intent/tests/setup.test.ts | 166 ++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+), 58 deletions(-) diff --git a/packages/intent/src/setup.ts b/packages/intent/src/setup.ts index 381ab11..77d7df5 100644 --- a/packages/intent/src/setup.ts +++ b/packages/intent/src/setup.ts @@ -28,14 +28,9 @@ export interface SetupGithubActionsResult { skipped: Array } -export interface MonorepoEditResult { +export interface MonorepoResult { package: string - result: EditPackageJsonResult -} - -export interface MonorepoBinResult { - package: string - result: AddLibraryBinResult + result: T } interface TemplateVars { @@ -353,11 +348,7 @@ export function runEditPackageJson(root: string): EditPackageJsonResult { // Monorepo workspace resolution // --------------------------------------------------------------------------- -interface WorkspaceConfig { - patterns: Array -} - -function readWorkspaceConfig(root: string): WorkspaceConfig | null { +function readWorkspacePatterns(root: string): Array | null { // pnpm-workspace.yaml const pnpmWs = join(root, 'pnpm-workspace.yaml') if (existsSync(pnpmWs)) { @@ -367,9 +358,13 @@ function readWorkspaceConfig(root: string): WorkspaceConfig | null { unknown > if (Array.isArray(config.packages)) { - return { patterns: config.packages as Array } + return config.packages as Array } - } catch {} + } catch (err: unknown) { + console.error( + `Warning: failed to parse ${pnpmWs}: ${err instanceof Error ? err.message : err}`, + ) + } } // package.json workspaces @@ -378,12 +373,16 @@ function readWorkspaceConfig(root: string): WorkspaceConfig | null { try { const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) if (Array.isArray(pkg.workspaces)) { - return { patterns: pkg.workspaces } + return pkg.workspaces } if (Array.isArray(pkg.workspaces?.packages)) { - return { patterns: pkg.workspaces.packages } + return pkg.workspaces.packages } - } catch {} + } catch (err: unknown) { + console.error( + `Warning: failed to parse ${pkgPath}: ${err instanceof Error ? err.message : err}`, + ) + } } return null @@ -434,8 +433,17 @@ function collectPackageDirs(dir: string, result: Array): void { if (existsSync(join(dir, 'package.json'))) { result.push(dir) } - for (const entry of readdirSync(dir, { withFileTypes: true })) { - if (!entry.isDirectory() || entry.name === 'node_modules') continue + let entries: Array + try { + entries = readdirSync(dir, { withFileTypes: true }) + } catch (err: unknown) { + console.error( + `Warning: could not read directory ${dir}: ${err instanceof Error ? err.message : err}`, + ) + return + } + for (const entry of entries) { + if (!entry.isDirectory() || entry.name === 'node_modules' || entry.name.startsWith('.')) continue collectPackageDirs(join(dir, entry.name), result) } } @@ -444,69 +452,58 @@ function collectPackageDirs(dir: string, result: Array): void { * Find workspace packages that contain at least one SKILL.md file. */ function findPackagesWithSkills(root: string): Array { - const config = readWorkspaceConfig(root) - if (!config) return [] + const patterns = readWorkspacePatterns(root) + if (!patterns) return [] - const allPkgs = resolveWorkspacePackages(root, config.patterns) - return allPkgs.filter((dir) => { + return resolveWorkspacePackages(root, patterns).filter((dir) => { const skillsDir = join(dir, 'skills') return existsSync(skillsDir) && findSkillFiles(skillsDir).length > 0 }) } // --------------------------------------------------------------------------- -// Command: edit-package-json (monorepo-aware) +// Monorepo-aware command runner // --------------------------------------------------------------------------- /** * When run from a monorepo root, finds all workspace packages with SKILL.md - * files and runs edit-package-json on each. When run from a non-root - * directory, falls back to single-package behavior. + * files and runs the given command on each. Falls back to single-package + * behavior only when no workspace config is detected. If workspace config + * exists but no packages have skills, warns and returns empty. */ -export function runEditPackageJsonAll( +function runForEachPackage( root: string, -): Array | EditPackageJsonResult { - const pkgsWithSkills = findPackagesWithSkills(root) + runOne: (dir: string) => T, +): Array> | T { + const isMonorepo = readWorkspacePatterns(root) !== null + const pkgsWithSkills = isMonorepo ? findPackagesWithSkills(root) : [] + + if (!isMonorepo) { + return runOne(root) + } if (pkgsWithSkills.length === 0) { - return runEditPackageJson(root) + console.log('No workspace packages with skills found.') + return [] } - const results: Array = [] - for (const pkgDir of pkgsWithSkills) { + return pkgsWithSkills.map((pkgDir) => { const rel = relative(root, pkgDir) || '.' console.log(`\n── ${rel} ──`) - const result = runEditPackageJson(pkgDir) - results.push({ package: rel, result }) - } - return results + return { package: rel, result: runOne(pkgDir) } + }) } -// --------------------------------------------------------------------------- -// Command: add-library-bin (monorepo-aware) -// --------------------------------------------------------------------------- +export function runEditPackageJsonAll( + root: string, +): Array> | EditPackageJsonResult { + return runForEachPackage(root, runEditPackageJson) +} -/** - * When run from a monorepo root, finds all workspace packages with SKILL.md - * files and runs add-library-bin on each. - */ export function runAddLibraryBinAll( root: string, -): Array | AddLibraryBinResult { - const pkgsWithSkills = findPackagesWithSkills(root) - - if (pkgsWithSkills.length === 0) { - return runAddLibraryBin(root) - } - - const results: Array = [] - for (const pkgDir of pkgsWithSkills) { - const rel = relative(root, pkgDir) || '.' - console.log(`\n── ${rel} ──`) - const result = runAddLibraryBin(pkgDir) - results.push({ package: rel, result }) - } - return results +): Array> | AddLibraryBinResult { + return runForEachPackage(root, runAddLibraryBin) } // --------------------------------------------------------------------------- diff --git a/packages/intent/tests/setup.test.ts b/packages/intent/tests/setup.test.ts index 1c4f6d2..b3f75fd 100644 --- a/packages/intent/tests/setup.test.ts +++ b/packages/intent/tests/setup.test.ts @@ -12,8 +12,11 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { runAddLibraryBin, runEditPackageJson, + runEditPackageJsonAll, + runAddLibraryBinAll, runSetupGithubActions, } from '../src/setup.js' +import type { MonorepoResult, EditPackageJsonResult, AddLibraryBinResult } from '../src/setup.js' let root: string let metaDir: string @@ -288,3 +291,166 @@ describe('runSetupGithubActions', () => { expect(result.workflows).toHaveLength(0) }) }) + +// --------------------------------------------------------------------------- +// Monorepo-aware commands +// --------------------------------------------------------------------------- + +/** + * Helper: create a monorepo layout with pnpm-workspace.yaml, + * workspace packages, and optional SKILL.md files. + */ +function createMonorepo(opts?: { + usePackageJsonWorkspaces?: boolean + packages?: Array<{ name: string; hasSkills?: boolean }> +}): string { + const monoRoot = mkdtempSync(join(tmpdir(), 'mono-test-')) + const packages = opts?.packages ?? [ + { name: 'lib-a', hasSkills: true }, + { name: 'lib-b', hasSkills: false }, + ] + + if (opts?.usePackageJsonWorkspaces) { + writeFileSync( + join(monoRoot, 'package.json'), + JSON.stringify( + { private: true, workspaces: ['packages/*'] }, + null, + 2, + ), + ) + } else { + writeFileSync( + join(monoRoot, 'package.json'), + JSON.stringify({ private: true }, null, 2), + ) + writeFileSync( + join(monoRoot, 'pnpm-workspace.yaml'), + 'packages:\n - "packages/*"\n', + ) + } + + for (const pkg of packages) { + const pkgDir = join(monoRoot, 'packages', pkg.name) + mkdirSync(pkgDir, { recursive: true }) + writeFileSync( + join(pkgDir, 'package.json'), + JSON.stringify({ name: `@scope/${pkg.name}`, files: ['dist'] }, null, 2), + ) + if (pkg.hasSkills) { + const skillDir = join(pkgDir, 'skills', 'core', 'setup') + mkdirSync(skillDir, { recursive: true }) + writeFileSync( + join(skillDir, 'SKILL.md'), + '---\nname: core/setup\ndescription: test\n---\n# Setup\n', + ) + } + } + + return monoRoot +} + +describe('runEditPackageJsonAll', () => { + it('updates only packages with skills in pnpm monorepo', () => { + const monoRoot = createMonorepo() + + const results = runEditPackageJsonAll(monoRoot) as Array< + MonorepoResult + > + + expect(Array.isArray(results)).toBe(true) + expect(results).toHaveLength(1) + expect(results[0]!.package).toBe(join('packages', 'lib-a')) + expect(results[0]!.result.added).toContain('files: "skills"') + + // lib-b should not have been modified + const libBPkg = JSON.parse( + readFileSync( + join(monoRoot, 'packages', 'lib-b', 'package.json'), + 'utf8', + ), + ) + expect(libBPkg.files).toEqual(['dist']) + + rmSync(monoRoot, { recursive: true, force: true }) + }) + + it('updates only packages with skills using package.json workspaces', () => { + const monoRoot = createMonorepo({ usePackageJsonWorkspaces: true }) + + const results = runEditPackageJsonAll(monoRoot) as Array< + MonorepoResult + > + + expect(Array.isArray(results)).toBe(true) + expect(results).toHaveLength(1) + expect(results[0]!.package).toBe(join('packages', 'lib-a')) + + rmSync(monoRoot, { recursive: true, force: true }) + }) + + it('falls back to single-package when no workspace config exists', () => { + writePkg({ name: 'test-pkg', files: ['dist'] }, 2) + + const result = runEditPackageJsonAll(root) as EditPackageJsonResult + + expect(Array.isArray(result)).toBe(false) + expect(result.added).toContain('files: "skills"') + }) + + it('returns empty array when monorepo has no packages with skills', () => { + const monoRoot = createMonorepo({ + packages: [ + { name: 'lib-a', hasSkills: false }, + { name: 'lib-b', hasSkills: false }, + ], + }) + + const results = runEditPackageJsonAll(monoRoot) + + expect(Array.isArray(results)).toBe(true) + expect(results).toHaveLength(0) + + // Root package.json should NOT have been modified + const rootPkg = JSON.parse( + readFileSync(join(monoRoot, 'package.json'), 'utf8'), + ) + expect(rootPkg.files).toBeUndefined() + + rmSync(monoRoot, { recursive: true, force: true }) + }) +}) + +describe('runAddLibraryBinAll', () => { + it('generates shims only in packages with skills', () => { + const monoRoot = createMonorepo() + + const results = runAddLibraryBinAll(monoRoot) as Array< + MonorepoResult + > + + expect(Array.isArray(results)).toBe(true) + expect(results).toHaveLength(1) + expect(results[0]!.package).toBe(join('packages', 'lib-a')) + expect(results[0]!.result.shim).toBeTruthy() + + // lib-b should not have a shim + expect( + existsSync(join(monoRoot, 'packages', 'lib-b', 'bin', 'intent.mjs')), + ).toBe(false) + expect( + existsSync(join(monoRoot, 'packages', 'lib-b', 'bin', 'intent.js')), + ).toBe(false) + + rmSync(monoRoot, { recursive: true, force: true }) + }) + + it('falls back to single-package when no workspace config exists', () => { + writePkg({ name: 'test-pkg' }) + + const result = runAddLibraryBinAll(root) as AddLibraryBinResult + + expect(Array.isArray(result)).toBe(false) + expect(result.shim).toBeTruthy() + }) +}) From 6831d4ceeb5034532c5da32258eddbf0cb800e6c Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Wed, 11 Mar 2026 07:54:03 -0600 Subject: [PATCH 3/4] chore: add changeset for monorepo-aware setup commands Co-Authored-By: Claude Opus 4.6 --- .changeset/monorepo-aware-setup-commands.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/monorepo-aware-setup-commands.md diff --git a/.changeset/monorepo-aware-setup-commands.md b/.changeset/monorepo-aware-setup-commands.md new file mode 100644 index 0000000..3578b8b --- /dev/null +++ b/.changeset/monorepo-aware-setup-commands.md @@ -0,0 +1,5 @@ +--- +'@tanstack/intent': patch +--- + +Make `edit-package-json` and `add-library-bin` monorepo-aware: when run from a monorepo root, they discover workspace packages containing SKILL.md files and apply changes to each package's package.json. Also improve domain-discovery skill to read in-repo docs before interviewing and avoid asking factual questions the agent can answer by searching the codebase. From 12f3a55716d55f09f51bc07dbebf893b26dbcf9e Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:55:19 +0000 Subject: [PATCH 4/4] ci: apply automated fixes --- packages/intent/src/setup.ts | 7 ++++++- packages/intent/tests/setup.test.ts | 17 +++++++---------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/intent/src/setup.ts b/packages/intent/src/setup.ts index 77d7df5..7bbac1b 100644 --- a/packages/intent/src/setup.ts +++ b/packages/intent/src/setup.ts @@ -443,7 +443,12 @@ function collectPackageDirs(dir: string, result: Array): void { return } for (const entry of entries) { - if (!entry.isDirectory() || entry.name === 'node_modules' || entry.name.startsWith('.')) continue + if ( + !entry.isDirectory() || + entry.name === 'node_modules' || + entry.name.startsWith('.') + ) + continue collectPackageDirs(join(dir, entry.name), result) } } diff --git a/packages/intent/tests/setup.test.ts b/packages/intent/tests/setup.test.ts index b3f75fd..2e9c95f 100644 --- a/packages/intent/tests/setup.test.ts +++ b/packages/intent/tests/setup.test.ts @@ -16,7 +16,11 @@ import { runAddLibraryBinAll, runSetupGithubActions, } from '../src/setup.js' -import type { MonorepoResult, EditPackageJsonResult, AddLibraryBinResult } from '../src/setup.js' +import type { + MonorepoResult, + EditPackageJsonResult, + AddLibraryBinResult, +} from '../src/setup.js' let root: string let metaDir: string @@ -313,11 +317,7 @@ function createMonorepo(opts?: { if (opts?.usePackageJsonWorkspaces) { writeFileSync( join(monoRoot, 'package.json'), - JSON.stringify( - { private: true, workspaces: ['packages/*'] }, - null, - 2, - ), + JSON.stringify({ private: true, workspaces: ['packages/*'] }, null, 2), ) } else { writeFileSync( @@ -365,10 +365,7 @@ describe('runEditPackageJsonAll', () => { // lib-b should not have been modified const libBPkg = JSON.parse( - readFileSync( - join(monoRoot, 'packages', 'lib-b', 'package.json'), - 'utf8', - ), + readFileSync(join(monoRoot, 'packages', 'lib-b', 'package.json'), 'utf8'), ) expect(libBPkg.files).toEqual(['dist'])