Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .ai-context/COMMANDS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ options.
seed agent guidance, and write installer templates. `repo init` defaults new
repositories to the configured workspace root; use `--path .` for the current
checkout. Plain `repo init` writes local baseline files without committing or
pushing them; `repo init --pr` commits baseline changes on a branch, pushes to
`origin`, and opens a PR.
pushing them; `repo init --agent-ready` also seeds `AGENTS.md` and `skills.md`;
`repo init --pr` commits baseline changes on a branch, pushes to `origin`, and
opens a PR.
- `basectl <setup|check|doctor> --ci <project>` - run Base setup/check/doctor
with CI-safe defaults. It does not run project tests or create CI runners/VMs.
`setup --ci --format json` uses `output` for the compact final status and
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ and Base versions are tracked in the repo-root `VERSION` file.
- Added a bounded `copilot-setup-steps` workflow and documentation for optional
GitHub Copilot cloud-agent setup without changing normal local development or
CI behavior.
- Added `basectl repo init --agent-ready` to seed `AGENTS.md` and `skills.md`
alongside the standard repo baseline.

### Changed

Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,9 @@ inferred. Newly created GitHub repositories are private by default; pass
local baseline but does not commit or push local files. Use `--pr` on an
existing clean Git worktree to commit baseline changes on a branch, push that
branch to `origin`, and open a pull request. Use `--no-configure` to skip the
GitHub step, or rerun it later with `basectl repo configure`.
GitHub step, or rerun it later with `basectl repo configure`. Add
`--agent-ready` when a new baseline should also include `AGENTS.md` and
`skills.md` for repo-local agent workflow guidance.

Clone an existing GitHub repository into the configured workspace with:

Expand Down Expand Up @@ -680,11 +682,16 @@ basectl repo configure ~/work/example --repo basefoundry/example
Seed optional repo-local agent guidance with:

```bash
basectl repo init example --repo basefoundry/example --agent-ready
basectl repo agent-guidance ~/work/example --repo-name example
basectl repo agent-guidance ~/work/example --repo-name example --pr --dry-run
basectl repo check ~/work/example --agent-guidance
```

Use `repo init --agent-ready` for new baselines that should include agent
guidance from the first pull request. Use `repo agent-guidance` to add or repair
that optional layer in an existing repository.

Use `--pr` on `repo agent-guidance` or `repo installer-template` when the
generated helper files should go through review first. The target must be a
clean Git worktree, the GitHub repository is inferred from `origin` unless
Expand Down
10 changes: 6 additions & 4 deletions cli/bash/commands/basectl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ such command directories exist. Optional utility CLIs such as `caff` and
checkout, pass the repository name plus `--path .`; plain `repo init` does not
commit or push local files. Use `--pr` on an existing clean Git worktree to
commit baseline changes on a branch, push that branch to `origin`, and open a
pull request.
pull request. Use `--agent-ready` when the baseline should also include
`AGENTS.md` and `skills.md`.
`basectl repo clone <name-or-owner/name>` clones one existing GitHub
repository into the configured workspace, supports `--owner <owner>` for
short names, and treats matching existing checkouts as already satisfied.
Expand Down Expand Up @@ -141,9 +142,10 @@ such command directories exist. Optional utility CLIs such as `caff` and
preserves missing item field values where possible. Already-standard Projects
are left intact.
`basectl repo agent-guidance [path]` seeds optional repo-local agent guidance
files and `basectl repo check [path] --agent-guidance` verifies that optional
layer for repos that opt in. Use `--pr` when generated guidance should land
through a draft pull request instead of direct file generation.
files for existing repos, and `basectl repo check [path] --agent-guidance`
verifies that optional layer for repos that opt in. Use `--pr` when generated
guidance should land through a draft pull request instead of direct file
generation.
`basectl repo installer-template [path]` prints or writes the maintained
project installer starter script. Use `--pr` with a path to open the
generated installer template as a draft pull request.
Expand Down
94 changes: 84 additions & 10 deletions cli/bash/commands/basectl/subcommands/repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Options:
--path <path> Target path for repo init. Defaults to workspace root plus <name>.
--repo <owner/name> GitHub repository to configure.
--pr Commit the generated baseline on a branch and open a pull request.
--agent-ready Also seed repo-local agent guidance files.
--description <text> Repository description for generated README.
--copyright-holder <name> Copyright holder for generated AGPL license. Defaults to git config user.name.
--private Create a private GitHub repository when needed. This is the default.
Expand Down Expand Up @@ -102,6 +103,7 @@ configuration.
For the current checkout, pass its repository name and --path .
Plain repo init writes local baseline files but does not commit or push them.
With --pr, repo init commits baseline changes on a branch, pushes that branch to origin, and opens a pull request.
Pass --agent-ready to include AGENTS.md and skills.md with the baseline.
EOF
}

Expand Down Expand Up @@ -1539,9 +1541,15 @@ base_repo_stage_pr_files() {
}

base_repo_stage_pr_baseline_files() {
local agent_ready="${2:-0}"
local files=("${BASE_REPO_BASELINE_FILES[@]}")
local root="$1"

base_repo_stage_pr_files "$root" "repository baseline files" "${BASE_REPO_BASELINE_FILES[@]}"
if [[ "$agent_ready" == "1" ]]; then
files+=(AGENTS.md skills.md)
fi

base_repo_stage_pr_files "$root" "repository baseline files" "${files[@]}"
}

base_repo_relative_path_under_root() {
Expand Down Expand Up @@ -1612,8 +1620,9 @@ base_repo_finish_generated_pr() {

base_repo_create_baseline_pr_body() {
local name="$1"
local root="$2"
local repo="$3"
local root="$2"
local command_hint="${4:-basectl repo init $name --path $root --repo $repo --pr}"

cat <<EOF
## Summary
Expand All @@ -1627,7 +1636,7 @@ base_repo_create_baseline_pr_body() {
Generated by:

\`\`\`bash
basectl repo init $name --path $root --repo $repo --pr
$command_hint
\`\`\`
EOF
}
Expand Down Expand Up @@ -1683,6 +1692,7 @@ base_repo_print_init_github_skip_notice() {
}

base_repo_init_pr_rerun_command() {
local agent_ready="${11}"
local configure="$4"
local configure_project="$6"
local copy_project_fields_from="${10}"
Expand All @@ -1695,9 +1705,10 @@ base_repo_init_pr_rerun_command() {
local repo="$3"
local root="$2"
local command=(basectl repo init "$name" --path "$root" --repo "$repo" --pr)
shift 10
shift 11

[[ "$configure" == "1" ]] || command+=(--no-configure)
[[ "$agent_ready" == "1" ]] && command+=(--agent-ready)
[[ "$protect_default_branch" == "1" ]] || command+=(--no-protect-default-branch)
[[ "$configure_project" == "1" ]] || command+=(--no-project)
[[ -z "$project_title" ]] || command+=(--project "$project_title")
Expand All @@ -1712,6 +1723,7 @@ base_repo_init_pr_rerun_command() {
}

base_repo_finish_pr_baseline() {
local agent_ready="${8:-0}"
local body_file
local branch="$5"
local command_hint="${7:-}"
Expand All @@ -1731,7 +1743,7 @@ base_repo_finish_pr_baseline() {
return 0
fi

base_repo_stage_pr_baseline_files "$root" || return 1
base_repo_stage_pr_baseline_files "$root" "$agent_ready" || return 1
if git -C "$root" diff --cached --quiet --; then
log_info "No repository baseline changes to commit; skipping pull request creation."
return 0
Expand All @@ -1754,7 +1766,7 @@ base_repo_finish_pr_baseline() {
log_error "Failed to create a temporary pull request output file."
return 1
}
base_repo_create_baseline_pr_body "$name" "$root" "$repo" > "$body_file"
base_repo_create_baseline_pr_body "$name" "$root" "$repo" "$command_hint" > "$body_file"
gh pr create \
--repo "$repo" \
--base "$default_branch" \
Expand All @@ -1774,9 +1786,10 @@ base_repo_finish_pr_baseline() {
}

base_repo_pr_baseline_has_changes() {
local agent_ready="${2:-0}"
local root="$1"

base_repo_stage_pr_baseline_files "$root" || return 2
base_repo_stage_pr_baseline_files "$root" "$agent_ready" || return 2
if git -C "$root" diff --cached --quiet --; then
git -C "$root" reset --quiet || return 2
return 1
Expand All @@ -1785,6 +1798,51 @@ base_repo_pr_baseline_has_changes() {
return 0
}

base_repo_write_init_agent_guidance() {
local agents_existed=0
local default_branch="$3"
local dry_run="$1"
local pr_template_existed=0
local repo_name="$2"
local root="$5"
local skills_existed=0
local status=0
local summary_args=()
local validation_command="$4"

base_repo_load_agent_guidance || return 1

if [[ "$dry_run" != "1" ]]; then
[[ -e "$root/AGENTS.md" ]] && agents_existed=1
[[ -e "$root/skills.md" ]] && skills_existed=1
[[ -e "$root/.github/pull_request_template.md" ]] && pr_template_existed=1
fi

base_repo_write_agent_instructions "$dry_run" "$repo_name" "$default_branch" "$validation_command" "$root" || status=1
base_repo_write_agent_skills "$dry_run" "$repo_name" "$root" || status=1

if [[ "$dry_run" != "1" && "$status" -eq 0 ]]; then
if ((agents_existed)); then
summary_args+=(--unchanged "AGENTS.md")
else
summary_args+=(--created "AGENTS.md")
fi
if ((skills_existed)); then
summary_args+=(--unchanged "skills.md")
else
summary_args+=(--created "skills.md")
fi
if ((pr_template_existed)); then
summary_args+=(--unchanged ".github/pull_request_template.md")
else
summary_args+=(--created ".github/pull_request_template.md")
fi
base_repo_print_agent_guidance_summary "${summary_args[@]}"
fi

return "$status"
}

base_repo_check_baseline() {
local current_dir
local fix_path
Expand Down Expand Up @@ -1874,6 +1932,8 @@ base_repo_check_agent_guidance() {
}

base_repo_init() {
local agent_default_branch="main"
local agent_ready=0
local configure=1
local baseline_change_status=0
local copyright_holder=""
Expand Down Expand Up @@ -1932,6 +1992,10 @@ base_repo_init() {
create_pr=1
shift
;;
--agent-ready)
agent_ready=1
shift
;;
--description)
[[ -n "${2:-}" ]] || {
base_repo_init_usage_error "Option '--description' requires an argument."
Expand Down Expand Up @@ -2096,20 +2160,30 @@ base_repo_init() {
"$project_owner" \
"$project_schema" \
"$copy_project_fields_from" \
"$agent_ready" \
"${initiative_options[@]}"
)"
base_repo_prepare_pr_branch "$dry_run" "$root" "$pr_branch" "$default_branch" || return 1
fi

base_repo_write_baseline "$dry_run" "$name" "$description" "$copyright_holder" "$root" || return 1
if ((agent_ready)); then
if [[ -n "$default_branch" && "$default_branch" != "<default branch>" ]]; then
agent_default_branch="$default_branch"
elif [[ "$dry_run" != "1" ]]; then
agent_default_branch="$(base_repo_detect_default_branch "$root" 2>/dev/null || true)"
[[ -n "$agent_default_branch" ]] || agent_default_branch="main"
fi
base_repo_write_init_agent_guidance "$dry_run" "$name" "$agent_default_branch" "./tests/validate.sh" "$root" || return 1
fi

if ((create_pr)); then
if [[ "$dry_run" == "1" ]]; then
base_repo_finish_pr_baseline "$dry_run" "$name" "$root" "$github_repo" "$pr_branch" "$default_branch" "$pr_rerun_command"
base_repo_finish_pr_baseline "$dry_run" "$name" "$root" "$github_repo" "$pr_branch" "$default_branch" "$pr_rerun_command" "$agent_ready"
return $?
fi
if base_repo_pr_baseline_has_changes "$root"; then
base_repo_finish_pr_baseline "$dry_run" "$name" "$root" "$github_repo" "$pr_branch" "$default_branch" "$pr_rerun_command"
if base_repo_pr_baseline_has_changes "$root" "$agent_ready"; then
base_repo_finish_pr_baseline "$dry_run" "$name" "$root" "$github_repo" "$pr_branch" "$default_branch" "$pr_rerun_command" "$agent_ready"
return $?
else
baseline_change_status=$?
Expand Down
11 changes: 8 additions & 3 deletions cli/bash/commands/basectl/subcommands/repo_agent_guidance.sh
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ base_repo_print_agent_guidance_summary() {
local total=3
local unchanged=()
local unchanged_count
local unchanged_verb
local unchanged_word

while (($#)); do
Expand Down Expand Up @@ -180,13 +181,17 @@ base_repo_print_agent_guidance_summary() {
fi

created_word="files"
unchanged_verb="were"
unchanged_word="files"
[[ "$created_count" == "1" ]] && created_word="file"
[[ "$unchanged_count" == "1" ]] && unchanged_word="file"
if [[ "$unchanged_count" == "1" ]]; then
unchanged_word="file"
unchanged_verb="was"
fi

if ((created_count > 0 && unchanged_count > 0)); then
printf "Agent guidance: %d %s created, %d %s already existed and were left unchanged.\n" \
"$created_count" "$created_word" "$unchanged_count" "$unchanged_word"
printf "Agent guidance: %d %s created, %d %s already existed and %s left unchanged.\n" \
"$created_count" "$created_word" "$unchanged_count" "$unchanged_word" "$unchanged_verb"
elif ((created_count > 0)); then
printf "Agent guidance: %d %s created.\n" "$created_count" "$created_word"
else
Expand Down
2 changes: 1 addition & 1 deletion cli/bash/commands/basectl/tests/completions.bats
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ EOF
[[ "$output" == *"trust_allow_options=--workspace --manifest-sha256"* ]]
[[ "$output" == *"trust_revoke_options=--workspace"* ]]
[[ "$output" == *"repo_commands=init clone check configure agent-guidance installer-template"* ]]
[[ "$output" == *"repo_init_options=--path --repo --pr --description --copyright-holder --private --public --no-configure --no-protect-default-branch --project --project-owner --project-schema --initiative-option --copy-project-fields-from --no-project --dry-run"* ]]
[[ "$output" == *"repo_init_options=--path --repo --pr --agent-ready --description --copyright-holder --private --public --no-configure --no-protect-default-branch --project --project-owner --project-schema --initiative-option --copy-project-fields-from --no-project --dry-run"* ]]
[[ "$output" == *"repo_clone_options=--owner --path --dry-run"* ]]
[[ "$output" == *"repo_check_options=--agent-guidance"* ]]
[[ "$output" == *"repo_configure_options=--repo --no-protect-default-branch --project --project-owner --project-schema --initiative-option --copy-project-fields-from --replace-project --no-project --dry-run"* ]]
Expand Down
Loading
Loading