diff --git a/README.md b/README.md index 6d702cb..9871ea8 100644 --- a/README.md +++ b/README.md @@ -56,104 +56,11 @@ brew-change --help - **Revision Support**: Advanced handling of Homebrew revision numbers - **Performance Optimized**: 75% faster than original with intelligent caching -### Upgrade behavior +A few pointers into the docs — the README stays lean on purpose: -`brew-change -u` defaults only to packages whose fresh release evidence produced no risk signal. Packages marked **attention** or **unknown** are never bulk-selected. Before any upgrade, brew-change previews the exact named package list with Homebrew, then asks for immediate confirmation. Homebrew can still act on dependencies or dependents shown in that preview. - -In a pipe or other non-interactive environment, brew-change prints guidance and never starts an upgrade. - -### Breaking-change verdict (`-b`) - -`brew-change -b` processes every outdated package and ends with a verdict that answers the only question a `-b` run has: are there any breaking packages or none? The verdict uses the same honest three-state assessment as the `-u` dashboard, computed from the evidence the run already fetched: - -``` -Verdict: 4 attention · 2 no-signal · 19 unknown - -Breaking changes (2) - abseil 20260526.0 → 20260817.0 - absl::void_t is now deprecated; users should use C++17 std::void_t… - nnn 5.2 → 5.3 - removed support for the legacy plugin interface -Major version transitions (1) - vercel 58.9.0 → 59.1.4 -No risk signal found (2) -Unknown (19) — no usable release notes; review individually -``` - -When nothing matches, the run says so explicitly ("No breaking-change patterns or major version transitions detected across N packages.") while still disclosing the unknown count — packages without release notes are never reported as clean. Piped output is identical to the terminal base render (`NO_COLOR` changes nothing). - -### First run - -On an interactive `brew-change -u` run you will see a one-line hint on stderr: brew-change checks your outdated packages, shows what changed for each (`r` review), and only upgrades what you explicitly confirm — nothing runs until you approve the exact plan. No account or configuration is needed, and quitting (`q`) changes nothing. The hint is never printed in pipes or scripts, and it is not stored anywhere. - -### Changed defaults (v1.14.0) - -`brew-change -u` on a terminal now runs the interactive dashboard by default instead of the plain prompt flow: review each package's evidence provenance read-only (`r`), stage an explicit per-package selection (`s`), upgrade the no-signal set (`u`/Enter), or quit (`q`). - -```bash -brew-change -u # dashboard is now the default on a terminal -brew-change -u --plain # previous prompt flow (or BREW_CHANGE_PLAIN=1) -``` - -Escape hatches, in precedence order (`--plain` flag > `BREW_CHANGE_PLAIN=1` environment variable > default dashboard): - -- `--plain` (or `BREW_CHANGE_PLAIN=1`, e.g. in an rc file) restores the previous prompt flow. -- `--dashboard` and `BREW_CHANGE_DASHBOARD=1`, the pre-v1.14.0 opt-ins, are accepted as documented no-ops. - -Piped or redirected runs are unchanged: plain deterministic output, no prompts, no upgrades, and the view flags do not switch views. - -### Evidence caching and re-entry - -Every evidence fetch (GitHub API, npm registry, scraped release pages) goes through one HTTP response cache under `~/.cache/brew-change/http/`, so a re-run after quitting the dashboard reuses earlier responses instead of re-probing. The dashboard's review shows where each package's evidence came from and how fresh it is; rows served from cache say so, and quitting with a staged selection prints a one-line hint on the terminal about re-running. - -```bash -brew-change -u --fresh # re-probe all evidence this run (clears only the HTTP cache) -``` - -`--fresh` removes and recreates only the HTTP response cache; the GitHub breaking-change patterns, the brew-info cache, and everything else are preserved. The HTTP cache is bounded (at most 512 entries / 100 MiB, oldest entries pruned first), never stores authentication tokens (cache keys use a SHA-256-derived token fingerprint instead), and authenticated responses are partitioned away from anonymous ones. Failed probes are never cached (a "no notes" result must not freeze); instead, a package whose release-notes probe chain concluded nothing is remembered for 10 minutes so immediate re-runs skip that chain — a successful chain clears the memo instantly. - -### Accessibility - -Output meaning never depends on color or emoji: text labels (like `[breaking]` and the dashboard group headers) always carry the full classification, and any emoji is strictly additive decoration on a terminal. The base render — piped output, `NO_COLOR=1`, screen readers, copy-paste — is identical by construction. - -```bash -export NO_COLOR=1 # no-color convention: also suppresses decorative emoji -export BREW_CHANGE_NO_EMOJI=1 # explicit no-emoji opt-out (labels unchanged) -export BREW_CHANGE_STATIC_PROGRESS=1 # plain "stage n/N" progress line, no spinner animation -``` - -`BREW_CHANGE_STATIC_PROGRESS=1` keeps the progress lifecycle (TTY-only drawing, cleared line before the dashboard, restored terminal state) but replaces the animated spinner with a static line that updates only when the count changes. - -### Assessment export - -`brew-change export` prints the last assessment run data to stdout as JSON. External tools like [brew-usage](https://github.com/shrwnsan/brew-usage) can consume this to integrate brew-change's assessment knowledge without coupling to its internal data formats. - -```bash -brew-change export # Print last assessment as JSON to stdout -``` - -The export is written automatically at the end of any assessment run (`-u` or `-b`) to `~/.brew-change/last-assessment.json` with a stable, versioned schema designed for external consumers: - -```json -{ - "schema_version": 1, - "generated_at": "2026-08-20T12:34:56Z", - "packages": [ - { - "name": "node", - "display_name": "node", - "kind": "formula", - "installed_version": "22.6.0", - "available_version": "22.8.0", - "classification": "attention", - "matched_signals": ["major-version-transition"], - "retrieval_status": "fresh" - } - ] -} -``` - -The export includes package names, versions, classifications (attention/no-signal/unknown), and matched signals while excluding internal implementation details and large payloads. Consumers should gate on `schema_version` and treat missing or unsupported schema versions as non-events (never errors). See [docs/tasks-005-assessment-export-surface.md](docs/tasks-005-assessment-export-surface.md) for the full consumer contract and schema design. +- **The trusted update workflow** — upgrade behavior, the `-b` verdict, first-run behavior, dashboard defaults, evidence caching & re-entry, accessibility modes: [docs/trusted-update.md](docs/trusted-update.md) +- **Assessment export** — the versioned JSON feed for external tools (brew-usage): [docs/assessment-export.md](docs/assessment-export.md) +- **Configuration** — every environment variable in one reference: [docs/configuration.md](docs/configuration.md) ## 📦 Installation @@ -223,14 +130,10 @@ rm -rf ~/.cache/brew-change/* ## 📈 Recent Updates -- **Unreleased**: `brew-change -b` ends with an honest verdict summary (attention split into breaking changes and major version transitions, no-signal and unknown counts, all-clear line that never claims safe) -- **Unreleased trusted-update foundation**: Honest three-state assessments, canonical cask identities, exact package previews, final confirmation, deterministic tests, signal-safe terminal cleanup, and a strict evidence URL policy -- **v1.11.0–v1.11.5**: Made `-u` interactive by default, added `--dry-run`, and refined prompt/spinner behavior -- **v1.10.0–v1.10.1**: Improved interactive upgrade UX and ensured Homebrew receives `--yes` -- **v1.9.0–v1.9.2**: Removed prompt timeouts and simplified prompt formatting -- **v1.8.0–v1.8.8**: Added selective upgrades and iteratively hardened `/dev/tty` prompt handling and animation -- **v1.7.0**: Applied the post-refactor code-review fixes -- **v1.6.0**: Added positional multi-package support +- **v1.20.0**: Negative probe cache — immediate re-runs skip concluded no-notes probe chains (10-minute memo) +- **v1.19.0**: SELECT arrow-key navigation with stage-all (`a`); single action line; Enter no longer silently quits when nothing is preselected; subtractive post-upgrade refresh (no more full re-probe after upgrading) +- **v1.18.x**: `-b` verdict summary (attention split into breaking changes and major transitions, all-clear that never claims safe); pattern-precision fixes; npm→GitHub notes fallback; assessment export in CI +- **v1.15.0–v1.17.0**: Trusted-update workflow waves — first-run guidance, plain-language remediation, accessibility modes, evidence cache & re-entry, `brew-change export` → **Full changelog**: [CHANGELOG.md](CHANGELOG.md) diff --git a/docs/README.md b/docs/README.md index d4b9d8a..5446c00 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,33 +1,37 @@ # brew-change Documentation -## 📚 Essential Reading +## 📖 Guides -### [Technical Documentation](technical-documentation.md) ⭐ -**Comprehensive guide** - Architecture, features, use cases, and configuration +- **[The Trusted Update Workflow](trusted-update.md)** — upgrade behavior, the `-b` verdict, first run, dashboard defaults, evidence caching & re-entry, accessibility modes +- **[Assessment Export](assessment-export.md)** — the versioned JSON feed for external tools (schema + consumer contract) +- **[Package Types](package-types.md)** — GitHub, npm, third-party taps, hybrid packages, docs-repository pattern +- **[Configuration](configuration.md)** — every environment variable in one reference +- **[Troubleshooting](../README.md#-troubleshooting)** — quick fixes live in the README -### [Package Types](package-types.md) -**Package support details** - GitHub, npm, third-party taps, and hybrid packages +## 📚 Reference -## 🔧 Performance & Optimization +- **[Technical Documentation](technical-documentation.md)** — comprehensive feature and architecture guide +- **[Architecture](architecture.md)** — modular `lib/` structure and processing pipeline +- **[Performance](performance.md)** — benchmarks and optimization notes -### [Performance Benchmarks](performance.md) -**Speed and efficiency** - Benchmarks and optimization details +## 🛠️ Development & Planning -### [Configuration Guide](configuration.md) -**Customization** - Environment variables and settings +Active PRDs, task graphs, and ratified decision records (research-NNN): -## 🏗️ Development Resources +- [PRD 003 — Trusted Update Workflow](dev/prd-003-trusted-update-workflow.md) and its [task graph](dev/tasks-003-trusted-update-workflow.md) +- [Tasks 004 — `-b` verdict summary + LLM triage](dev/tasks-004-b-verdict-summary-llm-triage.md) (Task 0/1 shipped; Task 2 parked — see [research-009](dev/research-009-llm-triage.md)) +- [Tasks 005 — Assessment Export Surface](dev/tasks-005-assessment-export-surface.md) (shipped; the export's design record) +- Decision records: [research-004](dev/research-004-cli-default-compatibility.md) · [research-005](dev/research-005-assessment-record-contract.md) · [research-006](dev/research-006-progress-event-contract.md) · [research-007](dev/research-007-dashboard-actions.md) · [research-008](dev/research-008-evidence-cache-resume.md) · [research-009](dev/research-009-llm-triage.md) · [research-010](dev/research-010-native-app-dd.md) +- [Novice usability session kit](dev/novice-checks-t3.4.1.md) -### [Architecture Overview](architecture.md) -**System design** - Modular structure and processing pipeline +## 🗄️ Archive -### [Implementation Guide](self-implementation-guide.md) -**Build it yourself** - Step-by-step implementation guide +Superseded and historical records, preserved as-is: -## 📋 Project Background - -### [Migration Background](migration-background.md) -**Project history** - Why brew-change was created - -### [Roadmap](standalone-roadmap.md) -**Future plans** - Upcoming features and development direction \ No newline at end of file +- [TypeScript migration PRD](archive/prd-001-typescript-migration.md) · [task breakdown](archive/tasks-001-typescript-migration.md) · [refactor assessment](archive/eval-001-typescript-refactor-assessment.md) — evaluated and shelved (Bash stays) +- [Multi-package support PRD](archive/prd-002-multi-package-support.md) — shipped in v1.6.0 +- [Standalone roadmap](archive/standalone-roadmap.md) — the v1.4.0-era project vision (superseded by the PRD/task era) +- [Migration background](archive/migration-background.md) — dotfiles → standalone history +- [Performance comparison](archive/performance-comparison.md) — 2025-12 benchmark record +- [Self-implementation guide](archive/self-implementation-guide.md) — pre-implementation design essay +- [Phase 1 implementation plan](archive/superpowers-phase-1-plan.md) — executed agent plan diff --git a/docs/eval-001-typescript-refactor-assessment.md b/docs/archive/eval-001-typescript-refactor-assessment.md similarity index 100% rename from docs/eval-001-typescript-refactor-assessment.md rename to docs/archive/eval-001-typescript-refactor-assessment.md diff --git a/docs/migration-background.md b/docs/archive/migration-background.md similarity index 100% rename from docs/migration-background.md rename to docs/archive/migration-background.md diff --git a/docs/performance-comparison.md b/docs/archive/performance-comparison.md similarity index 100% rename from docs/performance-comparison.md rename to docs/archive/performance-comparison.md diff --git a/docs/prd-001-typescript-migration.md b/docs/archive/prd-001-typescript-migration.md similarity index 99% rename from docs/prd-001-typescript-migration.md rename to docs/archive/prd-001-typescript-migration.md index ecc4987..18bac30 100644 --- a/docs/prd-001-typescript-migration.md +++ b/docs/archive/prd-001-typescript-migration.md @@ -727,7 +727,7 @@ Error: Node.js required. Install: brew install node **Related Documents:** - [eval-001-typescript-refactor-assessment.md](./eval-001-typescript-refactor-assessment.md) - Initial evaluation -- [architecture.md](./architecture.md) - Current architecture +- [architecture.md](../architecture.md) - Current architecture - [tasks-001-typescript-migration.md](./tasks-001-typescript-migration.md) - Detailed task breakdown --- diff --git a/docs/prd-002-multi-package-support.md b/docs/archive/prd-002-multi-package-support.md similarity index 100% rename from docs/prd-002-multi-package-support.md rename to docs/archive/prd-002-multi-package-support.md diff --git a/docs/self-implementation-guide.md b/docs/archive/self-implementation-guide.md similarity index 100% rename from docs/self-implementation-guide.md rename to docs/archive/self-implementation-guide.md diff --git a/docs/standalone-roadmap.md b/docs/archive/standalone-roadmap.md similarity index 100% rename from docs/standalone-roadmap.md rename to docs/archive/standalone-roadmap.md diff --git a/docs/superpowers/plans/2026-07-28-trusted-update-phase-1.md b/docs/archive/superpowers-phase-1-plan.md similarity index 99% rename from docs/superpowers/plans/2026-07-28-trusted-update-phase-1.md rename to docs/archive/superpowers-phase-1-plan.md index 04d7dc8..930f360 100644 --- a/docs/superpowers/plans/2026-07-28-trusted-update-phase-1.md +++ b/docs/archive/superpowers-phase-1-plan.md @@ -8,7 +8,7 @@ **Tech Stack:** Bash 4+, jq, curl, Homebrew CLI, ShellCheck, GitHub Actions, Python 3 standard-library PTY tests. -**Source of scope:** [Phase 1 task graph](../../tasks-003-trusted-update-workflow.md#5-phase-1--trust-foundation) and [approved PRD](../../prd-003-trusted-update-workflow.md). +**Source of scope:** [Phase 1 task graph](../dev/tasks-003-trusted-update-workflow.md#5-phase-1--trust-foundation) and [approved PRD](../dev/prd-003-trusted-update-workflow.md). --- diff --git a/docs/tasks-001-typescript-migration.md b/docs/archive/tasks-001-typescript-migration.md similarity index 100% rename from docs/tasks-001-typescript-migration.md rename to docs/archive/tasks-001-typescript-migration.md diff --git a/docs/assessment-export.md b/docs/assessment-export.md new file mode 100644 index 0000000..70ab3c6 --- /dev/null +++ b/docs/assessment-export.md @@ -0,0 +1,48 @@ +# Assessment Export + +`brew-change export` prints the last assessment run data to stdout as JSON. +External tools like [brew-usage](https://github.com/shrwnsan/brew-usage) can +consume this to integrate brew-change's assessment knowledge without +coupling to its internal data formats. + +```bash +brew-change export # Print last assessment as JSON to stdout +``` + +The export is written automatically at the end of any assessment run (`-u` +or `-b`) to `~/.brew-change/last-assessment.json` with a stable, versioned +schema designed for external consumers: + +```json +{ + "schema_version": 1, + "generated_at": "2026-08-20T12:34:56Z", + "packages": [ + { + "name": "node", + "display_name": "node", + "kind": "formula", + "installed_version": "22.6.0", + "available_version": "22.8.0", + "classification": "attention", + "matched_signals": ["major-version-transition"], + "retrieval_status": "fresh" + } + ] +} +``` + +The export includes package names, versions, classifications +(attention/no-signal/unknown), and matched signals while excluding internal +implementation details and large payloads. + +## Consumer contract + +- Gate on `schema_version`; treat missing or unsupported schema versions as + non-events (never errors). +- A missing export file is a non-event, not a failure. +- The internal `assessment.jsonl` pipeline format is explicitly **not** + public API — consume the export only. + +The full schema design and design rationale live in +[dev/tasks-005-assessment-export-surface.md](dev/tasks-005-assessment-export-surface.md). diff --git a/docs/configuration.md b/docs/configuration.md index 44bed6f..e25053c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -54,6 +54,21 @@ export BREW_CHANGE_DEBUG=1 export BREW_CHANGE_DOCS_REPO=1 ``` +### Accessibility and Output Modes + +Output meaning never depends on color or emoji — text labels always carry +the full classification. These variables only change presentation: + +```bash +export NO_COLOR=1 # no-color convention: also suppresses decorative emoji +export BREW_CHANGE_NO_EMOJI=1 # explicit no-emoji opt-out (labels unchanged) +export BREW_CHANGE_STATIC_PROGRESS=1 # plain "stage n/N" progress line, no spinner animation +export BREW_CHANGE_PLAIN=1 # -u: previous prompt flow instead of the dashboard +``` + +See [trusted-update.md](trusted-update.md) for how these interact with the +dashboard and the `-b` verdict. + ### Internal Variables The following variables are used internally by brew-change and are not intended for direct user configuration: diff --git a/docs/novice-checks-t3.4.1.md b/docs/dev/novice-checks-t3.4.1.md similarity index 100% rename from docs/novice-checks-t3.4.1.md rename to docs/dev/novice-checks-t3.4.1.md diff --git a/docs/prd-003-trusted-update-workflow.md b/docs/dev/prd-003-trusted-update-workflow.md similarity index 100% rename from docs/prd-003-trusted-update-workflow.md rename to docs/dev/prd-003-trusted-update-workflow.md diff --git a/docs/research-004-cli-default-compatibility.md b/docs/dev/research-004-cli-default-compatibility.md similarity index 100% rename from docs/research-004-cli-default-compatibility.md rename to docs/dev/research-004-cli-default-compatibility.md diff --git a/docs/research-005-assessment-record-contract.md b/docs/dev/research-005-assessment-record-contract.md similarity index 100% rename from docs/research-005-assessment-record-contract.md rename to docs/dev/research-005-assessment-record-contract.md diff --git a/docs/research-006-progress-event-contract.md b/docs/dev/research-006-progress-event-contract.md similarity index 100% rename from docs/research-006-progress-event-contract.md rename to docs/dev/research-006-progress-event-contract.md diff --git a/docs/research-007-dashboard-actions.md b/docs/dev/research-007-dashboard-actions.md similarity index 100% rename from docs/research-007-dashboard-actions.md rename to docs/dev/research-007-dashboard-actions.md diff --git a/docs/research-008-evidence-cache-resume.md b/docs/dev/research-008-evidence-cache-resume.md similarity index 100% rename from docs/research-008-evidence-cache-resume.md rename to docs/dev/research-008-evidence-cache-resume.md diff --git a/docs/research-009-llm-triage.md b/docs/dev/research-009-llm-triage.md similarity index 100% rename from docs/research-009-llm-triage.md rename to docs/dev/research-009-llm-triage.md diff --git a/docs/research-010-native-app-dd.md b/docs/dev/research-010-native-app-dd.md similarity index 100% rename from docs/research-010-native-app-dd.md rename to docs/dev/research-010-native-app-dd.md diff --git a/docs/tasks-003-trusted-update-workflow.md b/docs/dev/tasks-003-trusted-update-workflow.md similarity index 99% rename from docs/tasks-003-trusted-update-workflow.md rename to docs/dev/tasks-003-trusted-update-workflow.md index bf82331..1aa6d80 100644 --- a/docs/tasks-003-trusted-update-workflow.md +++ b/docs/dev/tasks-003-trusted-update-workflow.md @@ -894,7 +894,7 @@ Acceptance: **Writes:** utils/config, evidence producers/display, launcher flag, dashboard quit path, tests/docs -Acceptance (per ratified docs/research-008-evidence-cache-resume.md): +Acceptance (per ratified docs/dev/research-008-evidence-cache-resume.md): - One `$CACHE_DIR/http/` raw-response cache boundary covers validated JSON, non-empty text, and GitHub requests; analysis always re-runs over cached bodies. - Endpoint-class TTLs distinguish low-volatility exact GitHub resources (24h) from mutable collections, npm, and scraped/branch-based content (≤1h). @@ -924,7 +924,7 @@ Acceptance: **Complexity:** M **Owner:** Maintainer/product review -Session record (kit: docs/novice-checks-t3.4.1.md, Environment B — deterministic demo: node 22→25 attention, bat no-signal, wrk rate-limited unknown; driven under a PTY against the Wave 1+2 build; all five scenarios exited 0, read-only): +Session record (kit: docs/dev/novice-checks-t3.4.1.md, Environment B — deterministic demo: node 22→25 attention, bat no-signal, wrk rate-limited unknown; driven under a PTY against the Wave 1+2 build; all five scenarios exited 0, read-only): - S1 orientation: dashboard answers "what am I looking at" (counts, three labeled groups, action line); the stderr first-run hint states the confirm-before-anything boundary verbatim; quit → "Dashboard closed." with no mutation. **Check passes on-screen.** - S2 no-signal vs unknown: group labels "No risk signal found" vs "Unknown" are distinct and cannot be confused; the per-package semantics (checked-and-clean vs could-not-check, with reason + Next step) live in the r-Review detail, not on the dashboard itself. **Check passes; wording observation O1 (P2).** diff --git a/docs/tasks-004-b-verdict-summary-llm-triage.md b/docs/dev/tasks-004-b-verdict-summary-llm-triage.md similarity index 100% rename from docs/tasks-004-b-verdict-summary-llm-triage.md rename to docs/dev/tasks-004-b-verdict-summary-llm-triage.md diff --git a/docs/tasks-005-assessment-export-surface.md b/docs/dev/tasks-005-assessment-export-surface.md similarity index 100% rename from docs/tasks-005-assessment-export-surface.md rename to docs/dev/tasks-005-assessment-export-surface.md diff --git a/docs/technical-documentation.md b/docs/technical-documentation.md index 7fb6295..ae91ba3 100644 --- a/docs/technical-documentation.md +++ b/docs/technical-documentation.md @@ -596,7 +596,7 @@ shellcheck bin/brew-change lib/brew-change-*.sh ## 📄 License -This project is licensed under the Apache License 2.0 - see the [LICENSE](../LICENSE) file for details. +This project is licensed under the MIT License - see the [LICENSE](../LICENSE) file for details. --- diff --git a/docs/trusted-update.md b/docs/trusted-update.md new file mode 100644 index 0000000..940e61c --- /dev/null +++ b/docs/trusted-update.md @@ -0,0 +1,123 @@ +# The Trusted Update Workflow + +How `brew-change -u` and `brew-change -b` decide what is safe to touch — +and why they never claim an update is "safe". + +## Upgrade behavior + +`brew-change -u` defaults only to packages whose fresh release evidence +produced no risk signal. Packages marked **attention** or **unknown** are +never bulk-selected. Before any upgrade, brew-change previews the exact +named package list with Homebrew, then asks for immediate confirmation. +Homebrew can still act on dependencies or dependents shown in that preview. + +In a pipe or other non-interactive environment, brew-change prints guidance +and never starts an upgrade. + +## The `-b` verdict + +`brew-change -b` processes every outdated package and ends with a verdict +that answers the only question a `-b` run has: are there any breaking +packages or none? The verdict uses the same honest three-state assessment +as the `-u` dashboard, computed from the evidence the run already fetched: + +``` +Verdict: 4 attention · 2 no-signal · 19 unknown + +Breaking changes (2) + abseil 20260526.0 → 20260817.0 + absl::void_t is now deprecated; users should use C++17 std::void_t… + nnn 5.2 → 5.3 + removed support for the legacy plugin interface +Major version transitions (1) + vercel 58.9.0 → 59.1.4 +No risk signal found (2) +Unknown (19) — no usable release notes; review individually +``` + +When nothing matches, the run says so explicitly ("No breaking-change +patterns or major version transitions detected across N packages.") while +still disclosing the unknown count — packages without release notes are +never reported as clean. Piped output is identical to the terminal base +render (`NO_COLOR` changes nothing). + +## First run + +On an interactive `brew-change -u` run you will see a one-line hint on +stderr: brew-change checks your outdated packages, shows what changed for +each (`r` review), and only upgrades what you explicitly confirm — nothing +runs until you approve the exact plan. No account or configuration is +needed, and quitting (`q`) changes nothing. The hint is never printed in +pipes or scripts, and it is not stored anywhere. + +## Dashboard by default (changed in v1.14.0) + +`brew-change -u` on a terminal runs the interactive dashboard by default +instead of the plain prompt flow: review each package's evidence +provenance read-only (`r`), stage an explicit per-package selection (`s`), +upgrade the no-signal set (`u`/Enter), or quit (`q`). + +```bash +brew-change -u # dashboard is now the default on a terminal +brew-change -u --plain # previous prompt flow (or BREW_CHANGE_PLAIN=1) +``` + +Escape hatches, in precedence order (`--plain` flag > +`BREW_CHANGE_PLAIN=1` environment variable > default dashboard): + +- `--plain` (or `BREW_CHANGE_PLAIN=1`, e.g. in an rc file) restores the + previous prompt flow. +- `--dashboard` and `BREW_CHANGE_DASHBOARD=1`, the pre-v1.14.0 opt-ins, + are accepted as documented no-ops. + +Piped or redirected runs are unchanged: plain deterministic output, no +prompts, no upgrades, and the view flags do not switch views. + +## Evidence caching and re-entry + +Every evidence fetch (GitHub API, npm registry, scraped release pages) goes +through one HTTP response cache under `~/.cache/brew-change/http/`, so a +re-run after quitting the dashboard reuses earlier responses instead of +re-probing. The dashboard's review shows where each package's evidence came +from and how fresh it is; rows served from cache say so, and quitting with +a staged selection prints a one-line hint on the terminal about re-running. + +```bash +brew-change -u --fresh # re-probe all evidence this run (clears only the HTTP cache) +``` + +`--fresh` removes and recreates only the HTTP response cache; the GitHub +breaking-change patterns, the brew-info cache, and everything else are +preserved. The HTTP cache is bounded (at most 512 entries / 100 MiB, oldest +entries pruned first), never stores authentication tokens (cache keys use a +SHA-256-derived token fingerprint instead), and authenticated responses are +partitioned away from anonymous ones. Failed probes are never cached (a +"no notes" result must not freeze); instead, a package whose release-notes +probe chain concluded nothing is remembered for 10 minutes so immediate +re-runs skip that chain — a successful chain clears the memo instantly. + +After an upgrade inside the dashboard, the refresh is *subtractive*: +packages whose version transition is unchanged keep their session-fresh +records verbatim, and only changed transitions, newly outdated packages, +and retryable rows are re-derived — so the pause after "Upgrade completed" +is short instead of a full second evidence pass. + +## Accessibility + +Output meaning never depends on color or emoji: text labels (like +`[breaking]` and the dashboard group headers) always carry the full +classification, and any emoji is strictly additive decoration on a +terminal. The base render — piped output, `NO_COLOR=1`, screen readers, +copy-paste — is identical by construction. + +```bash +export NO_COLOR=1 # no-color convention: also suppresses decorative emoji +export BREW_CHANGE_NO_EMOJI=1 # explicit no-emoji opt-out (labels unchanged) +export BREW_CHANGE_STATIC_PROGRESS=1 # plain "stage n/N" progress line, no spinner animation +``` + +`BREW_CHANGE_STATIC_PROGRESS=1` keeps the progress lifecycle (TTY-only +drawing, cleared line before the dashboard, restored terminal state) but +replaces the animated spinner with a static line that updates only when the +count changes. The full environment-variable reference lives in +[configuration.md](configuration.md).