pi-bro 0.23.1 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  All notable changes to pi-bro are documented here.
4
4
 
5
+ ## [0.25.0] - 2026-10-19
6
+
7
+ ### Highlights
8
+
9
+ - Improve a request before you send it: `/bro elevate <request>`, or **Ctrl+Shift+E** on an unsent draft, suggests up to five things an expert would check that you may have missed.
10
+ - Pick the suggestions you want, and Bro rewrites your request using only those. Nothing is ticked for you, and Bro does not do the task itself.
11
+ - Write or paste a **multi-line** objective: the request field grows like Bro's other editors instead of flattening it onto one line.
12
+ - Insert the rewrite into Pi's editor with one button, or copy it. Nothing goes to the main agent until you press Enter.
13
+ - Find what you need faster: the docs are split into a getting-started page, feature guides, a settings and commands reference, and examples.
14
+
15
+ ### Added
16
+
17
+ - `/bro elevate [request]` and the **Ctrl+Shift+E** shortcut open Bro Elevate in a Bro modal: write the objective, review findings, then insert or copy. An explicit request takes priority over the editor draft; with neither, the modal asks for one. Discovery returns up to five findings, none selected at first. Pick them with **Space** on the highlighted row (**↑**/**↓** move, `Tab` reaches the buttons), then **Enter** rewrites using only the selected findings. **Nothing is selected for you and every action is a labelled button**, so a stray keypress cannot toggle a finding, trigger a rewrite, or replace your editor text. Some terminals don't send Ctrl+Shift+E; use the command instead.
18
+ - Insertion never sends anything. Choose **[Insert into editor]** in the terminal, which replaces the editor only when Elevate was opened on that draft and it is still unchanged; if you passed an explicit request, the editor must be empty. In Pi Desktop it inserts only into an empty editor. Otherwise use **[Copy]**.
19
+ - The objective is a multi-line editor: `Enter` adds a line and **Ctrl+S** (or `Ctrl+Enter` where the terminal delivers it) starts discovery. **Ctrl+C** copies your objective or the rewritten request whenever there is one, and on a terminal too short for the editor the modal asks for a bigger one rather than letting you type blind.
20
+ - Elevate uses the btw backend, model and effort from `/bro config`; there is no separate Elevate setting. It sends the request, uncapped current-branch user/assistant text by default, saved preferences and approved findings. A visible **Context: Messages / Full** switch adds tool-call arguments and text results in Full mode; both exclude hidden reasoning and image binaries. Compose opens before any call, and changing mode resets discovery without sending. Explicit Retry after a recognized context-overload error progressively removes older history, visibly marks reduced context and preserves the objective and approvals; other failures do not trim history. Each step is a fresh call; selections are kept in memory only and cleared on close. Findings are model suggestions, not checked facts. **Retry** repeats the step that failed, so a failed rewrite keeps the findings you approved instead of re-running discovery. See [docs/elevate.md](docs/elevate.md).
21
+ - `/bro help` has an Elevate section.
22
+
23
+ ### Changed
24
+
25
+ - Elevate instructions explicitly carry forward user decisions and corrections, avoid completed or rejected work, seek simplifying opportunities, and integrate approved insights without adding separate deliverables. Output usefulness is left to user feedback rather than AI scoring.
26
+ - The docs are reorganised. A docs home (`docs/README.md`) links to getting started, per-feature guides (`docs/features/`), commands, settings, data-and-permissions and troubleshooting references (`docs/reference/`), and examples. `docs/user-guide.md` now links to these pages, and the new pages ship in the package.
27
+ - `npm run docs:check` checks docs links and quality, and `npm test` runs it.
28
+
29
+ ## [0.24.0] - 2026-10-19
30
+
31
+ ### Highlights
32
+
33
+ - Guided Review now works with Codex, Grok and Agy, not just Claude and Muse. Those three run shell commands inside their own sandbox on the captured checkout.
34
+ - Bro tells you plainly when a review backend can run shell commands (and that Agy's sandbox still allows writes), and recommends Claude or Muse for PRs you do not trust.
35
+ - `/bro doctor` no longer treats a Codex/Grok/Agy review choice as a setup problem; it shows the same advisory as information.
36
+ - Nothing changes for Claude and Muse, which still use strict file-only inspection.
37
+
38
+ ### Changed
39
+
40
+ - Review generation and questions no longer fail before starting on Codex, Grok and Agy. Codex runs `--sandbox read-only --ephemeral`, Grok runs `--sandbox read-only --permission-mode dontAsk`, and Agy keeps `--sandbox` (which limits terminal commands, not file writes); all three use the captured checkout and the 10-minute review deadline. No bypass flag is ever added to a review, and Grok review no longer gets the "do not inspect" prompt restriction.
41
+ - A new advisory appears while a review is being prepared, in the review window, and in `/bro doctor`: the backend runs commands inside its sandbox rather than doing strict file-only inspection.
42
+ - Saved reviews still open with any backend.
43
+
5
44
  ## [0.23.1] - 2026-10-15
6
45
 
7
46
  ### Highlights
package/README.md CHANGED
@@ -36,26 +36,38 @@ GitHub, use `pi install git:github.com/tranhoangnguyen03/pi-bro`.
36
36
 
37
37
  ## Try it
38
38
 
39
- | Type this in Pi | What happens |
39
+ For a first success, type this in Pi after setting up a backend:
40
+
41
+ ```text
42
+ /bro text A request limit means a service allows only a certain number of calls in a given time.
43
+ ```
44
+
45
+ **Expected:** Bro opens a separate window and explains that sentence in plain words. Close with **Esc**. Nothing is sent to your main agent's conversation. The exact words depend on your selected model.
46
+
47
+ | After that | What happens |
40
48
  | --- | --- |
41
- | `/bro` | Explains the agent's last reply |
42
- | `/bro file docs/report.pdf` | Explains a document (use your own path) |
43
- | `/bro url https://example.com/article` | Explains a webpage (use your own link) |
44
- | `/bro btw "what file defines this route?"` | Asks a side question |
45
- | `/bro show` | Draws the last turn as a diagram |
49
+ | `/bro` | Explains the agent's latest completed reply (requires one) |
50
+ | `/bro btw What is a race condition?` | Asks a private side question |
51
+ | `/bro show` | Draws the current session's recent conversation, if any |
52
+ | `/bro elevate Improve how we search company documents` | Find expert gaps before giving Pi a task |
53
+
54
+ File and webpage examples need your own real path or URL; see [how to explain them](docs/features/explain.md#explain-a-document). For a step-by-step first run, see [Getting started](docs/getting-started.md).
46
55
 
47
56
  ## What it does
48
57
 
49
58
  | Command | What you get |
50
59
  | --- | --- |
51
- | `/bro`, `/bro text`, `/bro file`, `/bro url` | **[Explain](docs/user-guide.md#what-bro-can-explain).** A plain-language version of the agent's last reply, pasted text, a PDF/DOCX/Markdown file, or a public webpage. Three modes: `brief`, `balanced`, `faithful`. |
52
- | `/bro show` | **[Show](docs/user-guide.md#bro-show).** The last few turns drawn as a shape (call tree, file tree, diff, pseudocode, a sequence diagram, or an HTML layout) instead of prose. |
53
- | `/bro btw` | **[Side questions](docs/user-guide.md#bro-btw-side-conversation).** A separate conversation seeded with recent context, so you can ask without interrupting the agent. ⚠️ [Full-permission mode](#what-leaves-your-machine) can edit files. |
54
- | `/bro guided-review <PR>` | **[Guided Review](docs/guided-review.md).** An explanation and quality assessment of a GitHub PR, with ranked findings, source evidence and private questions. Needs the Claude or Muse backend. |
55
- | `bro_advisor` tool | **[Second opinion](docs/user-guide.md#bro-advisor).** A tool your agent can call mid-task; a fresh backend process investigates and returns advice to the agent. ⚠️ [Runs with permissions bypassed](#what-leaves-your-machine). |
56
- | `/bro config`, `/bro preferences` | **[Settings](docs/user-guide.md#settings) and [preferences](docs/user-guide.md#preferences).** Pick the backend, model and effort per feature, and tell Bro how you like answers. |
57
-
58
- Every command, control and setting is in the **[user guide](docs/user-guide.md)**.
60
+ | `/bro`, `/bro text`, `/bro file`, `/bro url` | **[Explain](docs/features/explain.md).** A plain-language version of the agent's last reply, pasted text, a PDF/DOCX/Markdown file, or a public webpage. Three modes: `brief`, `balanced`, `faithful`. |
61
+ | `/bro show` | **[Show](docs/features/show.md#bro-show).** The last few turns drawn as a shape (call tree, file tree, diff, pseudocode, a sequence diagram, or an HTML layout) instead of prose. |
62
+ | `/bro elevate` or **Ctrl+Shift+E** | **[Elevate](docs/elevate.md).** Discover missing expert considerations, select useful improvements, and rewrite your task without submitting it. Shares BTW backend settings. |
63
+ | `/bro btw` | **[Side questions](docs/features/btw.md#bro-btw-side-conversation).** A separate conversation seeded with recent context, so you can ask without interrupting the agent. ⚠️ [Full-permission mode](#what-leaves-your-machine) can edit files. |
64
+ | `/bro guided-review <PR>` | **[Guided Review](docs/guided-review.md).** An explanation and quality assessment of a GitHub PR, with ranked findings, source evidence and private questions. Claude or Muse is recommended for untrusted PRs. |
65
+ | `bro_advisor` tool | **[Second opinion](docs/features/advisor.md#bro-advisor).** A tool your agent can call mid-task; a fresh backend process investigates and returns advice to the agent. ⚠️ [Runs with permissions bypassed](#what-leaves-your-machine). |
66
+ | `/bro config`, `/bro preferences` | **[Settings](docs/reference/settings.md#settings) and [preferences](docs/user-guide.md#preferences).** Pick the backend, model and effort per feature, and tell Bro how you like answers. |
67
+
68
+ For help by task, start at the **[docs home](docs/README.md)**; see the [command reference](docs/reference/commands.md) for syntax.
69
+ **Elevate, in practice:** Bro points out expert questions or tests you may have missed before you ask Pi to do the work. Review the suggestions, approve only what matters, then edit or submit the resulting request yourself. See the [walkthrough](docs/elevate.md) for limits, privacy, and editor replacement.
70
+
59
71
  Guided Review has its own [guide](docs/guided-review.md).
60
72
 
61
73
  ## Requirements
@@ -68,14 +80,14 @@ Guided Review has its own [guide](docs/guided-review.md).
68
80
 
69
81
  | Backend | CLI | Notes |
70
82
  | --- | --- | --- |
71
- | [Google Antigravity](https://antigravity.google/docs/cli-install) | `agy` | Default for new settings. Needs `>=1.1.15`. Not for Guided Review. |
72
- | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | Works for every feature, including Guided Review. |
73
- | [Grok Build](https://docs.x.ai/build/overview) | `grok` | Not for Guided Review. |
74
- | [Codex CLI](https://github.com/openai/codex) | `codex` | Not for Guided Review. |
75
- | [Muse Code](https://dev.meta.ai/docs/muse-code) | `muse` | Works for every feature, including Guided Review. |
83
+ | [Google Antigravity](https://antigravity.google/docs/cli-install) | `agy` | Default for new settings. Needs `>=1.1.15`. Guided Review uses `--sandbox`, which restricts shell commands but still allows writes inside the project. |
84
+ | [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | `claude` | Works for every feature; strict file-only inspection for Guided Review. |
85
+ | [Grok Build](https://docs.x.ai/build/overview) | `grok` | Guided Review uses its read-only sandbox (shell-enabled). |
86
+ | [Codex CLI](https://github.com/openai/codex) | `codex` | Guided Review uses its read-only sandbox (shell-enabled). |
87
+ | [Muse Code](https://dev.meta.ai/docs/muse-code) | `muse` | Works for every feature; strict file-only inspection for Guided Review. |
76
88
 
77
89
  - Guided Review also needs Git and an authenticated [`gh`](https://cli.github.com/).
78
- Choose Claude or Muse for it in `/bro config`.
90
+ Claude or Muse is recommended for untrusted PRs (strict file-only inspection); Codex, Grok and Agy run with shell available under their sandbox, with an advisory.
79
91
  - [PiG](docs/pig-compatibility.md) support is experimental.
80
92
 
81
93
  ## What leaves your machine
@@ -89,6 +101,7 @@ which may keep it under their own policies. Paths below are under
89
101
  | Explain | The agent's last reply, your pasted text, or text extracted from your file or webpage, plus your preferences | Nothing; the last result stays in memory |
90
102
  | Show | User and assistant text from recent turns (no tool calls, tool results, reasoning or images), plus your preferences | Diagram pages in `pi-bro-<uid>/` in your system temp folder |
91
103
  | Side questions | Your questions and up to the last 8 turns of conversation text, plus your preferences | Nothing; the thread stays in memory |
104
+ | Elevate | Your objective, selected findings, all current-branch user/assistant text; Full also includes tool-call arguments and text results, and preferences | Nothing; the workflow stays in memory |
92
105
  | Guided Review | The PR description and diff, the files the backend reads, your questions, plus your preferences | Reviews and captured source in `bro-reviews/`, with no automatic cleanup |
93
106
  | Advisor | The agent's system instructions, tool list and whole conversation, including tool calls and results (reasoning and images omitted), plus your steering | Steering in `bro-advisor.md` and the session file |
94
107
 
@@ -105,12 +118,13 @@ tool results.
105
118
  > only an instruction.
106
119
  > - **BTW full-permission mode** (turned on with `/mode` inside BTW): it is
107
120
  > meant to edit files and run commands.
108
- > - **Grok, wherever you use it:** its sandbox is always off. "Answer only from
109
- > the supplied context" is only an instruction.
121
+ > - **Grok:** its sandbox is off except during Guided Review, which uses the
122
+ > read-only sandbox. "Answer only from the supplied context" is only an
123
+ > instruction.
110
124
 
111
125
  Details per backend:
112
- [Backends: access and retention](docs/user-guide.md#backends-access-and-retention)
113
- and [Privacy and safety](docs/user-guide.md#privacy-and-safety).
126
+ [Backends: access and retention](docs/reference/data-and-permissions.md#backends-access-and-retention)
127
+ and [Privacy and safety](docs/reference/data-and-permissions.md#privacy-and-safety).
114
128
 
115
129
  ## Limits
116
130
 
@@ -120,12 +134,13 @@ and [Privacy and safety](docs/user-guide.md#privacy-and-safety).
120
134
  proxy settings. → Save the page as PDF or text and use `/bro file`.
121
135
  - No fallback: if the chosen backend, model or effort fails, Bro shows that
122
136
  backend's error instead of switching. → Run `/bro doctor`.
137
+ - Elevate runs fresh restricted calls through the BTW model setting. Restricted does not always mean sandboxed; see [access and retention](docs/reference/data-and-permissions.md). The shortcut may not work in all terminals: use `/bro elevate` instead.
123
138
  - BTW threads and the last explanation live in memory only and clear on
124
139
  reload or restart.
125
140
  - Guided Review runs in local interactive Pi only and does not post to
126
141
  GitHub.
127
142
 
128
- Full list: [Troubleshooting and current limits](docs/user-guide.md#troubleshooting-and-current-limits).
143
+ Full list: [Troubleshooting and current limits](docs/reference/troubleshooting.md#troubleshooting-and-current-limits).
129
144
 
130
145
  ## Stability
131
146
 
package/docs/README.md CHANGED
@@ -1,14 +1,32 @@
1
- # pi-bro docs
2
-
3
- - [README](../README.md) — the short overview: install, try it, requirements, data flow.
4
- - [user-guide.md](user-guide.md) — the full user guide (authoritative for behavior).
5
- - [guided-review.md](guided-review.md) — current Guided Review behavior, optional controls, access/storage and limits.
6
- - [pig-compatibility.md](pig-compatibility.md) — experimental PiG support and its limits.
7
- - [DEVELOPMENT.md](DEVELOPMENT.md) — code map, settings and BTW continuation model, invariants, test commands.
8
- - [TESTING.md](TESTING.md) — the manual end-to-end checklist across backends.
9
- - [test-consolidation.md](test-consolidation.md) — the #74 test coverage ledger.
10
- - [PUBLIC-PRESENTATION.md](PUBLIC-PRESENTATION.md) — how pi-* repos present themselves publicly; sister repos follow it too.
11
- - [dev/README.md](../dev/README.md) — manual review launcher and profile/call precautions (not shipped).
12
- - [plans/](plans/README.md) — historical design notes and plans; not the current spec.
13
- - [images/](images/) — screenshots used by the README and user guide.
14
- - [benchmark/README.md](../benchmark/README.md) — the manual, live prompt benchmark.
1
+ # Pi-bro documentation
2
+
3
+ Start with what you want to do. The [README](../README.md) explains the product, install, and privacy summary.
4
+
5
+ ## I'm new
6
+
7
+ - [Getting started](getting-started.md) — install, check your backend, and complete a working first example.
8
+ - [Command lookup](reference/commands.md#commands) — find the right command.
9
+
10
+ ## I want to do something
11
+
12
+ - [Explain an agent answer or text](features/explain.md#explanation-modes) — plain-language explanations.
13
+ - [Explain a local file](features/explain.md#explain-a-document) or [webpage](features/explain.md#explain-a-webpage).
14
+ - [Visualize a conversation](features/show.md#bro-show) — Show diagrams.
15
+ - [Ask a private side question](features/btw.md#bro-btw-side-conversation) — BTW.
16
+ - [Improve a request before sending it](elevate.md) — Elevate: discover expert gaps, choose improvements, rewrite the task.
17
+ - [Investigate a PR](guided-review.md) — Guided Review.
18
+ - [Get an agent's second opinion](features/advisor.md#bro-advisor) — Advisor; review its permissions first.
19
+
20
+ ## I need to set up or fix something
21
+
22
+ - [Choose backend, model and preferences](reference/settings.md#settings).
23
+ - [Check your setup](reference/troubleshooting.md#check-your-setup) and [troubleshoot](reference/troubleshooting.md#troubleshooting-and-current-limits).
24
+ - [See exactly what Bro sends and can access](reference/data-and-permissions.md#backends-access-and-retention) — backend permissions, retention, and [privacy](reference/data-and-permissions.md#privacy-and-safety).
25
+ - [PiG compatibility](pig-compatibility.md) — experimental host support.
26
+
27
+ ## For contributors
28
+
29
+ - [Contributing](../CONTRIBUTING.md), [code map](DEVELOPMENT.md), [manual testing](TESTING.md), and [security reports](../SECURITY.md).
30
+ - [Presentation standard](PUBLIC-PRESENTATION.md), [test evidence](test-consolidation.md), [prompt benchmarks](../benchmark/README.md), and [historical plans](plans/).
31
+
32
+ The topic pages and references above document shipped behavior. [Old user-guide links](user-guide.md) still work as pointers. Historical plans may describe work that did not ship.
@@ -0,0 +1,125 @@
1
+ # Bro Elevate — improve a request before you send it
2
+
3
+ **Elevate helps you ask for better work when you may not know what to ask for.** You describe what you want to achieve; Bro suggests a few expert questions, methods, or checks you may have missed. You choose which ones matter. Bro then rewrites **your assignment**, not the answer to it.
4
+
5
+ Elevate is useful before a design, research task, implementation, plan, or important decision. It is not a way to turn every small request into a large project. Sometimes the best result is: *Your original request is good enough.*
6
+
7
+ Elevate works inside Pi's **separate Bro modal**. It does not post its discussion to the main agent or execute the revised assignment. You control whether the final text goes into the main editor, and you still press Enter to send it.
8
+
9
+ ## Start here (one minute)
10
+
11
+ **Option A: Improve a draft already in Pi's editor.** Type your request normally, but **do not submit it**. Invoke the **Ctrl+Shift+E** shortcut, where your terminal sends that key combination to Pi. Elevate opens Compose with your unsent draft; choose a context mode before starting discovery. If the shortcut doesn't work in your terminal, use `/bro elevate <request>` instead.
12
+
13
+ **Option B: Start with a slash command.**
14
+
15
+ ```text
16
+ /bro elevate Design a retrieval system for our company documents.
17
+ ```
18
+
19
+ **Option C: Start with no text.**
20
+
21
+ ```text
22
+ /bro elevate
23
+ ```
24
+
25
+ If the main editor contains a draft, Bro pre-fills the objective with that draft. Elevate always opens Compose first so you can choose context before any model call. Otherwise, it shows a multi-line objective field: type or paste the objective and choose **Ctrl+S** (or `Ctrl+Enter` on terminals that send it, or the `[Discover gaps]` button). `Enter` adds a new line, so a pasted multi-line task keeps its structure.
26
+
27
+ When both an explicit `/bro elevate <request>` argument and a draft exist, the **explicit argument takes priority**. The main editor is left untouched unless you later choose to insert the revision.
28
+
29
+ ## Conversation context and retry
30
+
31
+ The **Context: Messages** button toggles to **Context: Full**. Use Tab to focus actions and Left/Right to reach it; Enter activates it. Short labels may show Messages or Full on narrow screens. The header always shows the active mode. While reviewing findings, choose **Edit request** to return to Compose and switch context; keeping the review action row short leaves space for explanations on small terminals.
32
+
33
+ - **Messages (default):** all user and assistant text from the current conversation branch.
34
+ - **Full:** also includes tool-call arguments and text tool results. This may send sensitive file contents, command arguments or tool output to the selected provider. Hidden reasoning, image binaries and provider metadata are excluded in both modes.
35
+ - There is **no fixed history cap**. Provider context limits still apply. The separate 12,000-character objective limit remains.
36
+ - Changing mode never makes a model call. It returns to Compose and clears old findings, approvals and rewrites. Start discovery again to use the new mode. Each new window defaults to Messages; history is captured when the window opens.
37
+ - After an explicit context-overload error, **Retry** removes the oldest half of remaining messages and repeats the failed step. If only one oversized message remains, subsequent retries halve its text, then omit it. The header shows **reduced** and the prompt marks partial history. The objective and approved findings remain intact. There are no automatic retries and ordinary failures do not trim context. Once history is exhausted, shorten the objective or choose a larger-context backend.
38
+
39
+ ## The two questions Elevate asks
40
+
41
+ 1. **Discover:** “Given my objective, what would a skilled expert know, question, investigate, or test that I haven't accounted for?” Bro looks across **altitude** (right problem), **depth** (evidence, methods, tests), and **range** (useful ideas from other fields). It offers up to **five** non-overlapping suggestions, with a reason and an expert action for each. It can also report **zero** suggestions.
42
+ 2. **Upgrade:** “Rewrite my request using only the insights I approve. Keep my outcome, constraints, and scope. Improve the quality of the work, not the amount of work.” Bro returns the improved assignment for **you to review**.
43
+
44
+ The flow is **Discover → Select → Upgrade → Insert or Copy**. It typically makes **two model calls** (discovery and rewrite); if Bro finds no useful changes, it makes only the discovery call and keeps the original request.
45
+
46
+ ## Example: before and after
47
+
48
+ **Your original request**
49
+
50
+ > Help me design a system that lets AI agents find relevant information in company documents. Keep our current data pipelines.
51
+
52
+ **Possible discoveries** (illustrative, not a promise of any exact answer):
53
+
54
+ | Finding | Why an expert would ask about it |
55
+ | --- | --- |
56
+ | **Depth — Test real questions first** | A plausible demo may still miss facts spread across different documents. Collect sample questions and expected source evidence before choosing a search method. |
57
+ | **Range — Link company names and metrics** | Acquired firms may use different names for the same product or metric. Map those links so agents don't mistake them for separate things. |
58
+ | **Altitude — Define what a correct answer means** | Retrieving relevant text is not the final goal. The agent must give useful, well-supported answers. |
59
+
60
+ You might approve the first and third findings and reject the second for now.
61
+
62
+ **Possible upgraded request**
63
+
64
+ > Design an approach for helping agents answer real business questions from our existing documents, without replacing our current structured-data pipelines. Start by collecting a small set of representative questions and the evidence needed for correct answers. Compare retrieval approaches against those questions, including how they handle facts spread across documents. Recommend the smallest sound design and specify how we would test answer correctness, coverage, and source support. Flag gaps in access or evidence rather than assuming the answers are known.
65
+
66
+ Bro has **not designed the system** here. It has improved the assignment you can give to Pi. You can still edit or reject the rewrite.
67
+
68
+ ## Controls in the modal
69
+
70
+ Every consequential action is a **button** on the action row. `Tab` / `Shift+Tab` move between the text/list area and the buttons, `←`/`→` move between buttons, and `Enter` activates the focused one. The focused button is marked with `›`. Nothing that changes your request or your editor happens on a stray keypress.
71
+
72
+ | Screen | Key | Effect |
73
+ | --- | --- | --- |
74
+ | Write a request | `Enter` | Start a new line in the objective. |
75
+ | Write a request | `Ctrl+S` or `Ctrl+Enter` | Start discovery. The same as the `[Discover gaps]` button. `Ctrl+S` is listed first because many terminals never deliver `Ctrl+Enter`. |
76
+ | Review discoveries | `↑` / `↓` | Move the highlight between findings. |
77
+ | Review discoveries | `Space` or `Enter` | Tick or untick the **highlighted** finding. Either key works, so there is no wrong one to press. Nothing is selected at first, so you approve only what you read; the reason for the highlighted finding is shown under the list. |
78
+ | Review discoveries | `Tab` | Move focus to the buttons. |
79
+ | Review discoveries | `[Rewrite with N selected]` | Generate a revised request using only the ticked findings. With nothing ticked it explains why instead of proceeding. |
80
+ | Review discoveries | `[Select all]` / `[Select none]` | Change every tick at once. |
81
+ | Revised request | `[Insert into editor]` | Insert the revised request into Pi's main editor, **without sending it**. See editor behavior below. |
82
+ | Revised request | `[Copy]` | Copy the revised request to the system clipboard. |
83
+ | Revised request | `[Back]` | Return to the findings and change your choices. |
84
+ | Failed step | `[Retry]` | Repeat **the step that failed**: a failed rewrite retries the rewrite with the same approved findings, so your choices are not lost. |
85
+ | Any screen | `Ctrl+C` | Copy the objective or the revised request, so closing never loses pasted work. |
86
+ | Any screen | `Esc` | Cancel/close. A running backend request is asked to stop. |
87
+ | Read long content | `↑`/`↓`, Page Up/Down, wheel | Scroll. In the findings list, `↑`/`↓` move the highlight and Page Up/Down scroll. |
88
+
89
+ If there are **no material findings**, the revised-request screen displays your original text unchanged. You may copy, insert, or close it; no rewrite model call is made.
90
+
91
+ ### What happens to the original editor draft?
92
+
93
+ - **Before you insert:** Opening, selecting, copying, cancelling, or retrying Elevate does **not** change the main editor.
94
+ - **In Pi terminal (TUI):** The `[Insert into editor]` button replaces the editor text with the revised request. It only replaces the draft Elevate was opened on, and only if that text has not changed since it opened; if you opened Elevate with an explicit request, the editor must be empty. Otherwise insertion is refused and you can copy instead. There is no built-in undo of this replacement in Elevate—copy the original first if you want to keep both versions.
95
+ - **In compatible Pi Desktop/RPC:** The adapter only inserts when the editor is empty and confirms atomic insertion support. If the editor contains a draft or insertion isn't supported, use `[Copy]` and paste manually. It does **not** replace a Desktop draft.
96
+ - **After insertion:** The new text remains editable. **Nothing is sent to Pi's main agent** until *you* submit it.
97
+
98
+ ## What Elevate can and cannot do
99
+
100
+ **Does:** Improve how the assignment is framed, point out missing checks, offer cross-field methods, help you choose, and create a stricter request that preserves the outcome and stated limits.
101
+
102
+ **Doesn't (MVP):** Solve the task, run real-world experiments, fetch external sources as an explicit research step, implement code, interrupt the agent mid-task, ask the main agent for advice, or save an ongoing Elevate conversation. It cannot confirm its ideas are correct without external evidence. Suggestions are **model-generated hypotheses**, not verified findings. The rewrite may still misread your intent; review it before sending.
103
+
104
+ **Access and privacy:**
105
+
106
+ - Bro sends the **request**, conversation history selected by **Messages** or **Full**, saved Bro preferences if any, and later the **approved findings**, to the selected backend/provider. History is initially uncapped; Full includes tool-call arguments and text results. Hidden reasoning and image binaries are never captured. Explicit overload retries can remove older context as described above.
107
+ - Elevate uses the **BTW backend/model/effort setting** from `/bro config`, falling back to Bro's shared default. There is **no separate Elevate setting** in this MVP. Each stage makes a **fresh, non-continuing** backend call; your Elevate selections live only in memory and clear on close/reload.
108
+ - Requests use Bro's **restricted explain-style execution path**. Restrictions depend on the backend. For example, **Grok's restriction is prompt-only and its sandbox is off**; **Codex and Muse can have read tools**, including tools governed by local configuration. **Do not treat this as a firm sandbox or a guarantee of no file/network access.** Consult [backend access details](reference/data-and-permissions.md#backends-access-and-retention). Elevate itself has no file-read or file-write action.
109
+ - Closing or cancelling does not submit anything to the main agent. Your backend and provider may still retain prompts or process data under their own policies. Clipboard copies may remain in clipboard history.
110
+
111
+ ## Troubleshooting
112
+
113
+ | Problem | What to do |
114
+ | --- | --- |
115
+ | Shortcut doesn't open Elevate | Some terminals don't send `Ctrl+Shift+E` as a distinct key. Use `/bro elevate <request>`; check Pi key bindings. |
116
+ | Nothing to work on | Type the objective into the modal and choose `[Discover gaps]`, or pass it with `/bro elevate <request>`. |
117
+ | “Invalid discovery JSON” | The model didn't follow the required response format. Choose `[Retry]` to repeat the step; consider a different BTW model in `/bro config`. |
118
+ | Backend/model/effort fails | Run `/bro doctor`; Elevate does not silently switch models. |
119
+ | If `[Insert into editor]` is refused | Your editor changed while Elevate was open, or Desktop can't safely insert into a non-empty editor. Use `[Copy]`, then paste. |
120
+ | The rewrite added unwanted scope | Use `[Back]` to approve fewer findings, or `Esc` to keep your original request. |
121
+ | You need source-backed research | Ask the main agent to investigate after you submit the improved request. Elevate's discovery alone does not verify source facts. |
122
+
123
+ ## For maintainers
124
+
125
+ See [DEVELOPMENT.md](DEVELOPMENT.md) for code boundaries and [TESTING.md](TESTING.md) for terminal/desktop checks. `src/elevate-engine.ts` is a host-free prompt, parser, and selection layer; `src/elevate.ts` owns the Pi modal and backend calls. Future cross-harness work is intentionally out of scope.
@@ -0,0 +1,268 @@
1
+ # Examples: before and after
2
+
3
+ [Docs home](README.md) · [All commands](reference/commands.md) · [Safety and permissions](reference/data-and-permissions.md)
4
+
5
+ ## Bro in action
6
+
7
+ ### Assistant response
8
+
9
+ **Before `/bro`: the original agent response**
10
+
11
+ [![A dense assistant response before Bro](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-response-before.png)](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-response-before.png)
12
+
13
+ **After `/bro`: the plain-language explanation**
14
+
15
+ [![The assistant response explained in the Bro modal](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-response-after.png)](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-response-after.png)
16
+
17
+ ### Local document
18
+
19
+ **Before: a complex PDF**
20
+
21
+ [![A complex PDF before Bro](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-file-before.png)](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-file-before.png)
22
+
23
+ **After `/bro file <path>`**
24
+
25
+ [![The PDF explained in the Bro modal](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-file-after.png)](https://raw.githubusercontent.com/tranhoangnguyen03/pi-bro/main/docs/images/bro-file-after.png)
26
+
27
+ Bro optimizes for understanding, not simply for fewer words. The written
28
+ examples below are synthetic and were run through Bro's default prompt. Click
29
+ a screenshot to see it at full size.
30
+
31
+ <details>
32
+ <summary><strong>Short:</strong> TypeScript says a value is <code>never</code></summary>
33
+
34
+ ### Before
35
+
36
+ > The diagnostic is not evidence that `result` is intrinsically uninhabitable; it is an artifact of TypeScript's intraprocedural control-flow graph. Because `result` is initialized to `null` and only assigned inside the `forEach` callback, the outer scope does not model that callback as definitely executing. After `if (!result) return`, the remaining branch therefore collapses to `never`, producing the property-access error. Replace the callback-driven mutation with a control-flow-visible loop: `for (const item of items) { if (matches(item)) { result = item; break; } }`. Alternatively, derive the value expressionally with `const result = items.find(matches);` and guard `if (!result) return;` before dereferencing it. Avoid an `as Result` assertion; it suppresses the symptom while preserving the unsound state transition that caused the narrowing anomaly.
37
+
38
+ ### After `/bro`
39
+
40
+ #### What happened
41
+
42
+ TypeScript showed an error saying your variable `result` cannot be used or
43
+ accessed.
44
+
45
+ This happened because `result` was set to `null` outside a `forEach` loop and
46
+ then modified inside the loop's helper function (callback). TypeScript tracks
47
+ code line by line. It cannot guarantee that code inside a `forEach` callback
48
+ will actually run.
49
+
50
+ #### What it means
51
+
52
+ Because TypeScript assumes the loop's callback might not run:
53
+
54
+ 1. It believes `result` might still be `null`.
55
+ 2. When you check `if (!result) return`, TypeScript thinks `result` can never
56
+ hold a valid value after that check.
57
+ 3. It sets the type of `result` to `never` (a special type meaning "impossible
58
+ value") and blocks you from reading its properties.
59
+
60
+ The error is a limitation in how TypeScript analyzes loops with callbacks.
61
+
62
+ #### What you should do next
63
+
64
+ Choose one of these two fixes:
65
+
66
+ **Option 1: Use a standard `for...of` loop**
67
+
68
+ ```ts
69
+ for (const item of items) {
70
+ if (matches(item)) {
71
+ result = item;
72
+ break;
73
+ }
74
+ }
75
+ ```
76
+
77
+ **Option 2: Use `Array.prototype.find`**
78
+
79
+ ```ts
80
+ const result = items.find(matches);
81
+ if (!result) return;
82
+ ```
83
+
84
+ Avoid using a type assertion like `as Result`. It only hides the warning
85
+ without fixing the underlying tracking issue.
86
+
87
+ </details>
88
+
89
+ <details>
90
+ <summary><strong>Medium:</strong> Login succeeds, but the user is still logged out</summary>
91
+
92
+ ### Before
93
+
94
+ > What you're observing is almost certainly not an authentication failure in the credential-validation layer; it is a post-authentication session persistence failure caused by an environment-dependent mismatch between Express's transport-security inference and the TLS termination topology in production.
95
+ >
96
+ > Locally, Express sees the request as plain HTTP and your development cookie configuration probably permits a non-secure session cookie. In production, however, the browser connects over HTTPS to Nginx, a load balancer, or an ingress controller, which terminates TLS and forwards the request to Node over HTTP. Unless Express trusts that intermediary, `req.secure` remains `false`, even when the proxy sends `X-Forwarded-Proto: https`. With `cookie.secure: true`, `express-session` can consequently decline to emit the cookie because it believes the originating request was insecure. The login route may still return `200`, making the credentials appear accepted, but the next request has no session identifier and is treated as anonymous.
97
+ >
98
+ > Configure proxy trust before registering session middleware, and make the cookie policy reflect whether the frontend and API are same-site or genuinely cross-site:
99
+ >
100
+ > ```js
101
+ > app.set("trust proxy", 1);
102
+ >
103
+ > app.use(session({
104
+ > secret: process.env.SESSION_SECRET,
105
+ > resave: false,
106
+ > saveUninitialized: false,
107
+ > proxy: true,
108
+ > cookie: {
109
+ > httpOnly: true,
110
+ > secure: true,
111
+ > sameSite: "lax",
112
+ > maxAge: 1000 * 60 * 60 * 24
113
+ > }
114
+ > }));
115
+ > ```
116
+ >
117
+ > Use `sameSite: "none"` instead of `"lax"` only when the browser must send the cookie in a cross-site context, such as a frontend and API on unrelated registrable domains. Browsers require `Secure` when `SameSite=None`, so that combination must remain HTTPS-only. Separate subdomains such as `app.example.com` and `api.example.com` are usually same-site, though they are still cross-origin.
118
+ >
119
+ > Also verify that the proxy explicitly forwards `X-Forwarded-Proto`, that the browser receives a `Set-Cookie` response header, and that frontend requests use `credentials: "include"` when crossing origins. If CORS is involved, the server must return the exact allowed origin plus `Access-Control-Allow-Credentials: true`; a wildcard origin is incompatible with credentialed requests.
120
+ >
121
+ > Avoid setting a cookie `domain` unless sharing across subdomains is intentional. A host-only cookie is safer and eliminates another production-only failure mode.
122
+
123
+ ### After `/bro`
124
+
125
+ #### What happened
126
+
127
+ Your username and password check succeeded, and the login route returned `200
128
+ OK`. However, the browser did not receive or return a usable session cookie in
129
+ production.
130
+
131
+ #### What it means
132
+
133
+ In production, secure web traffic (HTTPS) hits an intermediary, such as a load
134
+ balancer or Nginx, before reaching your Node/Express app as plain HTTP.
135
+
136
+ Because your session cookie requires HTTPS (`secure: true`), Express may withhold
137
+ it when it does not trust the proxy forwarding the request. The exact trust
138
+ setting must match your deployment's proxy topology.
139
+
140
+ #### What you should do next
141
+
142
+ 1. Configure Express to trust only your actual proxy topology. Put this before
143
+ the session setup. For example, use `1` only when there is exactly one trusted
144
+ proxy hop:
145
+
146
+ ```js
147
+ app.set("trust proxy", 1);
148
+
149
+ app.use(session({
150
+ secret: process.env.SESSION_SECRET,
151
+ resave: false,
152
+ saveUninitialized: false,
153
+ cookie: {
154
+ httpOnly: true,
155
+ secure: true,
156
+ sameSite: "lax",
157
+ maxAge: 1000 * 60 * 60 * 24
158
+ }
159
+ }));
160
+ ```
161
+
162
+ 2. Check your cookie settings:
163
+ - Keep `sameSite: "lax"` if your frontend and backend share the same main
164
+ domain, such as `app.example.com` and `api.example.com`.
165
+ - Use `sameSite: "none"` only when the cookie must be sent cross-site.
166
+ Browsers require `secure: true` with this setting.
167
+ - Avoid defining a custom cookie `domain` unless you deliberately need to
168
+ share cookies across subdomains.
169
+
170
+ 3. Verify the proxy, browser, and CORS settings:
171
+ - Ensure the proxy forwards the `X-Forwarded-Proto` header.
172
+ - Check that the response contains a `Set-Cookie` header.
173
+ - Include `credentials: "include"` in cross-origin frontend requests.
174
+ - Return the exact allowed origin with
175
+ `Access-Control-Allow-Credentials: true`. Do not use a wildcard (`*`) for
176
+ credentialed requests.
177
+
178
+ </details>
179
+
180
+ <details>
181
+ <summary><strong>Long:</strong> A CI build fails only when its cache is restored</summary>
182
+
183
+ ### Before
184
+
185
+ > The failure is not a nondeterministic pnpm installation problem, despite the misleading first error being emitted from the test runner immediately after dependency hydration. It is a state-contamination problem at the intersection of the repository cache, the package export map, and an incorrectly scoped cache key. The decisive observation is that the same commit succeeds in a clean checkout and in CI when cache restoration is disabled, but fails when the pre-build workspace cache is restored. That isolates the variable to files materialized outside Git rather than source, Node, or runner image drift.
186
+ >
187
+ > The affected package, `@acme/config`, was recently migrated from a dual CommonJS/ESM build to an ESM-oriented TypeScript output. Its root `package.json` declares `"type": "module"` and maps the `import` condition to `./dist/index.js`, while the legacy `require` condition still maps to `./dist/index.cjs`. The current compiler emits `index.js` but does not remove the previous build directory first. An older cached `dist` directory therefore contributes two files that no longer belong to the current build graph: `dist/index.cjs` and `dist/package.json`, the latter declaring `"type": "commonjs"`. The new compiler overlays `dist/index.js` but leaves both obsolete files intact. Because nested package boundaries override the root package type, Node interprets the newly emitted ESM `index.js` as CommonJS in that restored workspace and reports `Unexpected token 'export'`. Test processes entering through `require()` instead resolve the obsolete `index.cjs`, which references a removed chunk and can instead produce `MODULE_NOT_FOUND`. These apparently different errors are two projections of the same dirty-output condition.
188
+ >
189
+ > The cache configuration makes that contaminated state persistent. The workflow computes the key with `hashFiles('packages/**/pnpm-lock.yaml')`, but this workspace has only the root-level `pnpm-lock.yaml`. GitHub Actions consequently evaluates the hash expression to an empty value, yielding a key equivalent to `Linux-node20-workspace-`. A broad restore key then permits an archive produced before the module-format migration to satisfy the lookup. That archive combines the pnpm content-addressable store, Turborepo metadata, and every package's `dist` directory. Those data classes do not share valid invalidation semantics: pnpm store entries are immutable by content, Turborepo artifacts are task-hash addressed, and arbitrary build directories are mutable snapshots whose correctness depends on complete deletion or exact provenance. Treating them as one cache effectively elevates obsolete untracked files into undeclared build inputs.
190
+ >
191
+ > The evidence is visible by comparing the restored and clean workspaces before compilation. In the failing job, `packages/config/dist/package.json` exists with `"type":"commonjs"` and `packages/config/dist/index.cjs` has a timestamp and checksum predating the current commit. Neither file appears after `git clean -ffdx` followed by installation and build. The Actions cache log also shows the truncated key without a lockfile digest, while `git diff` remains empty because the problematic files are ignored. Finally, deleting only `packages/config/dist` before rerunning the unchanged test command converts the failure to a pass, which excludes dependency resolution and network variability as primary causes.
192
+ >
193
+ > The minimal durable remediation has three parts. First, stop caching package output directories. Cache the pnpm store separately, using a key that includes the actual root lockfile:
194
+ >
195
+ > ```yaml
196
+ > key: ${{ runner.os }}-node20-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
197
+ > restore-keys: |
198
+ > ${{ runner.os }}-node20-pnpm-
199
+ > ```
200
+ >
201
+ > A broad fallback is acceptable for the pnpm store because pnpm validates content-addressed entries; it is not acceptable for mutable `dist` snapshots. If remote or local Turborepo caching is retained, cache only `.turbo` and allow Turbo's task hash to govern artifact reuse rather than wrapping raw workspace outputs in a generic archive.
202
+ >
203
+ > Second, make every package build replace, rather than merge into, its output directory. `@acme/config` should delete `dist` before invoking `tsc`, `tsup`, or the existing bundler. The CI workflow should also run the repository's recursive clean target before the first build as a defense against future cache or runner reuse. This is not a substitute for fixing cache scope, but it restores the invariant that generated output is a function of the checked-out sources and declared toolchain.
204
+ >
205
+ > Third, make the export contract agree with emitted files. If `@acme/config` is intentionally ESM-only, remove the `require` condition and the obsolete CommonJS metadata. If CommonJS consumers remain supported, restore an explicit CJS build that deterministically emits `dist/index.cjs`; do not let a historical artifact impersonate that support. In either case, package publication should reject export targets that do not exist.
206
+ >
207
+ > Verification should exercise both cache states and both module entry paths. Run the full pipeline once with no cache, save only the corrected caches, and rerun the identical commit expecting a cache hit and the same result. Inspect the built package to confirm the nested CommonJS `package.json` and legacy chunks are absent unless intentionally generated. Add a lightweight smoke check using dynamic `import('@acme/config')`; if CommonJS remains supported, add a second check through `createRequire`. Finally, change the root lockfile and confirm the logged cache key changes. That matrix validates clean-build reproducibility, restored-cache reproducibility, export-map coherence, and dependency-cache invalidation independently rather than relying on a single green run.
208
+
209
+ ### After `/bro`
210
+
211
+ #### What happened
212
+
213
+ Your build failed because old files were left behind by a broken cache (a saved
214
+ snapshot of previous build files).
215
+
216
+ The package `@acme/config` recently switched its module format to modern
217
+ JavaScript (ESM). However, the build process did not delete the old output
218
+ folder (`dist`) before creating new files.
219
+
220
+ Because the GitHub Actions setting searches the wrong path
221
+ (`hashFiles('packages/**/pnpm-lock.yaml')`), GitHub could not find the root
222
+ `pnpm-lock.yaml`. It restored an outdated cache containing `dist/index.cjs` and
223
+ a `dist/package.json` configured for older JavaScript (CommonJS). The new build
224
+ wrote some files but left the old ones behind, confusing Node and causing errors
225
+ such as `Unexpected token 'export'` and `MODULE_NOT_FOUND`.
226
+
227
+ A clean checkout without the cache succeeds. This proves the problem is old
228
+ cached files, not your source code or dependencies.
229
+
230
+ #### What it means
231
+
232
+ - **Cache contamination:** The CI workflow restores mutable `dist` folders
233
+ alongside package-manager files, mixing obsolete files into new builds.
234
+ - **Mismatched module settings:** The package says it supports both modern
235
+ (`import`) and legacy (`require`) formats, but it only builds the modern one
236
+ while relying on leftover cached files for the legacy one.
237
+
238
+ #### What you should do next
239
+
240
+ 1. **Fix the GitHub Actions cache:** Stop caching `dist` folders. Cache only the
241
+ pnpm store, using the root lockfile:
242
+
243
+ ```yaml
244
+ key: ${{ runner.os }}-node20-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
245
+ restore-keys: |
246
+ ${{ runner.os }}-node20-pnpm-
247
+ ```
248
+
249
+ If you use Turborepo, cache only `.turbo`.
250
+
251
+ 2. **Clean output folders before building:** Make `@acme/config` delete `dist`
252
+ before running `tsc`, `tsup`, or the bundler. Run the repository's recursive
253
+ clean command before CI builds.
254
+
255
+ 3. **Update the package exports:**
256
+ - If `@acme/config` is ESM-only, remove the `require` entry and old CommonJS
257
+ metadata.
258
+ - If CommonJS is still needed, add a real build step for `dist/index.cjs`.
259
+
260
+ 4. **Verify the fix:**
261
+ - Delete the generated `packages/config/dist` folder, then run a clean build.
262
+ Do not use `git clean -ffdx` in a working copy with files you need.
263
+ - Run the workflow without a cache, save the new cache, and rerun the same
264
+ commit to verify that a cache hit also passes.
265
+ - Test `import('@acme/config')`, and test `createRequire` if CommonJS is
266
+ supported.
267
+
268
+ </details>