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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 8 additions & 105 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down
48 changes: 26 additions & 22 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -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
- [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
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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

---
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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).

---

Expand Down
48 changes: 48 additions & 0 deletions docs/assessment-export.md
Original file line number Diff line number Diff line change
@@ -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).
15 changes: 15 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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).**
Expand Down
2 changes: 1 addition & 1 deletion docs/technical-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

---

Expand Down
Loading
Loading