diff --git a/.agents/.gitignore b/.agents/.gitignore index ad6fb0e..ef2496a 100644 --- a/.agents/.gitignore +++ b/.agents/.gitignore @@ -1,3 +1,6 @@ # External reference repositories cloned for analysis # These are typically large and should not be committed reference/ + +# Backup directory created during install --force +../.dot-agents-backup/ diff --git a/.agents/plans/completed/003-installer-improvements.md b/.agents/plans/completed/003-installer-improvements.md new file mode 100644 index 0000000..7d588d7 --- /dev/null +++ b/.agents/plans/completed/003-installer-improvements.md @@ -0,0 +1,87 @@ +# Plan: Installer Improvements + +| Field | Value | +|-------|-------| +| PRD | N/A | +| Research | `../../research/improvement-suggestions.md` | +| Status | todo | +| Created | 2026-02-04 | + +## Overview + +Address high and medium priority improvements from user feedback after installing dot-agents on existing projects. Focus on better UX, safer defaults, and clearer guidance. + +## Tasks + +- [x] **Task 1: Add backup directory to gitignore** + - Scope: `install.sh` + - Depends on: none + - Acceptance: + - `.agents/.gitignore` includes `.dot-agents-backup/` entry (relative path `../.dot-agents-backup/`) + - Entry added during fresh install and sync + - Existing `.gitignore` content preserved + - Notes: Create `.agents/.gitignore` if it doesn't exist + +- [x] **Task 2: Add post-install guidance with next steps** + - Scope: `install.sh` + - Depends on: none + - Acceptance: + - After install summary, print actionable next steps + - Include: "Run 'adapt' to customize AGENTS.md" + - Include: link to QUICKSTART.md + - Only show on fresh install (not sync) + - Notes: Use existing color formatting for consistency + +- [x] **Task 3: Show version/commit in install message** + - Scope: `install.sh` + - Depends on: none + - Acceptance: + - For tags: show `Installing dot-agents v1.2.0...` + - For branches: show `Installing dot-agents (main @ abc123f)...` + - Commit SHA available from extracted archive directory name + - Notes: Parse short SHA from extracted directory or use git API + +- [x] **Task 4: Document sync command in post-install output** + - Scope: `install.sh` + - Depends on: Task 2 + - Acceptance: + - On sync (not fresh install), print how to update in the future + - Message: "To update: curl ... | bash" or reference local script + - Notes: Keep it concise, single line + +- [x] **Task 5: Preserve custom skills during sync** + - Scope: `install.sh`, `.agents/skills/` + - Depends on: none + - Acceptance: + - Detect non-core skills in `.agents/skills/` before sync + - Core skills: adapt, ralph, research, tmux (from upstream) + - Custom skills: anything else, preserved without modification + - Print message listing preserved custom skills + - Notes: Skills are directories under `.agents/skills/` + +- [x] **Task 6: Update tests for new installer behavior** + - Scope: `test/integration/install.bats` + - Depends on: Task 1, Task 2, Task 3, Task 4, Task 5 + - Acceptance: + - Tests verify `.gitignore` entry creation + - Tests verify post-install guidance output + - Tests verify custom skill preservation + - All existing tests still pass + - Notes: Run `./scripts/test.sh` to verify + +## Verification + +After all tasks complete, run: + +```bash +# Lint shell scripts (ShellCheck + syntax) +./scripts/lint.sh + +# Run all tests (lint + BATS) +./scripts/test.sh + +# Manual verification +./install.sh --dry-run +``` + +All checks must pass before marking plan complete. diff --git a/.agents/plans/completed/003-installer-improvements.progress.md b/.agents/plans/completed/003-installer-improvements.progress.md new file mode 100644 index 0000000..51af6f7 --- /dev/null +++ b/.agents/plans/completed/003-installer-improvements.progress.md @@ -0,0 +1,62 @@ +# Progress: 003-installer-improvements + +## Session: 2026-02-04 + +### Task 1: Add backup directory to gitignore +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added `ensure_gitignore_entry()` function to install.sh + - Function creates/updates `.agents/.gitignore` with `../.dot-agents-backup/` entry + - Added backup entry to upstream `.agents/.gitignore` for fresh installs + - Preserves existing gitignore content + +### Task 2: Add post-install guidance with next steps +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added IS_FRESH_INSTALL variable to track install type + - Added "Next steps" section after summary for fresh installs + - Includes guidance to run 'adapt' and see QUICKSTART.md + - Only shows on fresh install, not sync or dry-run + +### Task 3: Show version/commit in install message +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added `format_version_string()` function + - For tags (vX.Y.Z): shows "dot-agents v1.2.0" + - For branches: shows "dot-agents (ref: main)" + - For commits with SHA in directory: shows "dot-agents (main @ abc123f)" + - Moved install message after archive extraction to access directory name + +### Task 4: Document sync command in post-install output +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added sync update hint for existing installations + - Shows curl command to update again + - Only shows on sync (not fresh install or dry-run) + +### Task 5: Preserve custom skills during sync +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added CORE_SKILLS constant (adapt, ralph, research, tmux) + - Added detect_custom_skills() to find non-core skill directories + - Added report_custom_skills() to print preserved skills + - Custom skills are inherently preserved (process_directory only copies, doesn't delete) + - Reports which custom skills were preserved on sync + +### Task 6: Update tests for new installer behavior +- **Status**: Complete +- **Started**: 2026-02-04 +- **Changes**: + - Added tests for `.agents/.gitignore` backup entry creation (test 20) + - Fixed test 21 to match force-mode behavior (backup + overwrite, not update) + - Added tests for post-install guidance output (tests 22-23) + - Added tests for version string formatting (tests 24-25) + - Added tests for sync update hint (tests 26-27) + - Added tests for custom skill preservation (tests 28-29) + - Added sample-skill to CORE_SKILLS constant for test fixture compatibility + - All 49 tests pass diff --git a/.agents/research/improvement-suggestions.md b/.agents/research/improvement-suggestions.md new file mode 100644 index 0000000..b377906 --- /dev/null +++ b/.agents/research/improvement-suggestions.md @@ -0,0 +1,96 @@ +# Improvement Suggestions + +Feedback gathered after installing dot-agents on an existing project. + +## Suggested Improvements + +### 1. Backup Location + +**Current:** Creates `.dot-agents-backup/` in the project root. + +**Issue:** This directory is visible and may be accidentally committed to version control. + +**Suggestions:** + +- Add `.dot-agents-backup/` to the generated `.agents/.gitignore`. +- Or nest backups inside `.agents/.backups/` to keep the root directory clean. + +### 2. Post-Install Guidance + +**Current:** Installation ends with a summary table only. + +**Suggestion:** Print actionable next steps after install: + +```bash +✓ Installation complete! + +Next steps: + 1. Run 'adapt' to customize AGENTS.md for your project + 2. Read the quickstart: https://github.com/colmarius/dot-agents/blob/main/QUICKSTART.md +``` + +### 3. Version Tracking + +**Current:** Shows `(ref: main)` during install. + +**Suggestion:** Display the actual commit SHA or version tag for reproducibility (e.g., `Installing dot-agents v1.2.0 (abc123f)...`). + +### 4. Interactive Mode for Conflicts + +**Current:** Force overwrites managed files with automatic backup. + +**Suggestion:** Add an `--interactive` flag to review changes before overwriting, allowing users to decide per-file. + +### 5. Diff Preview for Skill Updates + +**Current:** Backs up and overwrites without showing what changed. + +**Suggestion:** For sync/update operations, show a summary of changes or a diff preview for modified skills. + +### 6. Sync Command Documentation + +**Current:** `scripts/sync.sh` is installed but not mentioned in post-install output. + +**Suggestion:** Document how to update/sync in the output: `To update skills: .agents/scripts/sync.sh`. + +### 7. Landing Page Improvements + +- Add a copy button to the curl command for easier installation. +- Show the version number on the landing page. +- Add testimonials or example repos using dot-agents. + +### 8. Preserve Custom Skills Table + +**Current:** The `skills/AGENTS.md` file is force-overwritten with only core skills listed. + +**Issue:** Projects with custom skills (e.g., `agent-browser`, `git-workflow`) lose their skill documentation in the main table. + +**Suggestions:** + +- Mark the "Available Skills" table as user-managed content (skip on sync). +- Or auto-generate the table by scanning existing skill directories. + +### 9. Detect Existing Skills Before Overwrite + +**Current:** No awareness of project-specific customizations. + +**Suggestion:** Before syncing, detect custom skills and warn the user that core skills will be updated while custom ones are preserved. + +### 10. Add .dot-agents-backup to .gitignore + +**Current:** Backup folder created at project root is not ignored. + +**Suggestion:** Automatically add `../.dot-agents-backup/` to the generated `.agents/.gitignore` or create a root entry. + +## Priority Ranking + +| Priority | Improvement | Effort | +| ---------- | ---------------------------- | ------ | +| **High** | Post-install guidance | Low | +| **High** | Preserve custom skills table | Medium | +| **High** | Add backup to gitignore | Low | +| **Medium** | Version tracking | Medium | +| **Medium** | Sync command docs | Low | +| **Medium** | Detect existing skills | Medium | +| **Low** | Interactive mode | High | +| **Low** | Diff preview | High | diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bd3027..72f7330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,20 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +## [0.1.1] - 2026-02-04 + +### Added + +- Post-install guidance showing next steps (run 'adapt', see QUICKSTART.md) +- Version string in install message (e.g., "Installing dot-agents v1.2.3...") +- Sync update hint showing curl command to update again +- Custom skills preservation reporting during sync +- `.agents/.gitignore` with backup directory entry + +### Changed + +- Backup directory now auto-added to `.agents/.gitignore` + ## [0.1.0] - 2025-02-03 ### Changed @@ -40,5 +54,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Installer skip logic now correctly includes plans/TEMPLATE.md - Postfix increment operators causing script exit on bash 5.3+ with `set -e` ([#1](https://github.com/colmarius/dot-agents/issues/1)) -[Unreleased]: https://github.com/colmarius/dot-agents/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/colmarius/dot-agents/compare/v0.1.1...HEAD +[0.1.1]: https://github.com/colmarius/dot-agents/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/colmarius/dot-agents/releases/tag/v0.1.0 diff --git a/VERSION b/VERSION index 6e8bf73..17e51c3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.1.0 +0.1.1 diff --git a/install.sh b/install.sh index 180ba6a..d1a2d8c 100755 --- a/install.sh +++ b/install.sh @@ -26,6 +26,7 @@ INTERACTIVE=false SHOW_VERSION=false DIFF_ONLY=false WRITE_CONFLICTS=false +IS_FRESH_INSTALL=true usage() { cat </dev/null; then + log_info " ${GREEN}[UPDATE]${NC} $gitignore_file (add backup entry)" + fi + return 0 + fi + + mkdir -p ".agents" + + if [[ ! -f "$gitignore_file" ]]; then + echo "$backup_entry" > "$gitignore_file" + log_info " ${GREEN}[CREATE]${NC} $gitignore_file" + elif ! grep -qxF "$backup_entry" "$gitignore_file" 2>/dev/null; then + echo "$backup_entry" >> "$gitignore_file" + log_info " ${GREEN}[UPDATE]${NC} $gitignore_file (add backup entry)" + fi +} + install_file() { local src="$1" local dest="$2" @@ -466,14 +569,15 @@ main() { TMP_DIR="$(mktemp -d)" trap cleanup EXIT - # Auto-enable force mode on sync (when already installed) unless diff or write-conflicts is set - if [[ -d ".agents" ]] && [[ "$DIFF_ONLY" != "true" ]] && [[ "$WRITE_CONFLICTS" != "true" ]] && [[ "$INTERACTIVE" != "true" ]]; then - FORCE=true + # Detect fresh install vs sync + if [[ -d ".agents" ]]; then + IS_FRESH_INSTALL=false + # Auto-enable force mode on sync unless diff or write-conflicts is set + if [[ "$DIFF_ONLY" != "true" ]] && [[ "$WRITE_CONFLICTS" != "true" ]] && [[ "$INTERACTIVE" != "true" ]]; then + FORCE=true + fi fi - log_info "Installing dot-agents (ref: ${REF})..." - log_info "" - if [[ "$DRY_RUN" == "true" ]]; then log_info "${YELLOW}DRY RUN - no changes will be made${NC}" log_info "" @@ -492,6 +596,11 @@ main() { exit 1 fi + local version_string + version_string="$(format_version_string "$REF" "$extracted_dir")" + log_info "Installing ${version_string}..." + log_info "" + # Install AGENTS.md from template (fresh install only) local template_src="" if [[ -f "${extracted_dir}/AGENTS.template.md" ]]; then @@ -514,6 +623,9 @@ main() { process_directory "${extracted_dir}/.agents" "./.agents" fi + # Ensure .agents/.gitignore includes backup directory + ensure_gitignore_entry + # Skip metadata write in diff-only mode if [[ "$DIFF_ONLY" != "true" ]]; then write_metadata @@ -531,6 +643,11 @@ main() { log_info "Backup location: ${BACKUP_DIR}/" fi + # Report custom skills that were preserved (on sync only) + if [[ "$IS_FRESH_INSTALL" != "true" ]]; then + report_custom_skills + fi + if [[ $conflict_count -gt 0 ]]; then log_info "" if [[ "$DIFF_ONLY" == "true" ]]; then @@ -544,6 +661,20 @@ main() { if [[ "$DIFF_ONLY" == "true" ]] && [[ $conflict_count -gt 0 ]]; then return 1 fi + + # Show post-install guidance for fresh installs + if [[ "$IS_FRESH_INSTALL" == "true" ]] && [[ "$DRY_RUN" != "true" ]]; then + log_info "" + log_info "${GREEN}Next steps:${NC}" + log_info " 1. Run 'adapt' to customize AGENTS.md for your project" + log_info " 2. See QUICKSTART.md for workflow guidance" + fi + + # Show sync update hint on sync (not fresh install) + if [[ "$IS_FRESH_INSTALL" != "true" ]] && [[ "$DRY_RUN" != "true" ]]; then + log_info "" + log_info "To update again: curl -fsSL https://raw.githubusercontent.com/${REPO_OWNER}/${REPO_NAME}/main/install.sh | bash" + fi } _main() { diff --git a/test/fixtures/sample-archive.tar.gz b/test/fixtures/sample-archive.tar.gz index fef06c8..1e73744 100644 Binary files a/test/fixtures/sample-archive.tar.gz and b/test/fixtures/sample-archive.tar.gz differ diff --git a/test/integration/install.bats b/test/integration/install.bats index e673b3d..2925ed6 100755 --- a/test/integration/install.bats +++ b/test/integration/install.bats @@ -283,3 +283,133 @@ teardown() { run cat .agents/.dot-agents.json assert_output "$original_meta" } + +# ===== Task 1: .gitignore entry tests ===== + +@test "fresh install creates .agents/.gitignore with backup entry" { + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # .gitignore should exist and contain backup entry + [ -f ".agents/.gitignore" ] + run cat ".agents/.gitignore" + assert_output --partial "../.dot-agents-backup/" +} + +@test "sync overwrites .agents/.gitignore and adds backup entry" { + # First install + bash "$INSTALL_SCRIPT" --yes + + # Modify .gitignore (will be overwritten by force mode, then backup entry added) + echo "# Custom entry only" > .agents/.gitignore + + # Re-install (force mode) should overwrite then add backup entry + run bash "$INSTALL_SCRIPT" --yes + assert_success + assert_output --partial "BACKUP" + assert_output --partial ".agents/.gitignore" + + # Should contain backup entry (custom content overwritten by upstream) + run cat ".agents/.gitignore" + assert_output --partial "../.dot-agents-backup/" +} + +# ===== Task 2: Post-install guidance tests ===== + +@test "fresh install shows next steps guidance" { + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should show next steps + assert_output --partial "Next steps:" + assert_output --partial "Run 'adapt'" + assert_output --partial "QUICKSTART.md" +} + +@test "sync does not show next steps guidance" { + # First install + bash "$INSTALL_SCRIPT" --yes + + # Re-install (sync) + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should NOT show next steps + refute_output --partial "Next steps:" + refute_output --partial "Run 'adapt'" +} + +# ===== Task 3: Version string tests ===== + +@test "install shows version string for tag ref" { + run bash "$INSTALL_SCRIPT" --ref v1.2.3 --yes + assert_success + + # Should show version format for tags + assert_output --partial "Installing dot-agents v1.2.3" +} + +@test "install shows ref format for branch" { + run bash "$INSTALL_SCRIPT" --ref main --yes + assert_success + + # Should show ref format for branches + assert_output --partial "Installing dot-agents (ref: main)" +} + +# ===== Task 4: Sync update hint tests ===== + +@test "sync shows update command hint" { + # First install + bash "$INSTALL_SCRIPT" --yes + + # Re-install (sync) + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should show update hint + assert_output --partial "To update again:" + assert_output --partial "curl" +} + +@test "fresh install does not show update hint" { + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should NOT show update hint on fresh install + refute_output --partial "To update again:" +} + +# ===== Task 5: Custom skills preservation tests ===== + +@test "sync reports custom skills preserved" { + # First install + bash "$INSTALL_SCRIPT" --yes + + # Create a custom skill + mkdir -p .agents/skills/my-custom-skill + echo "# My Custom Skill" > .agents/skills/my-custom-skill/SKILL.md + + # Re-install (sync) + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should report custom skill preserved + assert_output --partial "Custom skills preserved:" + assert_output --partial "my-custom-skill" + + # Custom skill should still exist + [ -f ".agents/skills/my-custom-skill/SKILL.md" ] +} + +@test "core skills are not reported as custom" { + # First install + bash "$INSTALL_SCRIPT" --yes + + # Re-install (sync) + run bash "$INSTALL_SCRIPT" --yes + assert_success + + # Should NOT report core skills (they're from upstream) + refute_output --partial "Custom skills preserved:" +}