diff --git a/functions/_agents_init_find.fish b/functions/_agents_init_find.fish new file mode 100644 index 0000000..6f889bd --- /dev/null +++ b/functions/_agents_init_find.fish @@ -0,0 +1,44 @@ +# Copyright (C) 2026 Rootiest +# SPDX-License-Identifier: AGPL-3.0-or-later + +# SYNOPSIS +# _agents_init_find ... +# +# DESCRIPTION +# Runs find over with the prune set agents-init discovery uses, +# then applies to every entry that survives. Pruned: +# dot-directories (.git, .claude, .github -- tool state, not scoped +# project dirs), any AGENTS/ (a mirror, never a source), node_modules, +# generated-output directories (build, dist, out, target -- an +# instruction file there is a build artifact), and nested repositories, +# submodules and worktrees (their own .git marks another project). +# -mindepth 1 keeps itself, which has a .git, from pruning the +# whole walk. +# +# Shared by agents-init (instruction-file discovery) and agents-cleanup +# (symlinks into AGENTS/), so the two never disagree about which part of +# the tree belongs to the project. +# +# ARGUMENTS +# root Absolute path to the project root +# find-expression find primaries applied to every unpruned entry; must +# carry its own action (for example -print) +# +# EXIT STATUS +# 0 find completed +# 1 No root given, or find failed +# +# RETURNS +# Whatever prints. +# +# EXAMPLE +# _agents_init_find /path/to/project \( -name AGENTS.md -o -name CLAUDE.md \) -print +# _agents_init_find /path/to/project -type l -print +function _agents_init_find --argument-names root + test -n "$root"; or return 1 + find "$root" -mindepth 1 \ + -type d \( -name '.*' -o -name AGENTS -o -name node_modules \ + -o -name build -o -name dist -o -name out -o -name target \ + -o -exec test -e '{}/.git' \; \) -prune -o \ + $argv[2..] +end diff --git a/functions/agents-init.fish b/functions/agents-init.fish index bf0dfcb..d8ea2d3 100644 --- a/functions/agents-init.fish +++ b/functions/agents-init.fish @@ -5,7 +5,7 @@ # 12-ai-and-developer-tools # # DEPENDENCIES -# _agents_init_sync_instructions, _agents_repo_install_tools, _agents_repo_sync, _agents_init_ensure_gitignore +# _agents_init_find, _agents_init_sync_instructions, _agents_repo_install_tools, _agents_repo_sync, _agents_init_ensure_gitignore # # CLASSIFICATION # self-limiting(rm,mkdir,grep), bypasses-shadow(mv), manual-section(16-agent-tooling) @@ -238,22 +238,11 @@ function agents-init --description 'scaffold AGENTS/ sub-repo with agent spec fi # # Discovery stays inside this project: a non-git root (a lone # agent file in, say, ~) syncs only itself -- walking it would - # reach into every unrelated tree below. In a git root, pruned: - # any AGENTS/ (a mirror, never a source), dot-directories (.git, - # .claude, .github: tool state, not scoped project dirs), - # node_modules, generated-output directories (build, dist, out, - # target: an instruction file there is a build artifact, never a - # source -- pruned outright, before tracked-file protection would - # even be consulted), and nested repos/submodules/worktrees (their - # own .git marks another project). -mindepth 1 keeps the root - # itself, which has a .git, from pruning the whole walk. + # reach into every unrelated tree below. In a git root the walk + # uses the shared prune set; see _agents_init_find. set -l found if test $in_git -eq 1 - set found (find "$root" -mindepth 1 \ - -type d \( -name '.*' -o -name AGENTS -o -name node_modules \ - -o -name build -o -name dist -o -name out -o -name target \ - -o -exec test -e '{}/.git' \; \) -prune -o \ - \( -name AGENTS.md -o -name CLAUDE.md \) -print) + set found (_agents_init_find "$root" \( -name AGENTS.md -o -name CLAUDE.md \) -print) end set -l rels "." for f in $found diff --git a/tests/test-agents-init.fish b/tests/test-agents-init.fish index 19ab86a..1b5af41 100644 --- a/tests/test-agents-init.fish +++ b/tests/test-agents-init.fish @@ -461,5 +461,20 @@ _agents_init_path_is_protected $g1 "$g1/a[1]/AGENTS.md" set -l protected $status check "glob false-match: untracked a[1]/AGENTS.md is not protected" 1 "$protected" +echo "" +echo "== _agents_init_find: shared prune set ==" + +set -l pf (new_repo) +mkdir -p $pf/src $pf/node_modules/pkg $pf/.claude $pf/AGENTS $pf/build $pf/nested +git -C $pf/nested init -q +ln -s ../x $pf/src/link +ln -s x $pf/node_modules/pkg/link +ln -s x $pf/.claude/link +ln -s x $pf/AGENTS/link +ln -s x $pf/build/link +ln -s x $pf/nested/link +check "find: only the unpruned symlink" $pf/src/link (_agents_init_find $pf -type l -print | string join ,) +check "find: no root -> status 1" 1 (_agents_init_find ""; echo $status) + cleanup report