diff --git a/.agent/CODEBASE.md b/.agent/CODEBASE.md index f6fe553..0ea0e7e 100644 --- a/.agent/CODEBASE.md +++ b/.agent/CODEBASE.md @@ -99,60 +99,6 @@ _Generated by `gen-codemap.sh`. Re-run after structural changes._ internal/cli/cli.go:67:type Version struct { internal/cli/cli.go:179:type App struct { internal/cli/cli.go:187:func New(out, errOut io.Writer, version Version) App { -internal/cli/cli_test.go:15:func TestListFlavors(t *testing.T) { -internal/cli/cli_test.go:28:func TestInitLegacyTargetArgument(t *testing.T) { -internal/cli/cli_test.go:47:func TestInitLegacyTargetArgumentWithoutFlag(t *testing.T) { -internal/cli/cli_test.go:61:func TestInitRejectsUnknownFlavor(t *testing.T) { -internal/cli/cli_test.go:74:func TestInitRejectsBareIdentifierAsSingleArg(t *testing.T) { -internal/cli/cli_test.go:90:func TestInitHelpFlagDoesNotError(t *testing.T) { -internal/cli/cli_test.go:106:func TestInitAgentsOnlyDropsFreshOnlyFiles(t *testing.T) { -internal/cli/cli_test.go:134:func TestInitAgentsOnlyRejectsUnsupportedFlavor(t *testing.T) { -internal/cli/cli_test.go:149:func TestInitVisibilityLocalAppendsGitignoreBlock(t *testing.T) { -internal/cli/cli_test.go:176:func TestInitVisibilityLocalIsIdempotent(t *testing.T) { -internal/cli/cli_test.go:197:func TestInitVisibilitySharedLeavesNoGitignore(t *testing.T) { -internal/cli/cli_test.go:214:func TestInitVisibilityLocalRejectedOnDocCollabFlavor(t *testing.T) { -internal/cli/cli_test.go:237:func TestInitVisibilityHiddenWritesGitInfoExclude(t *testing.T) { -internal/cli/cli_test.go:272:func TestInitPrivateAliasMatchesHidden(t *testing.T) { -internal/cli/cli_test.go:298:func TestInitPrivateConflictsWithVisibility(t *testing.T) { -internal/cli/cli_test.go:326:func TestInitVisibilityHiddenIsIdempotent(t *testing.T) { -internal/cli/cli_test.go:361:func TestInitVisibilityGlobalDefaultWritesExcludesAndWarns(t *testing.T) { -internal/cli/cli_test.go:395:func TestInitVisibilityGlobalDefaultIsIdempotent(t *testing.T) { -internal/cli/cli_test.go:415:func TestInitVisibilityHiddenRejectedOnDocCollabFlavor(t *testing.T) { -internal/cli/cli_test.go:428:func TestInitPrivateRejectedOnDocCollabFlavor(t *testing.T) { -internal/cli/cli_test.go:441:func TestInitVisibilityHiddenDryRunWritesNothing(t *testing.T) { -internal/cli/cli_test.go:458:func TestInitVisibilityGlobalDefaultDryRunWritesNothing(t *testing.T) { -internal/cli/cli_test.go:479:func TestInitVisibilityGlobalDefaultRejectedOnDocCollabFlavor(t *testing.T) { -internal/cli/cli_test.go:492:func TestInitVisibilityUnknownValueRejected(t *testing.T) { -internal/cli/cli_test.go:504:func TestInitVisibilityLocalDryRunWritesNothing(t *testing.T) { -internal/cli/cli_test.go:521:func TestRejectsUnknownCommandTypo(t *testing.T) { -internal/cli/cli_test.go:531:func TestListTrackers(t *testing.T) { -internal/cli/cli_test.go:547:func TestAddTrackerWritesFilesAndMergesMCP(t *testing.T) { -internal/cli/cli_test.go:578:func TestAddTrackerShipsNoSecretLiteralAndGuidesCredentials(t *testing.T) { -internal/cli/cli_test.go:628:func TestAddTrackerIsIdempotent(t *testing.T) { -internal/cli/cli_test.go:650:func TestAddTrackerMultipleCoexist(t *testing.T) { -internal/cli/cli_test.go:674:func TestAddTrackerRejectsMissingScaffold(t *testing.T) { -internal/cli/cli_test.go:688:func TestAddTrackerRejectsUnknownTracker(t *testing.T) { -internal/cli/cli_test.go:701:func TestTopLevelHelpListsAllSubcommands(t *testing.T) { -internal/cli/cli_test.go:728:func TestSubcommandHelpPrintsFlagsAndExamples(t *testing.T) { -internal/cli/cli_test.go:769:func TestFlaglessSubcommandHelp(t *testing.T) { -internal/cli/cli_test.go:787:func TestUnknownCommandErrorPointsAtHelp(t *testing.T) { -internal/cli/cli_test.go:799:func TestUnknownFlavorErrorPointsAtHelp(t *testing.T) { -internal/cli/cli_test.go:815:func TestHelpFlagsMatchDocs(t *testing.T) { -internal/cli/cli_test.go:842:func TestUpgradeHelp(t *testing.T) { -internal/cli/cli_test.go:859:func TestUpgradeDevBuildRefusedWithoutForce(t *testing.T) { -internal/cli/cli_test.go:871:func TestUpgradeRejectsPositionalArgs(t *testing.T) { -internal/cli/cli_test.go:880:func TestVersion(t *testing.T) { -internal/cli/cli_test.go:893:func TestVersionDefaultsToDev(t *testing.T) { -internal/cli/status_test.go:52:func TestStatusSharedWhenNoBlockAnywhere(t *testing.T) { -internal/cli/status_test.go:75:func TestStatusLocalWhenBlockInGitignore(t *testing.T) { -internal/cli/status_test.go:109:func TestStatusHiddenWhenBlockInGitInfoExclude(t *testing.T) { -internal/cli/status_test.go:146:func TestStatusShadowedByGlobalWhenOnlyGlobalCarriesBlock(t *testing.T) { -internal/cli/status_test.go:189:func TestStatusPrefersLocalOverHiddenOverGlobal(t *testing.T) { -internal/cli/status_test.go:226:func TestStatusDefaultTargetIsCwd(t *testing.T) { -internal/cli/status_test.go:250:func TestStatusExplicitTargetIsResolvedToAbsolutePath(t *testing.T) { -internal/cli/status_test.go:267:func TestStatusRejectsExtraPositionalArgs(t *testing.T) { -internal/cli/status_test.go:279:func TestStatusHelp(t *testing.T) { -internal/cli/status_test.go:302:func TestStatusIgnoresGlobalLookupErrors(t *testing.T) { internal/flavors/claudecowork/flavor.go:11:func Templates() embed.FS { internal/flavors/claudecowork/flavor.go:18:func ExecutablePaths() []string { internal/flavors/claudecowork/flavor.go:25:func NextSteps(target string) string { @@ -165,11 +111,9 @@ internal/flavors/fullstack/flavor.go:12:func ExecutablePaths() []string { internal/flavors/gobackend/flavor.go:8:func Templates() embed.FS { internal/flavors/gobackend/flavor.go:12:func ExecutablePaths() []string { internal/flavors/gobackend/templates/internal/api/handlers.go:10:func NewRouter(commit, buildDate string) http.Handler { -internal/flavors/gobackend/templates/internal/api/handlers_test.go:10:func TestHealthz(t *testing.T) { internal/flavors/gocli/flavor.go:8:func Templates() embed.FS { internal/flavors/gocli/flavor.go:12:func ExecutablePaths() []string { internal/flavors/gocli/templates/internal/version/version.go:4:func String(commit, date string) string { -internal/flavors/gocli/templates/internal/version/version_test.go:5:func TestString(t *testing.T) { internal/flavors/iac/flavor.go:8:func Templates() embed.FS { internal/flavors/iac/flavor.go:17:func ExecutablePaths() []string { internal/flavors/projectmgmt/flavor.go:11:func Templates() embed.FS { @@ -178,29 +122,49 @@ internal/flavors/projectmgmt/flavor.go:23:func NextSteps(target string) string { internal/flavors/registry.go:16:type Registry struct { internal/flavors/registry.go:20:func DefaultRegistry() Registry { internal/flavors/registry.go:153:func NewRegistry(items ...Flavor) Registry { -internal/flavors/registry_test.go:18:func TestAllTemplatesParse(t *testing.T) { internal/gitconfig/gitconfig.go:27:type Runner interface { internal/gitconfig/gitconfig.go:37:type Env interface { internal/gitconfig/gitconfig.go:54:func EnsureGlobal(runner Runner, env Env, upsert upsertFunc) (string, error) { internal/gitconfig/gitconfig.go:83:func GlobalPath(runner Runner, env Env) (string, error) { internal/gitconfig/gitconfig.go:136:type OSEnv struct{} internal/gitconfig/gitconfig.go:145:func NewExecRunner() Runner { return execRunner{} } -internal/gitconfig/gitconfig_test.go:98:func TestEnsureGlobalCreatesDefaultPathAndSetsKey(t *testing.T) { -internal/gitconfig/gitconfig_test.go:121:func TestEnsureGlobalHonorsXDGConfigHome(t *testing.T) { -internal/gitconfig/gitconfig_test.go:140:func TestEnsureGlobalHonorsConfiguredExcludesFileAndDoesNotSetKey(t *testing.T) { -internal/gitconfig/gitconfig_test.go:162:func TestEnsureGlobalExpandsTildeInConfiguredPath(t *testing.T) { -internal/gitconfig/gitconfig_test.go:176:func TestEnsureGlobalAppendsToExistingFileWithoutOurBlock(t *testing.T) { -internal/gitconfig/gitconfig_test.go:198:func TestEnsureGlobalIsIdempotent(t *testing.T) { -internal/gitconfig/gitconfig_test.go:223:func TestGlobalPathDoesNotWriteOrSet(t *testing.T) { internal/gitignore/gitignore.go:56:func Block() string { internal/gitignore/gitignore.go:71:func LocalPath(target string) (string, error) { internal/gitignore/gitignore.go:83:func EnsureLocal(target string) (string, error) { internal/gitignore/gitignore.go:102:func HiddenPath(target string) (string, error) { +internal/gitignore/gitignore.go:123:func EnsureHidden(target string) (string, error) { +internal/gitignore/gitignore.go:147:func Upsert(content string) string { +internal/gitignore/gitignore.go:155:func HasBlock(content string) bool { +internal/scaffold/scaffold.go:18:type Options struct { +internal/scaffold/scaffold.go:62:func Run(ctx context.Context, opts Options) error { +internal/scaffold/scaffold.go:102:func Overlay(opts Options, fsys fs.FS, root string) error { +internal/selfupdate/github.go:20:type GitHubSource struct { +internal/selfupdate/github.go:32:func NewGitHubSource(repo string) *GitHubSource { +internal/selfupdate/selfupdate.go:36:type Release struct { +internal/selfupdate/selfupdate.go:42:type Asset struct { +internal/selfupdate/selfupdate.go:49:type Source interface { +internal/selfupdate/selfupdate.go:57:type Updater struct { +internal/selfupdate/selfupdate.go:67:func NewUpdater(src Source, out io.Writer) *Updater { +internal/selfupdate/selfupdate.go:78:type CheckResult struct { +internal/selfupdate/selfupdate.go:99:type UpgradeOptions struct { +internal/trackers/ado/ado.go:16:func Templates() embed.FS { +internal/trackers/ado/ado.go:25:func MCPServer() map[string]any { +internal/trackers/gh/gh.go:13:func Templates() embed.FS { +internal/trackers/gh/gh.go:21:func MCPServer() map[string]any { +internal/trackers/jira/jira.go:14:func Templates() embed.FS { +internal/trackers/jira/jira.go:23:func MCPServer() map[string]any { +internal/trackers/mcp.go:21:func MergeMCPServer(target, serverKey string, serverConfig map[string]any) (bool, error) { +internal/trackers/registry.go:13:type Registry struct { +internal/trackers/registry.go:18:func DefaultRegistry() Registry { +internal/trackers/registry.go:51:func NewRegistry(items ...Tracker) Registry { +internal/trackers/tracker.go:15:type Tracker struct { +testdata/golden/go-backend/internal/api/handlers.go:10:func NewRouter(commit, buildDate string) http.Handler { +testdata/golden/go-cli/internal/version/version.go:4:func String(commit, date string) string { ## Stats ``` -Total tracked files: 358 +Total tracked files: 356 ``` diff --git a/.agent/scripts/gen-codemap.sh b/.agent/scripts/gen-codemap.sh index 3935851..ac2bd1b 100755 --- a/.agent/scripts/gen-codemap.sh +++ b/.agent/scripts/gen-codemap.sh @@ -47,7 +47,10 @@ else TREE_CMD="find . -maxdepth 3 -type d -not -path '*/\.*' -not -path '*/node_modules*' -not -path '*/target*' -not -path '*/dist*' -not -path '*/clients*'" fi -# Detect a few common API-surface signals; this is intentionally rough +# Detect a few common API-surface signals; this is intentionally rough. +# Test files are excluded: their functions (Go `TestXxx`, `test_*.py`, +# `*.test.ts`) are not public API, and their bulk can push real exported +# symbols past the per-language cap and silently drop them. api_surface() { local found=0 # `sort` before `head` keeps the output stable: ripgrep's parallel @@ -65,19 +68,19 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - rg --no-heading -n '^func [A-Z]|^type [A-Z]' --type go 2>/dev/null \ + rg --no-heading -n -g '!*_test.go' '^func [A-Z]|^type [A-Z]' --type go 2>/dev/null \ | sort -t: -k1,1 -k2,2n | head -100 || true found=1 fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - rg --no-heading -n '^export (function|class|interface|type|const|enum) ' --type ts 2>/dev/null \ + rg --no-heading -n -g '!*.test.ts' -g '!*.spec.ts' -g '!*.test.tsx' -g '!*.spec.tsx' '^export (function|class|interface|type|const|enum) ' --type ts 2>/dev/null \ | sort -t: -k1,1 -k2,2n | head -100 || true found=1 fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - rg --no-heading -n '^(class |def )[A-Za-z_]' --type py 2>/dev/null \ + rg --no-heading -n -g '!test_*.py' -g '!*_test.py' '^(class |def )[A-Za-z_]' --type py 2>/dev/null \ | grep -v '^.*:def _' \ | sort -t: -k1,1 -k2,2n | head -100 || true found=1 diff --git a/internal/flavors/common/templates/.agent/scripts/gen-codemap.sh b/internal/flavors/common/templates/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100644 --- a/internal/flavors/common/templates/.agent/scripts/gen-codemap.sh +++ b/internal/flavors/common/templates/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/fullstack-agents-only/.agent/scripts/gen-codemap.sh b/testdata/golden/fullstack-agents-only/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/fullstack-agents-only/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/fullstack-agents-only/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/fullstack/.agent/scripts/gen-codemap.sh b/testdata/golden/fullstack/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/fullstack/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/fullstack/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/go-backend-agents-only/.agent/scripts/gen-codemap.sh b/testdata/golden/go-backend-agents-only/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/go-backend-agents-only/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/go-backend-agents-only/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/go-backend/.agent/CODEBASE.md b/testdata/golden/go-backend/.agent/CODEBASE.md index fbbf8a4..276b0af 100644 --- a/testdata/golden/go-backend/.agent/CODEBASE.md +++ b/testdata/golden/go-backend/.agent/CODEBASE.md @@ -28,7 +28,6 @@ _Generated by `gen-codemap.sh`. Re-run after structural changes._ ### Go internal/api/handlers.go:10:func NewRouter(commit, buildDate string) http.Handler { -internal/api/handlers_test.go:10:func TestHealthz(t *testing.T) { ## Stats diff --git a/testdata/golden/go-backend/.agent/scripts/gen-codemap.sh b/testdata/golden/go-backend/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/go-backend/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/go-backend/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/go-cli-agents-only/.agent/scripts/gen-codemap.sh b/testdata/golden/go-cli-agents-only/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/go-cli-agents-only/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/go-cli-agents-only/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ diff --git a/testdata/golden/go-cli/.agent/CODEBASE.md b/testdata/golden/go-cli/.agent/CODEBASE.md index 6c220d6..b37b1e5 100644 --- a/testdata/golden/go-cli/.agent/CODEBASE.md +++ b/testdata/golden/go-cli/.agent/CODEBASE.md @@ -28,7 +28,6 @@ _Generated by `gen-codemap.sh`. Re-run after structural changes._ ### Go internal/version/version.go:4:func String(commit, date string) string { -internal/version/version_test.go:5:func TestString(t *testing.T) { ## Stats diff --git a/testdata/golden/go-cli/.agent/scripts/gen-codemap.sh b/testdata/golden/go-cli/.agent/scripts/gen-codemap.sh index 8aabf31..3243298 100755 --- a/testdata/golden/go-cli/.agent/scripts/gen-codemap.sh +++ b/testdata/golden/go-cli/.agent/scripts/gen-codemap.sh @@ -51,6 +51,10 @@ fi # Using grep + sort keeps output deterministic across filesystems / CI runners. # (We tried ripgrep first; its directory-walk order varies between rg versions # and gitignore parsing differs subtly between environments.) +# +# Test files are excluded from the surface: their functions (Go `TestXxx`, +# `test_*.py`, `*.test.ts`) are not public API, and their bulk can push real +# exported symbols past the per-language cap and silently drop them. GREP_EXCLUDES=( --exclude-dir=.git --exclude-dir=node_modules @@ -75,7 +79,7 @@ api_surface() { fi if compgen -G "**/*.go" > /dev/null 2>&1; then echo "### Go" - grep -rEn --include='*.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ + grep -rEn --include='*.go' --exclude='*_test.go' "${GREP_EXCLUDES[@]}" '^func [A-Z]|^type [A-Z]' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -83,7 +87,7 @@ api_surface() { fi if compgen -G "**/*.ts" > /dev/null 2>&1 || compgen -G "**/*.tsx" > /dev/null 2>&1; then echo "### TypeScript" - grep -rEn --include='*.ts' --include='*.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ + grep -rEn --include='*.ts' --include='*.tsx' --exclude='*.test.ts' --exclude='*.spec.ts' --exclude='*.test.tsx' --exclude='*.spec.tsx' "${GREP_EXCLUDES[@]}" '^export (function|class|interface|type|const|enum) ' . 2>/dev/null \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \ | head -100 || true @@ -91,7 +95,7 @@ api_surface() { fi if compgen -G "**/*.py" > /dev/null 2>&1; then echo "### Python" - grep -rEn --include='*.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ + grep -rEn --include='*.py' --exclude='test_*.py' --exclude='*_test.py' "${GREP_EXCLUDES[@]}" '^(class |def )[A-Za-z_]' . 2>/dev/null \ | grep -v '^.*:def _' \ | sed 's|^\./||' \ | sort -t: -k1,1 -k2,2n \