* Prefer AGENTS.md over CLAUDE.md for project instructions * fix: preserve CLAUDE.md fallback behavior * fix: isolate onboarding tests and preserve legacy init * fix: restore full fsOperations exports in test mock and align compact cwd * Fix onboarding test isolation and init migration guidance * Tighten init prompt coverage and onboarding copy * Handle nested project instruction paths consistently * Fix NEW_INIT feature gate for Bun build --------- Co-authored-by: 赵小落 <zhaoxiaoluo@zhaoxiaoluodeMac-mini.local> Co-authored-by: zhaomo01 <zhaomo01@baidu.com>
106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
import { join } from 'node:path'
|
|
|
|
import {
|
|
findProjectInstructionFilePathInAncestors,
|
|
FALLBACK_PROJECT_INSTRUCTION_FILE,
|
|
getProjectInstructionFilePath,
|
|
getProjectInstructionFilePaths,
|
|
hasProjectInstructionFile,
|
|
isProjectInstructionFileName,
|
|
PRIMARY_PROJECT_INSTRUCTION_FILE,
|
|
} from './projectInstructions.js'
|
|
|
|
describe('projectInstructions', () => {
|
|
test('prefers AGENTS.md over CLAUDE.md for root project instructions', () => {
|
|
const dir = '/repo'
|
|
const existingPaths = new Set([
|
|
join(dir, PRIMARY_PROJECT_INSTRUCTION_FILE),
|
|
join(dir, FALLBACK_PROJECT_INSTRUCTION_FILE),
|
|
])
|
|
|
|
const filePath = getProjectInstructionFilePath(
|
|
dir,
|
|
path => existingPaths.has(path),
|
|
)
|
|
|
|
expect(filePath).toBe(join(dir, PRIMARY_PROJECT_INSTRUCTION_FILE))
|
|
})
|
|
|
|
test('falls back to CLAUDE.md when AGENTS.md is absent', () => {
|
|
const dir = '/repo'
|
|
const existingPaths = new Set([join(dir, FALLBACK_PROJECT_INSTRUCTION_FILE)])
|
|
|
|
const filePath = getProjectInstructionFilePath(
|
|
dir,
|
|
path => existingPaths.has(path),
|
|
)
|
|
|
|
expect(filePath).toBe(join(dir, FALLBACK_PROJECT_INSTRUCTION_FILE))
|
|
})
|
|
|
|
test('returns both candidate root instruction paths', () => {
|
|
const dir = '/repo'
|
|
|
|
expect(getProjectInstructionFilePaths(dir)).toEqual([
|
|
join(dir, PRIMARY_PROJECT_INSTRUCTION_FILE),
|
|
join(dir, FALLBACK_PROJECT_INSTRUCTION_FILE),
|
|
])
|
|
})
|
|
|
|
test('detects whether a repo instruction file exists', () => {
|
|
const dir = '/repo'
|
|
const existingPaths = new Set([join(dir, PRIMARY_PROJECT_INSTRUCTION_FILE)])
|
|
|
|
expect(hasProjectInstructionFile(dir, path => existingPaths.has(path))).toBe(
|
|
true,
|
|
)
|
|
expect(hasProjectInstructionFile(dir, () => false)).toBe(false)
|
|
})
|
|
|
|
test('recognizes AGENTS.md as a root instruction filename', () => {
|
|
expect(isProjectInstructionFileName(PRIMARY_PROJECT_INSTRUCTION_FILE)).toBe(
|
|
true,
|
|
)
|
|
expect(isProjectInstructionFileName(FALLBACK_PROJECT_INSTRUCTION_FILE)).toBe(
|
|
true,
|
|
)
|
|
expect(isProjectInstructionFileName('README.md')).toBe(false)
|
|
})
|
|
|
|
test('finds repo instructions in ancestor directories', () => {
|
|
const repoDir = '/repo'
|
|
const nestedDir = join(repoDir, 'packages', 'app')
|
|
const existingPaths = new Set([join(repoDir, PRIMARY_PROJECT_INSTRUCTION_FILE)])
|
|
|
|
expect(
|
|
findProjectInstructionFilePathInAncestors(
|
|
nestedDir,
|
|
path => existingPaths.has(path),
|
|
),
|
|
).toBe(join(repoDir, PRIMARY_PROJECT_INSTRUCTION_FILE))
|
|
})
|
|
|
|
test('prefers the closest ancestor project instruction file', () => {
|
|
const repoDir = '/repo'
|
|
const nestedProjectDir = join(repoDir, 'packages', 'app')
|
|
const existingPaths = new Set([
|
|
join(repoDir, PRIMARY_PROJECT_INSTRUCTION_FILE),
|
|
join(nestedProjectDir, FALLBACK_PROJECT_INSTRUCTION_FILE),
|
|
])
|
|
|
|
expect(
|
|
findProjectInstructionFilePathInAncestors(
|
|
join(nestedProjectDir, 'src'),
|
|
path => existingPaths.has(path),
|
|
),
|
|
).toBe(join(nestedProjectDir, FALLBACK_PROJECT_INSTRUCTION_FILE))
|
|
})
|
|
|
|
test('returns null when no ancestor repo instruction file exists', () => {
|
|
expect(
|
|
findProjectInstructionFilePathInAncestors('/repo/packages/app', () => false),
|
|
).toBeNull()
|
|
})
|
|
})
|