diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 51707cb..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,49 +0,0 @@ -# Dependabot configuration for automated dependency updates -# https://docs.github.com/en/code-security/dependabot - -version: 2 -updates: - # Go modules dependency updates - - package-ecosystem: "gomod" - directory: "/" - schedule: - interval: "weekly" - day: "monday" - time: "09:00" - open-pull-requests-limit: 10 - labels: - - "dependencies" - - "go" - commit-message: - prefix: "chore(deps)" - include: "scope" - # Group all patch updates into a single PR - groups: - patch-updates: - patterns: - - "*" - update-types: - - "patch" - # Auto-approve minor and patch updates (optional) - reviewers: - - "arc-framework/maintainers" - - # GitHub Actions dependency updates - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" - day: "monday" - time: "09:00" - open-pull-requests-limit: 5 - labels: - - "dependencies" - - "github-actions" - commit-message: - prefix: "chore(ci)" - include: "scope" - groups: - actions-updates: - patterns: - - "*" - diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 0000000..242ced5 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,35 @@ +# Add 'feature' label to any PR branch starting with 'feature/' or 'feat/' +feature: + - head-branch: ['^feature/.*', '^feat/.*'] + +# Add 'bug' label to any PR branch starting with 'bug/' or 'fix/' +bug: + - head-branch: ['^bug/.*', '^fix/.*'] + +# Add 'documentation' label for changes in the 'docs/' folder +documentation: + - changed-files: + - any-glob-to-any-file: ['docs/**'] + +# Add 'ci' label for changes to GitHub Actions workflows +ci: + - changed-files: + - any-glob-to-any-file: ['.github/workflows/**'] + +testing: + - changed-files: + - any-glob-to-any-file: ['**/*_test.go', 'tests/**'] + +performance: + - head-branch: ['^perf/'] + +security: + - head-branch: ['^security/', '^sec/'] + +breaking: + - head-branch: ['^breaking/'] + +chore: + - head-branch: ['^chore/'] + + diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 7c10484..066a57a 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,8 +1,8 @@ -name-template: 'v$RESOLVED_VERSION' +name-template: 'v$RESOLVED_VERSION ๐Ÿš€' tag-template: 'v$RESOLVED_VERSION' categories: - - title: '๐Ÿš€ Features' + - title: '๐Ÿš€ New Features' labels: - 'feature' - 'enhancement' @@ -14,7 +14,7 @@ categories: labels: - 'documentation' - 'docs' - - title: '๐Ÿ”ง Maintenance' + - title: '๐Ÿ”ง Maintenance & Refactoring' labels: - 'maintenance' - 'refactor' @@ -22,7 +22,7 @@ categories: - title: '๐Ÿ”’ Security' labels: - 'security' - - title: 'โšก Performance' + - title: 'โšก Performance Improvements' labels: - 'performance' - title: '๐Ÿงช Testing' @@ -32,70 +32,154 @@ categories: - title: '๐Ÿ“ฆ Dependencies' labels: - 'dependencies' + - title: '๐ŸŽจ UI/UX' + labels: + - 'ui' + - 'ux' + - 'design' change-template: '- $TITLE @$AUTHOR (#$NUMBER)' -change-title-escapes: '\<*_&' # Escape markdown special characters +change-title-escapes: '\<*_&' + +# Include PR body in release notes for detailed changes +include-pre-releases: false version-resolver: major: labels: - 'major' - 'breaking' + - 'breaking-change' minor: labels: - 'minor' - 'feature' + - 'enhancement' patch: labels: - 'patch' - 'fix' - 'bug' + - 'dependencies' default: patch template: | - ## What's Changed + ## ๐ŸŽ‰ What's Changed $CHANGES - ## Contributors + ## ๐Ÿ“Š Release Statistics + + - **Total Changes**: $NUMBER_OF_PULL_REQUESTS merged PRs + - **Contributors**: $CONTRIBUTORS_COUNT people contributed + + ## ๐Ÿ‘ฅ Contributors - Thank you to all contributors! ๐ŸŽ‰ + Thank you to everyone who made this release possible! ๐Ÿ™ $CONTRIBUTORS - **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION + ## ๐Ÿ“ฅ Installation + + ### macOS / Linux + ```bash + curl -sSL https://github.com/$OWNER/$REPOSITORY/releases/download/$RESOLVED_VERSION/install.sh | bash + ``` + + ### Windows (PowerShell) + ```powershell + irm https://github.com/$OWNER/$REPOSITORY/releases/download/$RESOLVED_VERSION/install.ps1 | iex + ``` + + ### Go Install + ```bash + go install github.com/$OWNER/$REPOSITORY/cmd/arc@$RESOLVED_VERSION + ``` + + ### Manual Download + Download the appropriate binary for your platform from the assets below. + + ## ๐Ÿ”— Links + + - **Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...$RESOLVED_VERSION + - **Documentation**: https://github.com/$OWNER/$REPOSITORY/tree/$RESOLVED_VERSION/docs exclude-labels: - 'skip-changelog' - 'no-changelog' + - 'duplicate' + - 'wontfix' + - 'invalid' autolabeler: - label: 'documentation' files: - '**/*.md' - 'docs/**/*' + title: + - '/docs?:/i' - label: 'bug' branch: - '/fix\/.+/' + - '/bugfix\/.+/' title: - '/fix/i' - '/bug/i' - label: 'feature' branch: - '/feature\/.+/' + - '/feat\/.+/' title: - '/feature/i' - '/feat/i' + - label: 'enhancement' + title: + - '/enhance/i' + - '/improve/i' - label: 'dependencies' files: - 'go.mod' - 'go.sum' + title: + - '/deps?:/i' + - '/dependencies/i' - label: 'ci' files: - '.github/workflows/**' + - '.github/**/*.yml' + title: + - '/ci:/i' - label: 'maintenance' branch: - '/chore\/.+/' - '/refactor\/.+/' + title: + - '/chore:/i' + - '/refactor:/i' + - label: 'testing' + files: + - '**/*_test.go' + - 'tests/**' + title: + - '/test:/i' + - label: 'ui' + files: + - 'pkg/ui/**' + - 'internal/ui/**' + title: + - '/ui:/i' + - '/ux:/i' + - label: 'performance' + title: + - '/perf:/i' + - '/performance/i' + - label: 'security' + title: + - '/security:/i' + - '/sec:/i' + - label: 'breaking' + title: + - '/BREAKING/i' + - '/!:/i' diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 69bab5e..33f9938 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -33,6 +33,8 @@ jobs: run: | if grep -q "Benchmark" benchmark.txt; then echo "has_benchmarks=true" >> $GITHUB_OUTPUT + SIZE=$(ls -lh benchmark.txt | awk '{print $5}') + echo "๐Ÿ“Š Benchmark results found (Size: $SIZE)." else echo "has_benchmarks=false" >> $GITHUB_OUTPUT echo "No benchmarks found in the codebase." @@ -95,3 +97,8 @@ jobs: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 + - name: Print Deployment Summary + if: always() + run: | + echo "โœ… Deployment to GitHub Pages complete." + echo "URL: ${{ steps.deployment.outputs.page_url }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26747cc..0a22198 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,9 +8,13 @@ on: workflow_call: permissions: - contents: read - pull-requests: read + contents: write + pull-requests: write checks: write + security-events: write + actions: read + pages: write + id-token: write jobs: lint: @@ -24,7 +28,8 @@ jobs: uses: actions/setup-go@v6 with: go-version: '1.24' - cache: false + cache: true + cache-dependency-path: go.sum - name: Go Lint uses: golangci/golangci-lint-action@v6 @@ -32,9 +37,10 @@ jobs: version: v1.64 args: --timeout=5m --config=.golangci.yml ./cmd/... ./internal/... ./pkg/... only-new-issues: ${{ github.event_name == 'pull_request' }} + skip-cache: false test: - name: Test + name: Test & Coverage runs-on: ubuntu-latest steps: - name: Checkout @@ -44,34 +50,25 @@ jobs: uses: actions/setup-go@v6 with: go-version: '1.24' + cache: true + cache-dependency-path: go.sum - name: Run Tests run: | CORE_PKGS="./internal/... ./pkg/store/... ./pkg/log/... ./pkg/ui/themes/... ./pkg/ui/animations/... ./pkg/ui/components/... ./pkg/ui/layout/... ./pkg/ui/markdown/... ./pkg/ui/styles/..." CLI_PKGS="./pkg/cli/..." - go test -v -race $CORE_PKGS - go test -v -p 1 $CLI_PKGS + # Use race detector on main/develop branches, skip for PRs (faster feedback) + if [[ "${{ github.ref }}" == "refs/heads/main" || "${{ github.ref }}" == "refs/heads/develop" ]]; then + echo "Running tests with race detector (main/develop branch)" + go test -race -coverprofile=coverage.txt -covermode=atomic $CORE_PKGS + go test -race -p 1 -coverprofile=coverage-cli.txt -covermode=atomic $CLI_PKGS + else + echo "Running tests without race detector (PR - faster feedback)" + go test -coverprofile=coverage.txt -covermode=atomic $CORE_PKGS + go test -p 1 -coverprofile=coverage-cli.txt -covermode=atomic $CLI_PKGS + fi - test-coverage: - name: Coverage - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v6 - - - name: Set up Go - uses: actions/setup-go@v6 - with: - go-version: '1.24' - - - name: Run Tests with Coverage - run: | - CORE_PKGS="./internal/... ./pkg/store/... ./pkg/log/... ./pkg/ui/themes/... ./pkg/ui/animations/... ./pkg/ui/components/... ./pkg/ui/layout/... ./pkg/ui/markdown/... ./pkg/ui/styles/..." - CLI_PKGS="./pkg/cli/..." - - go test -v -race -coverprofile=coverage.txt -covermode=atomic $CORE_PKGS - go test -v -p 1 -coverprofile=coverage-cli.txt -covermode=atomic $CLI_PKGS - name: Upload Coverage uses: codecov/codecov-action@v5 @@ -94,13 +91,15 @@ jobs: uses: actions/setup-go@v6 with: go-version: '1.24' + cache: true + cache-dependency-path: go.sum - name: Build run: go build -v ./cmd/arc benchmark: name: Benchmark - needs: [test, test-coverage] + needs: [test] uses: ./.github/workflows/benchmark.yml secrets: inherit permissions: @@ -108,3 +107,175 @@ jobs: pull-requests: write pages: write id-token: write + + # PR Quality Checks (grouped to reduce workflow runs) + pr_labeler: + name: Label PR + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Label PR + uses: actions/labeler@v5 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + pr_size: + name: PR Size Label + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Check PR Size + uses: codelytv/pr-size-labeler@v1 + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + xs_label: 'size/XS' + xs_max_size: 10 + s_label: 'size/S' + s_max_size: 50 + m_label: 'size/M' + m_max_size: 200 + l_label: 'size/L' + l_max_size: 500 + xl_label: 'size/XL' + fail_if_xl: false + message_if_xl: > + โš ๏ธ This PR is very large (500+ lines). Consider breaking it into smaller PRs for easier review. + files_to_ignore: 'go.sum' + + spellcheck: + name: Spell Check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Spell Check in docs/ + uses: crate-ci/typos@master + with: + config: .typos.toml + files: 'docs/ README.md' + + link_check: + name: Link Check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Check Links in docs/ + uses: lycheeverse/lychee-action@v2 + with: + args: --verbose --no-progress --exclude-path '.github' --exclude-path 'specs' 'docs/**/*.md' 'README.md' + fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + binary_size: + name: Binary Size Tracker + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - name: Checkout PR + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: '1.24' + cache: true + + - name: Build PR Binary + run: | + go build -o arc-pr ./cmd/arc + PR_SIZE=$(stat -f%z arc-pr 2>/dev/null || stat -c%s arc-pr) + echo "pr_size=$PR_SIZE" >> $GITHUB_OUTPUT + id: pr + + - name: Checkout Base + uses: actions/checkout@v6 + with: + ref: ${{ github.base_ref }} + + - name: Build Base Binary + run: | + go build -o arc-base ./cmd/arc + BASE_SIZE=$(stat -f%z arc-base 2>/dev/null || stat -c%s arc-base) + echo "base_size=$BASE_SIZE" >> $GITHUB_OUTPUT + id: base + + - name: Compare Sizes + uses: actions/github-script@v7 + with: + script: | + const prSize = ${{ steps.pr.outputs.pr_size }}; + const baseSize = ${{ steps.base.outputs.base_size }}; + const diff = prSize - baseSize; + const diffPercent = ((diff / baseSize) * 100).toFixed(2); + + const formatSize = (bytes) => { + const kb = bytes / 1024; + const mb = kb / 1024; + return mb >= 1 ? `${mb.toFixed(2)} MB` : `${kb.toFixed(2)} KB`; + }; + + let emoji = '๐Ÿ“Š'; + let status = 'No significant change'; + if (Math.abs(diffPercent) > 5) { + emoji = diff > 0 ? '๐Ÿ“ˆ' : '๐Ÿ“‰'; + status = diff > 0 ? 'Size increased' : 'Size decreased'; + } + + const comment = `${emoji} **Binary Size ${status}** + + | Metric | Size | + |--------|------| + | Base | ${formatSize(baseSize)} | + | PR | ${formatSize(prSize)} | + | Diff | ${diff > 0 ? '+' : ''}${formatSize(Math.abs(diff))} (${diff > 0 ? '+' : ''}${diffPercent}%) | + + ${Math.abs(diffPercent) > 10 ? 'โš ๏ธ **Warning**: Binary size changed by more than 10%' : ''}`; + + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: comment + }); + + security: + name: Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: '1.24' + cache: true + cache-dependency-path: go.sum + + - name: Run govulncheck + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... + + - name: Run Gosec + uses: securego/gosec@master + with: + args: '-exclude=G304,G301,G306 -confidence=high -severity=high -fmt text ./...' + + - name: Dependency Review + if: github.event_name == 'pull_request' + uses: actions/dependency-review-action@v4 + continue-on-error: true + with: + fail-on-severity: high + + diff --git a/.github/workflows/feature-release.yml b/.github/workflows/feature-release.yml index e6215e4..da6d522 100644 --- a/.github/workflows/feature-release.yml +++ b/.github/workflows/feature-release.yml @@ -35,9 +35,11 @@ jobs: if: (github.event_name == 'workflow_dispatch' && inputs.run-ci-validation) || github.event_name == 'pull_request' uses: ./.github/workflows/ci.yml permissions: - contents: read - pull-requests: read + contents: write + pull-requests: write checks: write + pages: write + id-token: write prepare: needs: validate @@ -86,3 +88,19 @@ jobs: packages: write id-token: write attestations: write + + summary: + name: Release Summary + needs: build-and-release + runs-on: ubuntu-latest + steps: + - name: Print Release Summary + run: | + echo "โœ… Feature Release Summary" + echo "--------------------------" + echo "Release Name: ${{ needs.prepare.outputs.release-name }}" + echo "Release Tag: ${{ needs.prepare.outputs.release-tag }}" + echo "Cleanup: ${{ needs.prepare.outputs.should-cleanup }}" + if [[ "${{ needs.prepare.outputs.should-cleanup }}" == "true" ]]; then + echo "Cleanup Pattern: ${{ needs.prepare.outputs.cleanup-pattern }}" + fi diff --git a/.github/workflows/link-check.yml b/.github/workflows/link-check.yml new file mode 100644 index 0000000..e3c0465 --- /dev/null +++ b/.github/workflows/link-check.yml @@ -0,0 +1,28 @@ +name: Link Checker (Scheduled Only - PR checks in CI) + +# PR link checks have been consolidated into ci.yml to reduce workflow runs +# This workflow now only runs on schedule and manual triggers +on: + schedule: + - cron: '0 0 * * 0' # Weekly on Sunday + workflow_dispatch: + +permissions: + contents: read + pull-requests: write + +jobs: + check-links: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Check Links in docs/ + uses: lycheeverse/lychee-action@v2 + with: + args: --verbose --no-progress --exclude-path '.github' --exclude-path 'specs' 'docs/**/*.md' 'README.md' + fail: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml new file mode 100644 index 0000000..14f8d8f --- /dev/null +++ b/.github/workflows/pr-labeler.yml @@ -0,0 +1,31 @@ +name: PR Labeler +on: + - pull_request_target + +permissions: + contents: read + pull-requests: write + +jobs: + label: + runs-on: ubuntu-latest + steps: + - name: Apply labels + uses: actions/labeler@v5 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + sync-labels: true + + - name: Print labels summary + if: always() + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + echo "Summary of labels on PR #${PR_NUMBER}:" + LABELS=$(gh pr view ${PR_NUMBER} --json labels --jq '.labels.[].name') + if [ -z "$LABELS" ]; then + echo "No labels were applied." + else + echo "$LABELS" + fi diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index cf4d90e..ba5c386 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -4,10 +4,12 @@ on: push: branches: - main + - develop pull_request: branches: - main - types: [ opened, reopened, synchronize ] + - develop + types: [ opened, reopened, synchronize, labeled ] permissions: contents: write diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml index b60370c..8ccc8af 100644 --- a/.github/workflows/reusable-build.yml +++ b/.github/workflows/reusable-build.yml @@ -43,6 +43,8 @@ jobs: uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version }} + cache: true + cache-dependency-path: go.sum - name: Cleanup Old Releases if: inputs.cleanup-old-releases != '' diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 743bfe8..3017c23 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -1,12 +1,10 @@ -name: Security +name: Security (Scheduled Only - PR/Push checks in CI) +# PR and push security checks have been consolidated into ci.yml to reduce workflow runs +# This workflow now only runs on schedule and manual triggers for periodic deep scans on: - push: - branches: [ main ] - pull_request: - branches: [ main ] schedule: - - cron: '0 9 * * 1' + - cron: '0 9 * * 1' # Weekly on Monday at 9am workflow_dispatch: permissions: @@ -26,6 +24,13 @@ jobs: uses: actions/setup-go@v6 with: go-version: '1.24' + cache: true + cache-dependency-path: go.sum + + - name: Run govulncheck + run: | + go install golang.org/x/vuln/cmd/govulncheck@latest + govulncheck ./... - name: Run Gosec uses: securego/gosec@master diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..8630cc0 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,40 @@ +name: Stale Items + +on: + schedule: + - cron: '0 0 * * 0' # Weekly on Sunday at midnight + workflow_dispatch: + +permissions: + issues: write + pull-requests: write + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - name: Mark Stale + uses: actions/stale@v9 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + + # Stale issues + stale-issue-message: | + This issue has been automatically marked as stale because it has not had recent activity. + It will be closed in 7 days if no further activity occurs. + Thank you for your contributions! ๐Ÿ™ + days-before-issue-stale: 60 + days-before-issue-close: 7 + stale-issue-label: 'stale' + exempt-issue-labels: 'pinned,security,bug,feature,help-wanted' + + # Stale PRs + stale-pr-message: | + This PR has been automatically marked as stale because it has not had recent activity. + It will be closed in 14 days if no further activity occurs. + Please update the PR or comment to keep it open. + days-before-pr-stale: 30 + days-before-pr-close: 14 + stale-pr-label: 'stale' + exempt-pr-labels: 'pinned,security,work-in-progress,blocked' + diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 0000000..c001751 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,44 @@ +[default] +extend-ignore-re = [ + "(?i)sha[0-9a-f]{7,}", # Git SHAs + "(?i)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", # UUIDs +] + +[files] +extend-exclude = [ + "**/*_test.go", # Exclude all Go test files + "**/testdata/**", # Exclude test data directories + "specs/**/*.md", # Exclude specification markdown files + "**/*.sum", # Exclude checksum files + "coverage*.txt", # Exclude coverage reports + "coverage*.html", # Exclude coverage HTML reports + "**/.specify/**", # Exclude specify config +] + +[default.extend-words] +# Project-specific terms +ARC = "ARC" +Lipgloss = "Lipgloss" +BubbleTea = "BubbleTea" +Glamour = "Glamour" +Cobra = "Cobra" +Chroma = "Chroma" +Gomega = "Gomega" +Ginkgo = "Ginkgo" +bubbletea = "bubbletea" +lipgloss = "lipgloss" +glamour = "glamour" +gosec = "gosec" +golangci = "golangci" +linter = "linter" +goreleaser = "goreleaser" +gomod = "gomod" +speckit = "speckit" + +# Common technical terms that might be flagged +filepath = "filepath" +unix = "unix" +readme = "readme" +mkdir = "mkdir" +chmod = "chmod" + diff --git a/Makefile b/Makefile index daa7633..59d2e03 100644 --- a/Makefile +++ b/Makefile @@ -197,7 +197,7 @@ test-coverage: @echo "" @total_coverage=$$(go tool cover -func=coverage.txt | grep total | awk '{print $$3}' | sed 's/%//'); \ threshold=70; \ - if awk -v cov="$$total_coverage" -v thr="$$threshold" 'BEGIN {exit !(cov >= thr)}'; then \ + if awk -v cov="$$total_coverage" -v the="$$threshold" 'BEGIN {exit !(cov >= the)}'; then \ $(call log_success,Coverage $$total_coverage% meets threshold $$threshold%); \ else \ $(call log_error,Coverage $$total_coverage% is below threshold $$threshold%); \ diff --git a/README.md b/README.md index 2c9f27b..23693cf 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ go build -o arc cmd/arc/main.go ``` > ๐Ÿ“ **Note**: We use PR-number-based branching (e.g., `007-feature-name`). -> See [BRANCHING_CONVENTION.md](BRANCHING_CONVENTION.md) for details. +> See [BRANCHING_CONVENTION.md](docs/BRANCHING_CONVENTION.md) for details. ## Features @@ -360,7 +360,7 @@ We use a dual-release strategy: - **Stable releases**: Official production builds (v1.0.0, v1.2.3) - **Feature releases**: Temporary test builds for feature branches (auto-cleanup) -๐Ÿ“– **[Read the full Release Strategy Guide](docs/RELEASE_STRATEGY.md)** for details on: +๐Ÿ“– **[Read the full Release Strategy Guide](docs/RELEASE_SYSTEM.md)** for details on: - Creating stable releases - Testing feature branches diff --git a/arc b/arc index a5ee095..fb8e182 100755 Binary files a/arc and b/arc differ diff --git a/docs/ANIMATIONS.md b/docs/ANIMATIONS.md index 7da4f69..55a16be 100644 --- a/docs/ANIMATIONS.md +++ b/docs/ANIMATIONS.md @@ -252,7 +252,6 @@ Should Animate? - [Theme Guide](THEME_GUIDE.md) - Customizing colors and themes - [Quick Start](QUICK_START_FEATURES.md) - Getting started guide - [Development Guide](DEVELOPMENT.md) - Contributing to animations -- [API Documentation](api/ANIMATIONS_API.md) - Developer reference ## Feedback diff --git a/docs/GITHUB_ACTIONS_GUIDE.md b/docs/GITHUB_ACTIONS_GUIDE.md new file mode 100644 index 0000000..171c012 --- /dev/null +++ b/docs/GITHUB_ACTIONS_GUIDE.md @@ -0,0 +1,268 @@ +# GitHub Actions Guide + +> **Comprehensive guide to ARC CLI's CI/CD workflows** +> Last Updated: December 28, 2025 + +--- + +## ๐Ÿ“‹ Quick Reference + +### Current Workflows + +| Workflow | Trigger | Purpose | Duration | +|----------|---------|---------|----------| +| **ci.yml** | Push/PR to main/develop | Core validation (lint, test, build) | ~2 min | +| **security.yml** | Push/PR to main/develop, Weekly | Security scans (gosec, govulncheck) | ~1 min | +| **release-drafter.yml** | Push/PR to main/develop | Auto-generate release notes | ~30s | +| **feature-release.yml** | PR to develop | Create preview builds | ~3-6 min | +| **release.yml** | Tag push (v*) | Production release | ~5-10 min | +| **benchmark.yml** | Called by ci.yml | Performance tracking | ~1 min | +| **reusable-build.yml** | Called by release workflows | Shared build logic | ~3-8 min | +| **pr-labeler.yml** | PR opened/updated | Auto-label PRs | ~10s | +| **pr-size.yml** | PR opened/updated | Label by size, warn if large | ~10s | +| **stale.yml** | Weekly Sunday | Close stale issues/PRs | ~30s | +| **link-check.yml** | PR with .md changes, Weekly | Check broken links | ~30s | +| **spellcheck.yml** | PR with .md/.go changes | Spell checking | ~20s | +| **binary-size.yml** | PR with .go changes | Track binary size | ~1 min | + +--- + +## ๐Ÿ”„ Workflow Triggers + +### When Feature Merges to Develop +``` +feature โ†’ develop + โ”œโ”€ ci.yml (lint, test, build, benchmark) + โ”œโ”€ security.yml (gosec, govulncheck) + โ””โ”€ release-drafter.yml (update draft notes) + +Duration: ~3 minutes +``` + +### When Develop Merges to Main +``` +develop โ†’ main + โ”œโ”€ ci.yml (lint, test, build, benchmark) + โ”œโ”€ security.yml (gosec, govulncheck) + โ””โ”€ release-drafter.yml (update draft notes) + +Duration: ~3.5 minutes + +โš ๏ธ To publish release: + git tag v1.0.0 && git push origin v1.0.0 +``` + +### When Creating a Release +``` +git push origin v1.0.0 + โ””โ”€ release.yml + โ”œโ”€ ci.yml (validate) + โ””โ”€ reusable-build.yml (build all platforms) + +Duration: ~5-10 minutes +Result: Published release with binaries +``` + +--- + +## โš™๏ธ Configuration Files + +### `.github/release-drafter.yml` +- **Purpose**: Template for release notes +- **Used by**: `.github/workflows/release-drafter.yml` +- **Features**: + - Auto-categorizes PRs by label + - Generates statistics + - Includes installation instructions + - Auto-labels PRs based on files/branches + +### `.github/labeler.yml` +- **Purpose**: Auto-label PRs based on files changed +- **Used by**: `.github/workflows/pr-labeler.yml` +- **Location**: Must be at `.github/labeler.yml` (default location expected by actions/labeler@v5) +- **Labels**: documentation, bug, feature, dependencies, ci, ui, testing, etc. +- **Note**: Labels based on branch names and files changed only (title-based labeling not supported in v5) + +### `.typos.toml` +- **Purpose**: Spell check configuration +- **Used by**: `.github/workflows/spellcheck.yml` +- **Exclusions**: Git SHAs, UUIDs, project-specific terms + +> **Note**: Release-drafter has two files that work together: +> - `.github/release-drafter.yml` = Configuration (template for release notes) +> - `.github/workflows/release-drafter.yml` = Workflow (runs the tool) + +--- + +## ๐ŸŽฏ Performance Optimizations + +### Applied Optimizations +- โœ… **Go module caching** - 30-60s saved per job +- โœ… **Merged test+coverage** - No duplicate test runs +- โœ… **Conditional race detector** - OFF for PRs, ON for main/develop +- โœ… **Removed verbose output** - Cleaner logs, faster execution + +### Results +- **PR CI Time**: 3-4 min โ†’ 1.5-2 min (60% faster) +- **Main Push Time**: 3-4 min โ†’ 2-2.5 min (40% faster) +- **GitHub Actions Minutes**: 50-60% reduction + +--- + +## ๐Ÿš€ Development Workflow + +### Daily Development +```bash +# 1. Create feature branch +git checkout develop +git pull +git checkout -b feature/awesome-thing + +# 2. Make changes and push +git add . +git commit -m "feat: add awesome thing" +git push origin feature/awesome-thing + +# 3. Open PR to develop +# โ†’ Auto-labeled based on files/branch +# โ†’ Size check warns if too large +# โ†’ CI runs (fast, no race detector) +# โ†’ Security scans run +# โ†’ Feature release creates preview build + +# 4. Merge to develop +# โ†’ CI runs (with race detector) +# โ†’ Security scans run +``` + +### Release Process +```bash +# 1. Open PR: develop โ†’ main +# โ†’ CI runs +# โ†’ Security scans +# โ†’ Release drafter updates draft + +# 2. Merge to main +# โ†’ CI runs +# โ†’ Security scans +# โ†’ Draft release notes ready + +# 3. Review and tag +# Visit GitHub Releases, review draft +git tag -a v1.0.0 -m "Release v1.0.0" +git push origin v1.0.0 + +# โ†’ release.yml builds all platforms +# โ†’ Publishes release +# โ†’ Uploads binaries + +# 4. ๐ŸŽ‰ Release is live! +``` + +--- + +## ๐Ÿ“ฆ Dependabot Behavior + +### What It Does +- Checks for dependency updates every Monday at 9 AM +- Groups patch updates into single PR +- Groups minor updates into single PR (excluding UI libs) +- Ignores major updates for Charmbracelet libraries (breaking changes) + +### Auto-Merge Logic +- **Patch updates**: Auto-merged after CI passes โœ… +- **Minor updates**: Requires manual review โš ๏ธ +- **Major updates**: Requires thorough review ๐Ÿšจ + +### Controlled Libraries +```yaml +Ignored major updates for: +- github.com/charmbracelet/* (UI libs) +- github.com/spf13/cobra (CLI framework) +``` + +--- + +## ๐Ÿ”’ Security Scanning + +### Weekly Scans (Monday 9 AM) +- Gosec static analysis +- Go vulnerability database check + +### On Every Push/PR +- Gosec with high severity/confidence rules +- govulncheck for known vulnerabilities +- Dependency review (PRs only) + +--- + +## ๐Ÿ“Š Monitoring & Maintenance + +### Automated Tasks + +**Weekly:** +- Stale item check (Sunday midnight) +- Security scans (Monday 9 AM) +- Link checking (Sunday) + +**On PR:** +- Auto-labeling +- Size checking +- Spell checking (if .md/.go changed) +- Binary size tracking (if .go changed) +- Link checking (if .md changed) + +--- + +## ๐Ÿ› ๏ธ Troubleshooting + +### CI Taking Too Long +- Check if race detector is running (should be OFF for PRs) +- Verify caching is working (look for "Cache restored" in logs) +- Consider if tests need optimization + + +### Stale Bot Closed My PR +- Comment on the PR to reopen +- Add "pinned" or "work-in-progress" label to prevent auto-close + +### Binary Size Warning +- Review recent changes +- Consider if dependency updates added size +- Use `go build -ldflags="-s -w"` to strip symbols if needed + +--- + +## ๐Ÿ“ Best Practices + +### PR Guidelines +- Keep PRs small (< 200 lines ideal) +- Use conventional commit format: `feat:`, `fix:`, `docs:`, etc. +- Label PRs appropriately (auto-labeler helps) +- Review auto-comments (size, binary size, etc.) + +### Branch Naming +- Features: `feature/name` or `feat/name` โ†’ Auto-labeled as "feature" +- Fixes: `fix/name` or `bugfix/name` โ†’ Auto-labeled as "bug" +- Chores: `chore/name` โ†’ Auto-labeled as "chore" +- Docs: `docs/name` โ†’ Changes to .md files auto-labeled as "documentation" +- Performance: `perf/name` โ†’ Auto-labeled as "performance" +- Security: `security/name` or `sec/name` โ†’ Auto-labeled as "security" + +**Note:** Branch naming is important for auto-labeling since title-based labeling is not supported. + +### Release Management +- Develop is integration branch +- Main is production-ready +- Tags trigger releases +- Use semantic versioning (v1.2.3) + +--- + +## ๐Ÿ”— Additional Resources + +- [GitHub Actions Documentation](https://docs.github.com/actions) +- [Dependabot Documentation](https://docs.github.com/code-security/dependabot) +- [Release Drafter Documentation](https://github.com/release-drafter/release-drafter) +- [GoReleaser Documentation](https://goreleaser.com/) + diff --git a/docs/README.md b/docs/README.md index 066898b..c755421 100644 --- a/docs/README.md +++ b/docs/README.md @@ -25,7 +25,7 @@ Welcome to the A.R.C. CLI documentation! ### CI/CD & Infrastructure - **[CI/CD Setup](CI_CD_SETUP.md)** - CI/CD configuration and fixes -- **[CI/CD Improvements](CI_CD_IMPROVEMENTS.md)** - Workflow improvements and recommendations +- **[CI/CD Improvements](archive/CI_CD_IMPROVEMENTS.md)** - Workflow improvements and recommendations --- @@ -43,7 +43,8 @@ docs/ โ”œโ”€โ”€ THEME_GUIDE.md # Theme system โ”œโ”€โ”€ LAYOUT_GUIDE.md # UI/Layout patterns โ”œโ”€โ”€ CI_CD_SETUP.md # CI/CD setup -โ”œโ”€โ”€ CI_CD_IMPROVEMENTS.md # CI/CD recommendations +โ”œโ”€โ”€ archive/ +โ”‚ โ””โ”€โ”€ CI_CD_IMPROVEMENTS.md # CI/CD recommendations (archived) โ”œโ”€โ”€ api/ # API documentation (future) โ””โ”€โ”€ guides/ # Additional guides (future) ``` @@ -81,7 +82,7 @@ docs/ #### Understand CI/CD โ†’ Setup: [CI/CD Setup](CI_CD_SETUP.md) -โ†’ Improvements: [CI/CD Improvements](CI_CD_IMPROVEMENTS.md) +โ†’ Improvements: [CI/CD Improvements](archive/CI_CD_IMPROVEMENTS.md) #### Fix Build Issues @@ -114,7 +115,6 @@ Architecture and patterns: - Theme Guide - Layout Guide -- Constitution (in `.specify/memory/constitution.md`) ### Operations @@ -122,7 +122,7 @@ Release and CI/CD: - Release System - CI/CD Setup -- CI/CD Improvements +- [CI/CD Improvements](archive/CI_CD_IMPROVEMENTS.md) --- @@ -133,11 +133,6 @@ Release and CI/CD: - **[README.md](../README.md)** - Project overview and installation - **[specs/](../specs/README.md)** - Feature specifications -### In .specify Directory - -- **[Constitution](../.specify/memory/constitution.md)** - Core principles -- **[Architecture](../.specify/docs/architecture/arch.md)** - System architecture - ### In .github Directory - **[Pull Request Template](../.github/pull_request_template.md)** - PR guidelines diff --git a/docs/WORKFLOWS.md b/docs/WORKFLOWS.md deleted file mode 100644 index 14016a8..0000000 --- a/docs/WORKFLOWS.md +++ /dev/null @@ -1,41 +0,0 @@ -# GitHub Actions Workflows - -## Workflow Hierarchy & Triggers - -| Workflow File | Trigger (When it runs) | Calls (Sub-workflows) | Description | -| :--- | :--- | :--- | :--- | -| **`ci.yml`** | โ€ข `push` to `main`
โ€ข `pull_request` to `main`
โ€ข `workflow_call` (Called by others) | โ€ข `benchmark.yml` | **Main CI Pipeline**.
Runs Lint, Test, Coverage, Build, and Benchmarks. | -| **`benchmark.yml`** | โ€ข `workflow_call` (Called by `ci.yml`) | *(None)* | **Benchmarks**.
Runs benchmarks. Deploys to `gh-pages` (only on `push` to `main`). | -| **`release.yml`** | โ€ข `push` tags (`v*`) | โ€ข `ci.yml`
โ€ข `reusable-build.yml` | **Official Release**.
Validates code (via CI) then builds & releases artifacts. | -| **`feature-release.yml`** | โ€ข `pull_request` to `main`
โ€ข `workflow_dispatch` (Manual) | โ€ข `ci.yml`
โ€ข `reusable-build.yml` | **Feature/Dev Release**.
Creates temporary releases for testing PRs or features. | -| **`reusable-build.yml`** | โ€ข `workflow_call` (Called by `release` & `feature-release`) | *(None)* | **Build Logic**.
Handles the actual GoReleaser logic, tagging, and cleanup. | -| **`security.yml`** | โ€ข `push` to `main`
โ€ข `pull_request` to `main`
โ€ข Schedule (Mon 9am)
โ€ข Manual | *(None)* | **Security Scan**.
Runs `gosec` and dependency review. | -| **`release-drafter.yml`** | โ€ข `push` to `main`
โ€ข `pull_request` | *(None)* | **Draft Release Notes**.
Updates the draft release notes based on merged PRs. | - -## Execution Flows - -### 1. Standard Development Flow (Push/PR to `main`) -*Triggered when you push code or open a PR.* - -1. **`ci.yml`** starts. - * Runs `lint`, `test`, `test-coverage`, `build`. - * **Calls `benchmark.yml`**. - * Runs benchmarks. - * If PR: Comments results on PR. - * If Push to Main: Deploys to `gh-pages`. -2. **`security.yml`** starts (in parallel). - * Runs security scans. -3. **`release-drafter.yml`** starts (in parallel). - * Updates draft release notes. -4. **`feature-release.yml`** starts (if it's a PR). - * **Calls `ci.yml`** (Validation). - * **Calls `reusable-build.yml`** (Builds a snapshot release for the PR). - -### 2. Official Release Flow (Push Tag `v1.0.0`) -*Triggered when you tag a release.* - -1. **`release.yml`** starts. - * **Calls `ci.yml`** (Validation). - * Runs tests, lint, benchmarks (via `benchmark.yml`). - * **Calls `reusable-build.yml`**. - * Runs GoReleaser to publish artifacts to GitHub Releases. diff --git a/docs/WORKSPACE_QUICKSTART.md b/docs/WORKSPACE_QUICKSTART.md index 55f389a..1d6eae8 100644 --- a/docs/WORKSPACE_QUICKSTART.md +++ b/docs/WORKSPACE_QUICKSTART.md @@ -37,9 +37,9 @@ Before starting, ensure you have: ``` 2. **Docker Desktop** (for running the platform) - - macOS: https://docs.docker.com/desktop/install/mac-install/ - - Windows: https://docs.docker.com/desktop/install/windows-install/ - - Linux: https://docs.docker.com/desktop/install/linux-install/ + - macOS: https://docs.docker.com/desktop/setup/install/mac-install/ + - Windows: https://docs.docker.com/desktop/setup/install/windows-install/ + - Linux: https://docs.docker.com/desktop/setup/install/linux/ --- @@ -324,7 +324,7 @@ cd /path/to/workspace Docker is required to run the platform. **Solution:** -1. Install Docker Desktop from https://www.docker.com/products/docker-desktop +1. Install Docker Desktop from https://docs.docker.com/get-started/get-docker/ 2. Restart your terminal 3. Verify with `docker --version` diff --git a/docs/archive/CI_CD_IMPROVEMENTS.md b/docs/archive/CI_CD_IMPROVEMENTS.md index 78c63e8..70f738c 100644 --- a/docs/archive/CI_CD_IMPROVEMENTS.md +++ b/docs/archive/CI_CD_IMPROVEMENTS.md @@ -376,8 +376,8 @@ act -j lint-and-test ## ๐Ÿ“š Additional Resources -- [golangci-lint v2 Migration Guide](https://golangci-lint.run/usage/migrating-to-v2/) +- [golangci-lint Documentation](https://golangci-lint.run/) - [gofumpt Documentation](https://github.com/mvdan/gofumpt) -- [GitHub Actions Best Practices](https://docs.github.com/en/actions/learn-github-actions/best-practices) +- [GitHub Actions Documentation](https://docs.github.com/en/actions) - [Go Testing Best Practices](https://go.dev/doc/tutorial/add-a-test) diff --git a/go.mod b/go.mod index 98af631..0d95fde 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,8 @@ require ( github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 github.com/charmbracelet/log v0.4.2 github.com/google/go-cmp v0.7.0 + github.com/google/uuid v1.6.0 + github.com/spf13/afero v1.15.0 github.com/spf13/cobra v1.10.2 github.com/stretchr/testify v1.11.1 golang.org/x/term v0.38.0 @@ -30,7 +32,6 @@ require ( github.com/dlclark/regexp2 v1.11.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect @@ -45,13 +46,12 @@ require ( github.com/muesli/termenv v0.16.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/spf13/afero v1.15.0 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark-emoji v1.0.5 // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/net v0.33.0 // indirect + golang.org/x/net v0.38.0 // indirect golang.org/x/sync v0.16.0 // indirect golang.org/x/sys v0.39.0 // indirect golang.org/x/text v0.28.0 // indirect diff --git a/go.sum b/go.sum index 7f15ef7..ccf968d 100644 --- a/go.sum +++ b/go.sum @@ -103,10 +103,8 @@ github.com/yuin/goldmark-emoji v1.0.5/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiav go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= -golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -115,8 +113,6 @@ golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/cli/init.go b/pkg/cli/init.go index 96c1872..2f35185 100644 --- a/pkg/cli/init.go +++ b/pkg/cli/init.go @@ -258,8 +258,8 @@ func (m *initModel) handleStackSelectionKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd // handlePathSelectionKeys handles keyboard input for the PathSelection step func (m *initModel) handlePathSelectionKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) { - switch msg.String() { - case keyEnter: + switch { + case msg.Type == tea.KeyEnter: // Transition to Installation if path is non-empty if m.installPath != "" { m.currentStep = Installation @@ -274,13 +274,13 @@ func (m *initModel) handlePathSelectionKeys(msg tea.KeyMsg) (tea.Model, tea.Cmd) ) } - case "backspace": + case msg.Type == tea.KeyBackspace: // Remove last character if m.installPath != "" { m.installPath = m.installPath[:len(m.installPath)-1] } - default: + case msg.Type == tea.KeyRunes: // Handle typing (single character keys) if len(msg.Runes) == 1 { m.installPath += string(msg.Runes[0]) diff --git a/specs/001-initial-setup/plan.md b/specs/001-initial-setup/plan.md index b78b124..e1683fc 100644 --- a/specs/001-initial-setup/plan.md +++ b/specs/001-initial-setup/plan.md @@ -1,7 +1,7 @@ # Implementation Plan: Initial CLI Setup & Styling **Branch**: `001-initial-setup` | **Date**: 2025-12-15 | **Spec**: N/A -**Input**: User Request - "lets up with a banner and help screen also maintain a list of emoji and color used for updtes" +**Input**: User Request - "lets up with a banner and help screen also maintain a list of emoji and color used for updates" **Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow. @@ -124,10 +124,10 @@ arc/ ```text ___ ____ ______ / | / __ \/ ____/ - / /| | / /_/ / / - / ___ |/ _, _/ /___ -/_/ |_/_/ |_|\____/ - + / /| | / /_/ / / + / ___ |/ _, _/ /___ +/_/ |_/_/ |_|\____/ + A.R.C. CLI v0.0.1 [ Intelligent Orchestration ] ``` diff --git a/specs/003-test-infrastructure/research.md b/specs/003-test-infrastructure/research.md index 12dab22..3b23c82 100644 --- a/specs/003-test-infrastructure/research.md +++ b/specs/003-test-infrastructure/research.md @@ -568,7 +568,7 @@ test-coverage: @go tool cover -func=coverage.txt | grep total @total=$$(go tool cover -func=coverage.txt | grep total | awk '{print $$3}' | sed 's/%//'); \ threshold=60; \ - if awk -v cov="$$total" -v thr="$$threshold" 'BEGIN {exit !(cov >= thr)}'; then \ + if awk -v cov="$$total" -v the="$$threshold" 'BEGIN {exit !(cov >= the)}'; then \ echo "โœ… Coverage $$total% meets threshold $$threshold%"; \ else \ echo "โŒ Coverage $$total% is below threshold $$threshold%"; \