diff --git a/.agents/README.md b/.agents/README.md index f6ec435c..940f3c81 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -1,5 +1,5 @@ # Agents Instructions -Last updated: 2026-04-08 +Last updated: 2026-05-03 ## Scope - Source of truth for agent guidance and skill locations in this repository. @@ -17,6 +17,13 @@ Last updated: 2026-04-08 - Skills must reside under `.agents/skills//SKILL.md`. - Additional instruction files should live under `.agents/` when needed. +## Response framing +- Follow the response option framing in `AGENTS.md`. +- When presenting a minimal implementation path, also offer to provide `recommended` and `full` options with clear scope and tradeoffs. + +## Docs bump cadence +- If the current branch already includes a docs bump/version entry, rerun docs-bump checks after each meaningful change to avoid missing version/changelog drift. + ## Work snapshot guidance - Local handoff file: `.agents/work-snapshot.local.md`. - Read it at session start when present to recover intent/next steps. diff --git a/.agents/skills/update-changelog/SKILL.md b/.agents/skills/update-changelog/SKILL.md index a85a9451..7993da31 100644 --- a/.agents/skills/update-changelog/SKILL.md +++ b/.agents/skills/update-changelog/SKILL.md @@ -40,11 +40,13 @@ Update the current version changelog entry without changing the version. 3. If the version exists in branch changelog (including when it is not yet merged to `main`), update that same entry in place. 4. If branch entry is missing but `main` already has that version entry, cherry-pick/recreate that entry at the top and then update it. 5. If branch and `main` both lack that version entry, stop and run [Version Bump Skill](../version-bump/SKILL.md). -6. Consolidate the entry before finalizing: merge overlapping bullets, collapse low-level implementation-only bullets into higher-level outcomes, and remove duplicates. -7. Update Added/Changed/Fixed bullets with concise, user-visible or contributor-impacting changes; keep style and tense consistent. -8. When updating an existing entry, keep the version unchanged and set the entry date to today's date (`YYYY-MM-DD`, UTC). -9. If adding more changes later without bumping a new version, update that same entry again (rewrite/refine, not append-only) and refresh the date to today's date. -10. Validate with `git diff`; run tests if code changed. +6. If this PR branch already contains one bump, keep reusing that entry for subsequent commits; do not create another version header unless explicitly requested. +7. Consolidate the entry before finalizing: merge overlapping bullets, collapse low-level implementation-only bullets into higher-level outcomes, and remove duplicates. +8. Update Added/Changed/Fixed bullets with concise, user-visible or contributor-impacting changes; keep style and tense consistent. +9. When updating an existing entry, keep the version unchanged and set the entry date to today's date (`YYYY-MM-DD`, UTC). +10. If adding more changes later without bumping a new version, update that same entry again (rewrite/refine, not append-only) and refresh the date to today's date. +11. Validate with `git diff`; run tests if code changed. +12. If this branch already has a docs bump/current-version entry, rerun docs-bump checks after each meaningful change to catch version/changelog drift early. ## Outputs - Updated `CHANGELOG.md` entry for the current version reflecting all new work. diff --git a/.agents/skills/version-bump/SKILL.md b/.agents/skills/version-bump/SKILL.md index 289acab0..d0756763 100644 --- a/.agents/skills/version-bump/SKILL.md +++ b/.agents/skills/version-bump/SKILL.md @@ -16,6 +16,12 @@ Keep the BasicSetup CLI version and changelog in sync for releases. - Automated bumps (e.g., Dependabot) are not handling this branch. - For changelog-only edits after a bump, use [Update Changelog Skill](../update-changelog/SKILL.md). +## Precedence rules +- Default to one version bump per PR branch. +- After a branch has been bumped, do not bump again for follow-up commits unless the user explicitly requests another bump or release policy requires it. +- For follow-up commits on the same PR, update the existing current-version changelog entry via [Update Changelog Skill](../update-changelog/SKILL.md). +- If a docs bump is already present on the branch, rerun docs-bump checks after each meaningful change. + ## Prerequisites - Tools: `yq`, `git`, `make` (for tests when code changes are included). - Permissions to push branch changes. @@ -34,6 +40,12 @@ Keep the BasicSetup CLI version and changelog in sync for releases. 4. Verify alignment: top changelog version matches `.BasicSetupCliVersion`; date is valid for CI validation (UTC +/- 1 day). 5. Validate changes: at minimum `git diff`; run `make test` if code changed. +## Decision table +- No bump yet on the PR branch: create a new version entry and set version files. +- Branch already has a bump for this PR: do not bump again; update that same entry. +- User explicitly requests another bump: create the next version. +- Release policy explicitly requires another bump: create the next version and document why. + ## Outputs - Updated `resources/version.yaml` with the new version (and mirrored `bsctl/static/resources/constants.yaml` during transition). - Matching `CHANGELOG.md` entry for `X.Y.Z`. diff --git a/.github/workflows/static-checks.yaml b/.github/workflows/static-checks.yaml new file mode 100644 index 00000000..14096f5a --- /dev/null +++ b/.github/workflows/static-checks.yaml @@ -0,0 +1,121 @@ +name: Static Checks + +on: + pull_request: + branches: + - main + paths: + - "**/*.sh" + - "**/*.bash" + - "**/*.zsh" + - ".github/workflows/*.yml" + - ".github/workflows/*.yaml" + push: + branches: + - main + paths: + - "**/*.sh" + - "**/*.bash" + - "**/*.zsh" + - ".github/workflows/*.yml" + - ".github/workflows/*.yaml" + +defaults: + run: + shell: bash + +jobs: + shell-static: + name: Shell static checks + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Install shellcheck, shfmt, and zsh + run: | + sudo apt-get update + sudo apt-get install -y shellcheck shfmt zsh + + - name: Collect shell file lists + id: shell-files + run: | + # Temporary exclusion: basic-setup.sh declares sh shebang but uses bash-specific syntax. + # TODO: Align basic-setup.sh with its shebang (or switch it to bash) and remove this exclusion so it is covered by shell checks again. + mapfile -t sh_files < <(git ls-files '*.sh' | grep -v '^basic-setup\.sh$' || true) + mapfile -t bash_all < <(git ls-files '*.bash' || true) + mapfile -t zsh_files < <(git ls-files '*.zsh' || true) + + # Temporary exclusions for legacy/bash completion files pending dedicated cleanup. + mapfile -t shellcheck_bash_files < <( + printf '%s\n' "${bash_all[@]}" | + grep -v '^alias/bash/git-prompt.bash$' | + grep -v '^alias/bash/kubectl-completion.bash$' || true + ) + + # Keep shfmt exclusions aligned with shellcheck for consistency. + mapfile -t shfmt_bash_files < <(printf '%s\n' "${shellcheck_bash_files[@]}" || true) + + { + echo "sh_files<> "$GITHUB_OUTPUT" + + - name: Run shellcheck + run: | + mapfile -t sh_files <<< "${{ steps.shell-files.outputs.sh_files }}" + mapfile -t bash_files <<< "${{ steps.shell-files.outputs.shellcheck_bash_files }}" + if [ "${#sh_files[@]}" -eq 0 ] && [ "${#bash_files[@]}" -eq 0 ]; then + echo "No sh/bash files found" + exit 0 + fi + if [ "${#sh_files[@]}" -gt 0 ] && [ -n "${sh_files[0]}" ]; then + shellcheck "${sh_files[@]}" + fi + if [ "${#bash_files[@]}" -gt 0 ] && [ -n "${bash_files[0]}" ]; then + shellcheck -s bash "${bash_files[@]}" + fi + + - name: Run shfmt diff check + run: | + mapfile -t sh_files <<< "${{ steps.shell-files.outputs.sh_files }}" + mapfile -t bash_files <<< "${{ steps.shell-files.outputs.shfmt_bash_files }}" + if [ "${#sh_files[@]}" -eq 0 ] && [ "${#bash_files[@]}" -eq 0 ]; then + echo "No sh/bash files found" + exit 0 + fi + if [ "${#sh_files[@]}" -gt 0 ] && [ -n "${sh_files[0]}" ]; then + shfmt -d "${sh_files[@]}" + fi + if [ "${#bash_files[@]}" -gt 0 ] && [ -n "${bash_files[0]}" ]; then + shfmt -d "${bash_files[@]}" + fi + + - name: Run zsh syntax check + run: | + mapfile -t zsh_files <<< "${{ steps.shell-files.outputs.zsh_files }}" + if [ "${#zsh_files[@]}" -eq 0 ] || [ -z "${zsh_files[0]}" ]; then + echo "No zsh files found" + exit 0 + fi + zsh -n "${zsh_files[@]}" + + actionlint: + name: actionlint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Run actionlint + uses: rhysd/actionlint@v1 diff --git a/AGENTS.md b/AGENTS.md index dba0ebfd..4cafc552 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,6 +7,8 @@ This document outlines the coding standards and best practices for AI agents and - [Skills](#skills) - [Work Snapshot Usage](#work-snapshot-usage) - [Scope Control](#scope-control) +- [Merge Conflict Resolution](#merge-conflict-resolution) +- [Response Option Framing](#response-option-framing) - [Go Standards](#go-standards) - [Bash Standards](#bash-standards) - [Documentation Standards](#documentation-standards) @@ -56,6 +58,8 @@ When implementing work tied to an issue/PR, proactively detect scope creep and p - Never create commits or push branch updates unless the user explicitly asks for a commit/push in the current session. - Staging and local validation are allowed as preparation, but commit/push is opt-in only. +- If a user states they always handle commit/push themselves, treat that as standing preference and never commit/push unless explicitly asked in that session. +- Default behavior: do not commit or push unless asked; when work appears ready to commit, proactively propose a commit message draft for the user. 1. **Detect scope creep early** - Treat newly identified, non-blocking improvements as potential follow-up scope, not automatic additions. @@ -82,6 +86,53 @@ When implementing work tied to an issue/PR, proactively detect scope creep and p --- +## Merge Conflict Resolution + +When rebasing/merging long-lived branches, preserve mainline freshness and avoid silent regressions. + +1. **Never resolve by downgrading** + - Prefer newer dependency/tool versions from `main` unless a documented compatibility, security, compliance, or operational-support issue requires pinning lower. + - Treat version decreases (actions, language/toolchain, module/dependency, CLI semver) as regressions by default. + +2. **Keep and extend changelog history** + - Never delete existing `main` changelog entries during conflict resolution. + - Keep all existing released entries intact and add branch-relevant changes to the current branch/version entry per project bump policy. + +3. **Protect release/version files** + - Resolve `resources/version.yaml` and `bsctl/static/resources/constants.yaml` to at least the latest upstream version; when conflicts occur, bump forward from upstream as needed instead of reverting to an older value. + - Do not reduce version values during conflict resolution. + +4. **Verify semantic parity after conflict resolution** + - Compare rebased branch vs `origin/main` and verify there are no unintended reversions in pinned versions, toolchain levels, or workflow actions. + - Run targeted checks affected by conflicts (for example docs/version checks when `CHANGELOG.md` or version files conflict). + +5. **Document any intentional downgrade** + - If a lower version is intentionally kept for compatibility, record the reason in the PR and changelog entry so reviewers can validate the tradeoff. + +--- + +## Response Option Framing + +When presenting implementation options, make tradeoffs explicit and easy to choose. + +1. **When a minimal path is offered, expose deeper options** + - If you present a "minimal" approach, also offer to provide "recommended" and "full" variants. + - Keep minimal scoped to acceptance criteria and immediate unblock. + +2. **Use a consistent option ladder** + - `minimal`: least change to satisfy requirements safely. + - `recommended`: balanced durability/maintainability with moderate scope. + - `full`: comprehensive hardening/completeness with larger scope. + +3. **State scope and impact per option** + - Include what changes, expected risk/noise, and validation depth. + - Call out when recommended/full would be scope expansion and require explicit user approval. + +4. **Respect explicit user direction** + - If the user picks minimal/recommended/full (or explicitly approves scope expansion), follow that direction as authoritative. + +--- + ## Go Standards ### Idiomatic Go Practices @@ -403,8 +454,11 @@ Follow [Semantic Versioning 2.0.0](https://semver.org/): 4. **Automated Bumping** - Dependabot PRs are automatically bumped via workflow - Manual PRs require manual version bump - - Every MR/PR/changeset should include a version bump and matching CHANGELOG entry unless explicitly exempted - - Always bump version before merging + - Every MR/PR should include at least one version bump and matching CHANGELOG entry unless explicitly exempted + - Default to one bump per PR branch; follow-up commits should update the existing current-version entry rather than creating another version + - Only bump again on the same PR when explicitly requested by the user or required by release policy + - If a docs bump is already present on the branch, rerun docs-bump checks after each meaningful change to reduce missed changelog/version drift + - Always ensure the branch is bumped before merging ### Example CHANGELOG Entry diff --git a/CHANGELOG.md b/CHANGELOG.md index 750e09f6..8a60d320 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), --- +## [0.1.26] - 2026-05-02 +### Added +- Added `.github/workflows/static-checks.yaml` for Phase C static analysis (`shellcheck`, `shfmt -d`, `actionlint`) in support of #320. + +### Changed +- Updated `docs/plans/bsctl-codeql-decommission-plan.md` with Phase C status and next steps for static-check stabilization before CodeQL retirement/re-scope. +- Refined static-check workflow behavior by splitting zsh syntax checks (`zsh -n`) from `shellcheck`/`shfmt` and tuning temporary bash-file exclusions for stable CI signal. +- Added merge-conflict and response-framing policy clarifications in agent guidance and skills (`AGENTS.md`, `.agents/README.md`, `.agents/skills/update-changelog/SKILL.md`, `.agents/skills/version-bump/SKILL.md`). + ## [0.1.25] - 2026-04-30 ### Changed - Bump k8s.io/kubectl from 0.35.4 to 0.36.0 diff --git a/bsctl/static/resources/constants.yaml b/bsctl/static/resources/constants.yaml index 6dc2d348..a0971e72 100644 --- a/bsctl/static/resources/constants.yaml +++ b/bsctl/static/resources/constants.yaml @@ -1,2 +1,2 @@ # BasicSetupCliVersion - constant for semantic versioning -BasicSetupCliVersion: "0.1.25" +BasicSetupCliVersion: "0.1.26" diff --git a/docs/plans/bsctl-codeql-decommission-plan.md b/docs/plans/bsctl-codeql-decommission-plan.md index f558f853..a5a92886 100644 --- a/docs/plans/bsctl-codeql-decommission-plan.md +++ b/docs/plans/bsctl-codeql-decommission-plan.md @@ -46,6 +46,10 @@ Retire remaining `bsctl` Go CLI and CodeQL dependencies without breaking release - Re-scope or remove `.github/workflows/codeql.yaml` only after replacement checks are enforced in CI. - Document rationale and replacement security posture. +Current status: + +- Added `.github/workflows/static-checks.yaml` scaffolding for `shellcheck`, `shfmt -d`, and `actionlint`. + ### Phase D: `bsctl/` retirement - Remove remaining `bsctl/` tree once dependencies and references are eliminated. @@ -61,6 +65,6 @@ Retire remaining `bsctl` Go CLI and CodeQL dependencies without breaking release ## Immediate Next Steps -1. Complete Phase B PR merge and verify workflow parity on `main`. -2. Start Phase C by adding shell/workflow static checks (`shellcheck`, `shfmt -d`, `actionlint`) in CI. -3. Reassess CodeQL scope and retire/re-scope `.github/workflows/codeql.yaml` once replacement checks are stable. +1. Validate `.github/workflows/static-checks.yaml` in CI and tune file targeting/exclusions for stable signal. +2. Reassess CodeQL scope and retire/re-scope `.github/workflows/codeql.yaml` once replacement checks are stable. +3. Update issue #320 acceptance checkboxes as Phase C milestones complete. diff --git a/resources/version.yaml b/resources/version.yaml index dd137733..6196eafb 100644 --- a/resources/version.yaml +++ b/resources/version.yaml @@ -1,2 +1,2 @@ # BasicSetupCliVersion - primary version source for releases and docs bump automation -BasicSetupCliVersion: "0.1.25" +BasicSetupCliVersion: "0.1.26"