@underactive/pi-topping-moa-fusion 0.1.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/LICENSE +21 -0
  3. package/README.md +437 -0
  4. package/agents/mf-plan.md +43 -0
  5. package/agents/moa-debater.md +37 -0
  6. package/agents/moa-explore.md +56 -0
  7. package/agents/moa-opinion.md +29 -0
  8. package/agents/moa-proposer.md +49 -0
  9. package/agents/moa-synthesizer.md +124 -0
  10. package/agents/moa-verifier.md +67 -0
  11. package/index.ts +3 -0
  12. package/package.json +61 -0
  13. package/src/activityMeter.ts +193 -0
  14. package/src/agents/authoritative.ts +91 -0
  15. package/src/agents/defaults.ts +123 -0
  16. package/src/agents/discovery.ts +119 -0
  17. package/src/config/modelCatalogue.ts +54 -0
  18. package/src/config/planName.ts +74 -0
  19. package/src/config/rosters.ts +118 -0
  20. package/src/config/settings.ts +161 -0
  21. package/src/debate/debateContract.ts +89 -0
  22. package/src/debate/debateFanout.ts +285 -0
  23. package/src/debate/debateFile.ts +38 -0
  24. package/src/debate/debateResults.ts +115 -0
  25. package/src/debate/debateRounds.ts +61 -0
  26. package/src/debate/runDebate.ts +143 -0
  27. package/src/index.ts +283 -0
  28. package/src/moa/conflictContract.ts +49 -0
  29. package/src/moa/conflicts.ts +153 -0
  30. package/src/moa/contextContract.ts +52 -0
  31. package/src/moa/fanout.ts +152 -0
  32. package/src/moa/fanoutWiring.ts +88 -0
  33. package/src/moa/implementationRetry.ts +292 -0
  34. package/src/moa/modelRuntime.ts +87 -0
  35. package/src/moa/orchestration.ts +105 -0
  36. package/src/moa/planInfo.ts +57 -0
  37. package/src/moa/planlessRetry.ts +72 -0
  38. package/src/moa/reviewLoop.ts +170 -0
  39. package/src/moa/runContext.ts +118 -0
  40. package/src/moa/synthesis.ts +420 -0
  41. package/src/moa/verdicts.ts +81 -0
  42. package/src/moa/verification.ts +791 -0
  43. package/src/moa/verificationCriteria.ts +127 -0
  44. package/src/moa/verifyGate.ts +137 -0
  45. package/src/opinion/opinionContract.ts +21 -0
  46. package/src/opinion/opinionFanout.ts +135 -0
  47. package/src/opinion/opinionFile.ts +38 -0
  48. package/src/opinion/opinionResults.ts +73 -0
  49. package/src/opinion/runOpinion.ts +156 -0
  50. package/src/planning/askUserQuestion.ts +83 -0
  51. package/src/planning/instructions.ts +146 -0
  52. package/src/planning/modeState.ts +61 -0
  53. package/src/planning/planFile.ts +273 -0
  54. package/src/planning/planMode.ts +673 -0
  55. package/src/planning/tools/enterPlanMode.ts +165 -0
  56. package/src/planning/tools/exitPlanMode.ts +159 -0
  57. package/src/planning/tools/mfPlanSubagent.ts +311 -0
  58. package/src/planning/tools/shared.ts +19 -0
  59. package/src/planning/tools/writePlan.ts +33 -0
  60. package/src/runtime/activityTracking.ts +141 -0
  61. package/src/runtime/cancelRun.ts +134 -0
  62. package/src/runtime/mutationTripwire.ts +251 -0
  63. package/src/runtime/processPool.ts +55 -0
  64. package/src/runtime/results.ts +103 -0
  65. package/src/runtime/runner.ts +538 -0
  66. package/src/runtime/wire.ts +177 -0
  67. package/src/shared/functionKeys.ts +30 -0
  68. package/src/shared/modelRefs.ts +91 -0
  69. package/src/ui/agentStatus.ts +84 -0
  70. package/src/ui/agentTranscript.ts +112 -0
  71. package/src/ui/cancelOverlay.ts +191 -0
  72. package/src/ui/chrome.ts +151 -0
  73. package/src/ui/conflictOverlay.ts +363 -0
  74. package/src/ui/debateModelPicker.ts +273 -0
  75. package/src/ui/menu.ts +679 -0
  76. package/src/ui/moaModelPicker.ts +900 -0
  77. package/src/ui/moaProgressWidget.ts +910 -0
  78. package/src/ui/moaSetupOverlay.ts +368 -0
  79. package/src/ui/modelLabel.ts +61 -0
  80. package/src/ui/observeOverlay.ts +206 -0
  81. package/src/ui/opinionModelPicker.ts +246 -0
  82. package/src/ui/planReviewOverlay.ts +315 -0
  83. package/src/ui/promptEditor.ts +87 -0
  84. package/src/ui/rosterEditor.ts +310 -0
  85. package/src/ui/shimmer.ts +77 -0
  86. package/src/ui/toolActivity.ts +35 -0
  87. package/src/ui/twoPaneModelThinking.ts +272 -0
  88. package/src/ui/verificationFindingsOverlay.ts +137 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # Changelog
2
+
3
+ ## [0.1.0]
4
+
5
+ - Initial commit
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eric Sison
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,437 @@
1
+ # pi-topping-moa-fusion
2
+
3
+ A Pi extension built around **Mixture of Agents (MoA)** planning: several models independently explore your repo, each writes a complete implementation plan, and a synthesizer reconciles them into one stronger plan — surfacing every disagreement as a decision you get to make.
4
+
5
+ <img src="https://raw.githubusercontent.com/underactive/pi-topping-moa-fusion/main/docs/images/mf-plan-workflow-animated.svg" alt="/mf-plan workflow" width="100%">
6
+
7
+ ## Contents
8
+
9
+ - [Quick Start](#quick-start)
10
+ - [Screenshots](#screenshots)
11
+ - [Mixture of Agents (MoA)](#mixture-of-agents-moa)
12
+ - [Why prose, not code](#why-prose-not-code)
13
+ - [How a run works](#how-a-run-works)
14
+ - [How the synthesizer works](#how-the-synthesizer-works)
15
+ - [Implementation failures](#implementation-failures)
16
+ - [The MoA Fusion table](#the-moa-fusion-table)
17
+ - [Opinions (`/mf-opinion`)](#opinions-mf-opinion)
18
+ - [Debates (`/mf-debate`)](#debates-mf-debate)
19
+ - [Commands](#commands)
20
+ - [Cancelling running subagents](#cancelling-running-subagents)
21
+ - [Plan Mode](#plan-mode)
22
+ - [ask_user_question coordination](#ask_user_question-coordination)
23
+ - [Custom Tools](#custom-tools-available-in-plan-mode)
24
+ - [Subagents](#subagents)
25
+ - [Choosing their models](#choosing-their-models)
26
+ - [Parallel execution](#parallel-execution)
27
+ - [Plan File Location](#plan-file-location)
28
+ - [Non-Interactive Behavior](#non-interactive-behavior)
29
+ - [How It Works (Architecture)](#how-it-works-architecture)
30
+ - [Porting Notes](#porting-notes)
31
+
32
+ ## Quick Start
33
+
34
+ ```bash
35
+ pi install npm:@underactive/pi-topping-moa-fusion
36
+ ```
37
+
38
+ Run `/mf-plan`, describe what you want planned, and pick **Mixture of Agents** when the model picker opens. Assign your models in the **MoA Fusion Pre-flight** overview, then choose **Start fan-out**. In the prompt editor, Tab completes file paths and `@name` fuzzy-searches the repo when `fd` is available (pi's bundled copy, or `fd`/`fdfind` on your PATH); completions insert references, not file contents.
39
+
40
+ ## Screenshots
41
+
42
+ **MoA Fusion Pre-flight** — assign proposer, synthesizer, implementer, and verifier slots, or load a saved roster before starting fan-out.
43
+
44
+ ![MoA Fusion Pre-flight](https://raw.githubusercontent.com/underactive/pi-topping-moa-fusion/main/docs/images/demo1.png)
45
+
46
+ **MoA Fusion table** — watch proposers explore and plan in parallel while synthesis, implementation, and verification remain queued.
47
+
48
+ ![MoA Fusion table](https://raw.githubusercontent.com/underactive/pi-topping-moa-fusion/main/docs/images/demo2.png)
49
+
50
+ **Synthesized plan review** — inspect the reconciled plan's evaluation dimensions, proposer alignment, and synthesis decisions before approval.
51
+
52
+ ![Synthesized plan review — evaluation and alignment](https://raw.githubusercontent.com/underactive/pi-topping-moa-fusion/main/docs/images/demo3a.png)
53
+
54
+ **Synthesized plan detail** — review the concrete implementation steps produced from the merged proposals.
55
+
56
+ ![Synthesized plan review — synthesis decisions and plan](https://raw.githubusercontent.com/underactive/pi-topping-moa-fusion/main/docs/images/demo3b.png)
57
+
58
+ ## Mixture of Agents (MoA)
59
+
60
+ MoA is the reason this extension exists, and the mode it defaults to — the picker lists it first, and saving `/mf-plan-settings` sets it as your default. Up to 5 models each independently explore the repo and write their own complete implementation plan, then a synthesizer reconciles them into one.
61
+
62
+ It stays optional. Single-model planning is one keystroke away and runs the full 5-phase workflow on your active model. But MoA is worth preferring for anything non-trivial:
63
+
64
+ - **Independent proposals surface options one model won't.** Each proposer explores the repo on its own with no shared context, so they genuinely diverge on approach rather than converging on one model's first instinct.
65
+ - **Claims get checked.** The synthesizer has read-only repo access and verifies proposer claims about file paths, functions, and line numbers instead of trusting them — catching the confident-but-wrong details a single planner would carry straight into the plan.
66
+ - **Disagreements become your decision.** Where proposers took different approaches, you get an explicit conflict-review tab with the tradeoffs spelled out, instead of a silent choice buried in someone's plan.
67
+
68
+ The cost is real: an MoA run spends roughly N× the tokens of a single-model plan, takes as long as its slowest proposer, and wants several providers configured to be worth doing. For a one-line fix, use single model.
69
+
70
+ ### Why prose, not code
71
+
72
+ Fanning out a coding task and merging the resulting token streams does not work — different models produce wildly different code for the same problem, and any aggregator splicing them together introduces its own bias. MoA here never fuses code. Proposers write plans in prose, which is far easier to reconcile than syntax: a disagreement like "model A wants a migration, model B wants an in-place patch" is legible enough to evaluate on the merits. Code is written afterward, from the single merged plan, by one agent.
73
+
74
+ ### How a run works
75
+
76
+ 1. After you submit your plan prompt, a picker opens on a mode screen (**Mixture of Agents** or **Single model**). Single model — or Esc — runs the 5-phase workflow on the current model.
77
+ 2. MoA opens the **MoA Fusion Pre-flight** overview with all eight slots — five proposer slots plus a synthesizer, an implementer, and a verifier — starting empty at `(none)`, plus a **Load Roster** row above **Start fan-out** that applies a saved agent roster to every slot at once (see [Agent rosters](#agent-rosters)). Selecting any slot row opens a two-pane model/thinking picker for that one slot and returns to the overview; cancelling leaves the slot unchanged. **Start fan-out** stays disabled until you assign at least two proposer slots and all three required roles (the minimum roster; the same model may fill several slots, and the extra proposer slots are optional). Thinking levels come from the model's pi registry metadata, which is authoritative for every model the registry lists; the generic `off`/`low`/`medium`/`high` list applies only to models it doesn't. Your saved choices and active model only pre-highlight a slot's picker — they never count as assignments until you confirm them — and confirmed selections are remembered in `~/.pi/agent/mf-plan/settings.json`.
78
+ 3. Proposers run in parallel as isolated `moa-proposer` subprocesses. Each ends with an "Open Questions / Assumptions" section rather than pausing — proposers never block waiting on input.
79
+ 4. `moa-synthesizer` reads every successful proposal (at least 1 must succeed) plus the original request, and writes one merged plan.
80
+ 5. If the proposers substantively disagreed, a conflict-review overlay opens first: one tab per conflict, plain-language options, the synthesized pick tagged **(Recommended)**, and a **Chat about this** box for free-text feedback. Your resolutions are fed back for re-synthesis. Esc cancels the whole run.
81
+ 6. The plan opens in the same review overlay `exit_plan_mode` uses, where you can inspect any proposer's original plan, edit the synthesized one, or send the synthesizer feedback for a revised version (up to five rounds).
82
+ 7. On approval, the synthesizer makes one read-only pass to create a frozen observable checklist at `.pi/mf-plan/<slug>__criteria.md`, then plan mode exits and implementation begins in the current session using the implementer you already picked — there is **no** second picker (the single-model flow picks its implementing model up front when you choose **Single model**, and neither flow shows a model picker after approval — one appears only via `/mf-plan-implement`, or when an MoA run is resumed without a saved roster). If implementation fails (for example, auth expiration or provider error), an automatic recovery dialog prompts to retry, switch to a different model, or continue manually. You can also run `/mf-plan-implement` anytime to resume the approved plan.
83
+ 8. Once the implementation turn settles, the **verification phase** runs when a verifier is configured: the project's own `check` / `lint` / `test` scripts run first, then a read-only `moa-verifier` subprocess judges the working tree against the frozen approved plan and scores every frozen criterion pass/fail/cannot-verify. The overall verdict is derived from those scores. If criteria are unavailable, it falls back to judging plan steps directly. If it finds gaps (or a check fails), the repair prompt shows a short Simplified Technical English summary, then the verifier summary, unmet criteria or gaps, and failing project checks, followed in the TUI by three choices in order: *View full findings*, *Send verifier findings to the implementer* (a bounded **repair round**, up to two), and *Accept implementation as-is*. *View full findings* opens the complete verifier report in a read-only, scrollable popup and, when closed, returns to the same three choices, so viewing never consumes a repair round. A repair round sends the findings back to the implementer and re-verifies. The raw verdict is saved next to the plan as `<slug>__verification.md`. A user-cancelled implementation is never verified.
84
+
85
+ Before building the full verification task, MoA Fusion runs a cheap verifier preflight that asks for a one-word response. Auth, quota, model, and liveness problems therefore surface quickly with an actionable child error instead of after the full audit attempt.
86
+
87
+ **Verification troubleshooting.** If criteria generation fails, implementation continues and verification falls back to plan-step mode. If verification cannot complete, the dialog shows the underlying child error (including provider or spawn details), and failed output is saved at `.pi/mf-plan/<slug>__verification.md`.
88
+
89
+ ### How the synthesizer works
90
+
91
+ The synthesizer's contract (`agents/moa-synthesizer.md`) is to produce a new plan — selecting one proposal, or lightly editing a favorite, is defined as failure.
92
+
93
+ Several safeguards target known LLM judging biases:
94
+
95
+ - **Identity blinding** — proposals arrive headed `### Proposal from Proposer N`; real model names never appear in its input. This counters *self-preference bias*, where a model favors output it recognizes as its own. Enforcement runs both ways: proposers must not hint at their own model name, family, or provider, and the synthesizer must not infer or emit one — including in its own output, which keeps re-synthesis rounds blind too.
96
+ - **Separate evaluation dimensions** — proposals are judged on correctness, completeness, feasibility, risk, and simplicity as distinct dimensions rather than one overall impression. The prompt states outright that confidence, detail, and length are not evidence of quality, guarding against *verbosity bias*.
97
+ - **Agreement is signal, not proof** — where proposers agree, the synthesizer still sanity-checks the shared assumption against the repo, since independent models can share the same error.
98
+ - **Auditable reasoning** — the plan opens with a Context section recording dimension reasoning, proposer alignment, and synthesis decisions, so recombination choices are inspectable. Reconciliation commentary is confined there; the rest reads as one coherent plan. The orchestrator verifies all three subsections are present and rejects a first plan that omits them (one corrective retry, then a warning), the same way it enforces `## Proposer Verdicts`.
99
+ - **Disagreements go to the user** — every substantive disagreement must be emitted as a `## Conflicts` block, even when the synthesizer is confident, so its judgment is a default you can override rather than a decision made for you. Genuine ambiguity about *your intent* instead produces a single `## Open Question`, and the synthesizer is re-run with your answer.
100
+
101
+ **Protocol-internal, always current at runtime.** The proposer, synthesizer, and verifier prompts are tightly coupled to this extension's parsers and UI (e.g. the `## Conflicts` markup, and the verifier's `**Verdict:**`/`### Gaps` markup). A hand-edited copy under `~/.pi/agent/agents/` is still written for inspection, but MoA runs always use the bundled definition from the installed extension, so a protocol update can never desync from what the subprocess runs. `moa-explore` and `mf-plan` remain fully user-customizable.
102
+
103
+ ### Implementation failures
104
+
105
+ If the picked implementing model fails immediately upon kickoff (such as an expired session, auth failure, or provider outage), an automatic recovery prompt appears offering:
106
+ - **Retry with <model>** — retry kickoff with the same model.
107
+ - **Choose a different model** — pick a replacement model from the registry.
108
+ - **Continue manually** — keeps the plan safely saved on disk.
109
+
110
+ The approved plan is persisted across session restarts. You can run `/mf-plan-implement` at any time to re-send the approved plan and optionally pick a new implementing model.
111
+
112
+ ### The MoA Fusion table
113
+
114
+ When an MoA run starts, a `MoA Fusion` table pins itself above the editor and stays there for the whole run — proposer fan-out, synthesis, the in-session implementation turn, and verification. The plan's summarized name sits at the right of the title bar.
115
+
116
+ Under the title, a phase band traces the pipeline — `Plan › Synthesize › Implement › Verify` — with each phase's model beneath its name. The active phase shimmers. (The band's chevrons are Powerline glyphs; without a Nerd Font they render as boxes.)
117
+
118
+ Rows are grouped under `── Plan`, `── Synthesize`, `── Implement`, and `── Verify` headings, one row per model. Roles that have not started yet show as dim queued rows, so the table's shape is visible from the first second. Each row carries:
119
+
120
+ - **MODEL** — the provider/model reference.
121
+ - **CTX** — how much of that model's context window its latest turn is using.
122
+ - **MONITOR** — an activity meter of *generated output* rate, independent of CTX: an agent can be deep into its context window and idle, or near empty and generating hard. Uses provider-reported token counts when available, otherwise word counts of the streamed deltas. Each row's meter is tinted with the thinking level that row is running under, using that level's native theme colour (`off` through `max`), so you can read a row's effort at a glance; the hue is tracked per row, so the same model can show different colours in different slots and it follows retries, model swaps, verifier fallback, and resumed runs. A row whose level is unknown falls back to the neutral accent colour, and idle cells and settled traces keep their usual dimming under whichever hue applies.
123
+ - **ACTIVITY** — what the agent is doing, with its current tool call beneath, its tool name and argument highlighted with pi's own bold `toolTitle`/`accent` theme colours.
124
+ - **TURNS** / **TOOLS** / **COST** / **TIME** — assistant turns completed, tool calls started, registry-rate model cost, and elapsed time. All freeze when the agent settles.
125
+
126
+ While an agent is working, its row also shows a dim, guttered preview of the latest four wrapped lines from the same transcript used by Observe. The preview follows the newest output automatically; short terminals reduce or drop preview lines after preserving tool activity, and narrow terminals omit previews entirely.
127
+
128
+ Proposer and synthesizer rows are fed by the subagent processes. The Implement row is the model running in your own session: its turns, tool calls, output meter, and cost are collected live from pi's lifecycle events while the approved plan is being implemented. The Verify row is fed by the verifier subprocess; when you send verifier findings back to the implementer, the Implement row reactivates in the same table. The table closes when verification finishes, when an implementation is cancelled or paused with "Continue manually", or when the session shuts down.
129
+
130
+ Press `F2` or run `/mf-preview` to toggle the inline/live preview of streamed agent output shown under each row, or `F3` during a run to open a read-only observer of any agent's streamed output.
131
+
132
+ ### Opinions (`/mf-opinion`)
133
+
134
+ `/mf-opinion` asks up to five models the same repository question without entering plan mode or starting an implementation workflow:
135
+
136
+ 1. Enter a question directly (`/mf-opinion is this retry safe?`) or use the prompt editor. Tab completes file paths and `@name` fuzzy-searches the repo when `fd` is available (pi's bundled copy, or `fd`/`fdfind` on your PATH); completions insert references, not file contents.
137
+ 2. Assign 1–5 slots in **Select Opinion Models**. Duplicate model choices are allowed.
138
+ 3. Independent `moa-opinion` subprocesses inspect the repository in parallel with strict read-only tooling.
139
+ 4. After the last agent settles, every answer is appended verbatim to the transcript in slot order. Nothing synthesizes, judges, merges, or rewrites the opinions.
140
+
141
+ During the run, `F3` opens the live observer and `Esc` or `F4` opens cancellation controls. The prompt and combined result are saved under `.pi/mf-opinion/` as `<slug>__opinion-prompt.md` and `<slug>__opinions.md`.
142
+
143
+ ### Debates (`/mf-debate`)
144
+
145
+ `/mf-debate` runs a multi-round debate between up to five models — no judge, no synthesis, no implementation:
146
+
147
+ 1. Enter a topic directly (`/mf-debate is this retry safe?`) or use the prompt editor. Tab completes file paths and `@name` fuzzy-searches the repo when `fd` is available (pi's bundled copy, or `fd`/`fdfind` on your PATH); completions insert references, not file contents.
148
+ 2. Assign 2–5 slots in **Select Debating Models** and set the round ceiling (2–5, default 3) with `←`/`→` on the Rounds row. Duplicate model choices are allowed.
149
+ 3. Round 1: independent `moa-debater` subprocesses each form their own repo-grounded position with strict read-only tooling.
150
+ 4. Every later round, each surviving debater receives every other debater's prior position under anonymous `Debater N` labels and may rebut, concede, or change stance.
151
+ 5. The debate stops early when nobody moved in a round (from round 2 on) or fewer than two debaters remain. The full transcript — every round plus final positions — is appended verbatim to the session. Nothing judges or merges.
152
+
153
+ During the run, `F3` opens the live observer and `Esc` or `F4` opens cancellation controls. The prompt and combined transcript are saved under `.pi/mf-debate/` as `<slug>__debate-prompt.md` and `<slug>__debate.md`.
154
+
155
+ ## Commands
156
+
157
+ | Command | Shortcut | Description |
158
+ |---------|----------|-------------|
159
+ | `/mf-plan` | — | Toggle plan mode on/off |
160
+ | `/mf-opinion` | — | Ask 1–5 models for independent read-only opinions about the repository |
161
+ | `/mf-debate` | — | Run a read-only multi-round debate between up to 5 models |
162
+ | `/mf-preview` | — | Toggle the inline/live preview of streamed agent output |
163
+ | `/mf-plan-settings` | — | Configure the explore and cheap/fast agents, named agent rosters for the MoA roles, and plan options |
164
+ | `/mf-plan-implement` | — | Retry implementation of the last approved MoA plan, optionally with a different model |
165
+ | `/mf-plan-clear` | — | Clear completed plan state so the next `/mf-plan` starts a fresh round; approved plans stay in `.pi/mf-plan/` and remain re-implementable |
166
+ | `--mf-plan` | — | Start pi with plan mode enabled |
167
+ | — | `F2` (during MoA runs) | Toggle the inline/live preview of streamed agent output |
168
+ | — | `F3` (during MoA runs) | Open a read-only observer of streamed proposer/synthesizer output |
169
+ | — | `Esc` (during MoA runs) / `F4` | Open the cancel overlay: kill one stuck subagent or cancel all |
170
+
171
+ On Mac laptops the top row may send brightness/media keys by default. Enable the System Settings option to use the top row as standard function keys if the remaining function-key shortcuts do not work.
172
+
173
+ ### Cancelling running subagents
174
+
175
+ During an MoA fan-out or synthesis, **Esc** opens a cancel overlay. Enter kills the selected agent — its siblings keep going and synthesis proceeds with the surviving proposals; **Cancel ALL** aborts the run and reopens the prompt editor prefilled with your original prompt. Each agent's live tool call is highlighted the same way as the Fusion table's ACTIVITY column.
176
+
177
+ During the single-model workflow's `mf_plan_subagent` runs, plain Esc keeps pi's default abort-the-turn behavior; use **F4** to kill an individual agent instead. A cancelled agent reports "cancelled by user" back to the model, which continues with the other agents' results.
178
+
179
+ > While an MoA run is active this extension consumes Esc via a terminal-input listener, which may shadow another extension's Esc handling for the duration of the run.
180
+
181
+ ## Plan Mode
182
+
183
+ Both modes share the same plan-mode container. While it is active:
184
+
185
+ 1. **Read-only enforcement** — plan mode uses an explicit allowlist rather than disabling known mutators. Only read-only inspection tools and the custom plan-mode tools remain; generic subagent launchers and shell access are excluded.
186
+ 2. **5-phase workflow injected every turn:**
187
+ - **Phase 1: Initial Understanding** — launch parallel `moa-explore` subagents to search the codebase
188
+ - **Phase 2: Design** — launch `mf-plan` subagent(s) to design the implementation
189
+ - **Phase 3: Review** — read critical files, clarify requirements with the user
190
+ - **Phase 4: Final Plan** — write the finalized plan to disk
191
+ - **Phase 5: Exit** — call `exit_plan_mode` for user approval
192
+
193
+ This is the **single-model workflow**: the model you pick drives all five phases. [MoA](#mixture-of-agents-moa) replaces phases 1–2 with the proposer fan-out.
194
+ 3. **Per-session plan file** — one slug per session, persisted across `/resume`.
195
+ 4. **User approval** — `exit_plan_mode` prompts to approve or keep planning. Approving restores full tool access and hands the plan back to the model.
196
+
197
+ - A `● MoA Fusion (plan mode)` indicator sits in the footer while planning, and stays as `● MoA Fusion` through implementation and verification. Green: agents are working. Yellow: waiting for you (a prompt, an overlay, a questionnaire, or an idle plan-mode session). Red: a flow stopped with nothing left to try; it clears on your next turn or when you leave plan mode.
198
+
199
+ ### ask_user_question coordination
200
+
201
+ When an extension such as `rpiv-ask-user-question` registers the `ask_user_question` tool, MoA Fusion defers all in-plan clarification to it rather than drawing its own dialog. The plan-mode tools (`enter_plan_mode`, `exit_plan_mode`, `mf_plan_subagent`) run sequentially, so a same-message `ask_user_question` + `exit_plan_mode` resolves the questionnaire first — MoA Fusion's review overlay never opens on top of it. `exit_plan_mode` refuses with a pending-question error while a questionnaire is still waiting for answers. The slash commands, F3, and F4 warn instead of opening; **Esc** and **F4** during a `mf_plan_subagent` run pass through to the questionnaire. MoA orchestration prompts (synthesizer open questions, conflict review, review-loop plan review/chat editor, verification) are deliberately unaffected because they run while the session model is idle. Without the tool registered, the model asks for clarification in plain text and the injected instructions never name `ask_user_question`.
202
+
203
+ ## Custom Tools (Available in Plan Mode)
204
+
205
+ | Tool | Description |
206
+ |------|-------------|
207
+ | `write_plan` | Write/update the plan file (the only writable file) |
208
+ | `mf_plan_subagent` | Launch moa-explore/mf-plan subagents (single or parallel mode) |
209
+ | `exit_plan_mode` | Present plan for user approval and exit plan mode |
210
+ | `ask_user_question` | Ask structured questions — active only when an extension (e.g. `rpiv-ask-user-question`) registers it; MoA Fusion's plan-mode tools run sequentially so its own overlays never cover the questionnaire, and without it the model asks in plain text |
211
+
212
+ Outside plan mode, one additional tool is exposed:
213
+
214
+ | Tool | Description |
215
+ |------|-------------|
216
+ | `enter_plan_mode` | Lets the agent enter plan mode itself when asked for a design or plan. Takes the single-model path on the current session model — no pickers, no MoA. Exit and approval work exactly as if the user had invoked `/mf-plan`. |
217
+
218
+ ## Subagents
219
+
220
+ Seven agent definitions are auto-installed to `~/.pi/agent/agents/` on first run (won't overwrite existing files). Two belong to the single-model workflow, three to MoA planning, one to the independent opinion flow, and one to the debate flow:
221
+
222
+ | Agent | Workflow | Role | Model & thinking come from |
223
+ |-------|----------|------|----------------------------|
224
+ | `moa-proposer` | MoA fan-out | Explores the repo *and* writes a complete plan, one independent instance per slot | The per-slot picker at the start of each MoA run |
225
+ | `moa-synthesizer` | MoA synthesis | Reconciles every proposal into one plan | The synthesizer slot of the same picker |
226
+ | `moa-verifier` | MoA verification | Read-only; scores the frozen verification criteria against the implemented working tree, using the diff and `check`/`lint`/`test` results as evidence | The verifier slot of the same picker |
227
+ | `moa-opinion` | Opinion fan-out | Produces one independent, repo-grounded answer; no synthesis or adjudication follows | The selected `/mf-opinion` slot |
228
+ | `moa-debater` | Debate | Argues one side of a multi-round debate, seeing peers' labeled prior positions each round; may keep or change stance; no judge follows | The selected `/mf-debate` slot |
229
+ | `moa-explore` | Single-model (Phase 1) | Fast codebase recon | Its own frontmatter, via `/mf-plan-settings` (haiku by default) |
230
+ | `mf-plan` | Single-model (Phase 2) | Turns exploration context into a detailed plan | **The session's active model** — whatever you picked in the "Single model" picker. No settings slot |
231
+
232
+ MoA never invokes `moa-explore` or `mf-plan` — each `moa-proposer` is a self-contained fusion of both roles, doing its own exploration so the proposals stay independent. The plan-only tools (`write_plan`, `exit_plan_mode`, and `mf_plan_subagent`) are active only while `/mf-plan` or single-model plan mode is on.
233
+
234
+ Every planning subprocess is forced through a runtime `read,grep,find,ls` allowlist, even when an installed agent definition is stale, customized, or omits its `tools` field.
235
+
236
+ ### Choosing their models
237
+
238
+ `moa-explore` is the only agent whose frontmatter model is authoritative. `mf-plan` also carries a `model:` in its frontmatter, but it is only a fallback — the session's active model (set via `pi.setModel`) overrides it. The MoA agents carry no `model:` field at all.
239
+
240
+ ```yaml
241
+ ---
242
+ name: moa-explore
243
+ description: Fast codebase recon...
244
+ tools: read, grep, find, ls
245
+ model: anthropic/claude-haiku-4-5
246
+ thinking: off
247
+ ---
248
+ ```
249
+
250
+ `/mf-plan-settings` writes these two fields for you, but editing the file by hand works equally well — the overlay reads its current values back. An unrecognized `thinking:` value is ignored rather than passed to the subprocess.
251
+
252
+ #### Agent rosters
253
+
254
+ The MoA roles (proposers, synthesizer, implementer, verifier) are no longer assigned one-by-one in `/mf-plan-settings`. Instead the overlay's **agent rosters** row manages named rosters — reusable sets that assign a model + thinking level to every MoA role at once (2–5 proposers plus the three required roles; a roster must be complete to save). Each run, the picker's **Load Roster** row applies a roster to every slot wholesale — a 2-proposer roster also clears stale picks from slots 3–5 — and slots whose model is no longer callable are skipped with a warning while the rest load normally.
255
+
256
+ Rosters persist in `~/.pi/agent/mf-plan/settings.json`:
257
+
258
+ ```json
259
+ {
260
+ "rosters": [
261
+ {
262
+ "name": "team1",
263
+ "proposers": [
264
+ { "ref": { "provider": "anthropic", "id": "claude-opus-4-6" }, "thinking": "high" },
265
+ { "ref": { "provider": "google", "id": "gemini-3-pro" }, "thinking": "medium" }
266
+ ],
267
+ "synthesizer": { "ref": { "provider": "anthropic", "id": "claude-opus-4-6" }, "thinking": "high" },
268
+ "implementer": { "ref": { "provider": "anthropic", "id": "claude-opus-4-6" }, "thinking": "medium" },
269
+ "verifier": { "ref": { "provider": "anthropic", "id": "claude-haiku-4-5" }, "thinking": "off" }
270
+ }
271
+ ]
272
+ }
273
+ ```
274
+
275
+ Names are 1–24 alphanumeric characters, unique case-insensitively, up to 20 rosters. The roster manager stages every edit in memory — nothing is written until the settings overlay's **Save and Close**.
276
+
277
+ **First run.** Until the setup overlay has been saved once, `/mf-plan` opens it — set up agents and rosters before planning — instead of the plan prompt. Only interactive TUI sessions are gated; headless plan mode is unaffected.
278
+
279
+ **Agentic provider bridges.** Some pi providers are not plain chat-completion APIs but bridges to full coding agents with their *own* local edit/shell tools (e.g. pi-cursor-bridge, whose models run Cursor agents in the repo cwd). Pi's tool allowlist cannot restrain those agent-side tools, so plan mode adds two more layers:
280
+
281
+ - **Read-only env handshake** — every planning subprocess is spawned with `PI_CURSOR_FORCE_MODE=plan`, and the parent session sets it while plan mode is active. cursor-bridge maps this to Cursor's native read-only *plan* mode (SDK `mode: "plan"`; CLI `--mode plan` without `--force`).
282
+ - **Mutation tripwire** — `git status --porcelain` is snapshotted before subagents launch and re-checked after every phase. If the working tree changed while planning agents ran, a warning lists the touched files so rogue edits are never silently absorbed.
283
+
284
+ ### Parallel execution
285
+
286
+ In the single-model flow, Phase 1 launches up to **3 moa-explore agents in parallel** and Phase 2 up to **1 mf-plan agent**. Concurrency is capped at 5 simultaneous processes, with a per-task output cap of 50KB.
287
+
288
+ ```
289
+ mf_plan_subagent({
290
+ tasks: [
291
+ { agent: "moa-explore", task: "Find authentication modules and patterns" },
292
+ { agent: "moa-explore", task: "Explore middleware and hook patterns" }
293
+ ]
294
+ })
295
+ ```
296
+
297
+ ## Plan File Location
298
+
299
+ ```
300
+ ~/.pi/agent/mf-plan/plans/<word-slug>.md
301
+ ```
302
+
303
+ The slug is a generated adjective-adjective-noun triple (e.g. `happy-mellifluous-iguana`). One slug per session, persisted via `appendEntry` so `/resume` reuses the same file.
304
+
305
+ `/mf-plan-clear` rotates the session to a fresh empty slug so the next planning round starts without prefilling or re-entry instructions; old plan files under `~/.pi/agent/mf-plan/plans/` are kept, and the approved-plan handoff is preserved so `/mf-plan-implement` still works.
306
+
307
+ ## Non-Interactive Behavior
308
+
309
+ In non-interactive modes (`pi -p`, `--mode json`), `exit_plan_mode` is rejected unless `MOA_PLAN_AUTO_APPROVE=1` is set. With that explicit opt-in, it exits plan mode and hands the plan back without prompting. The plan file is still written to disk.
310
+
311
+ ## How It Works (Architecture)
312
+
313
+ ```
314
+ index.ts # Package entry point (re-exports src/index.ts)
315
+ src/
316
+ ├── index.ts # Thin composition entry
317
+ ├── activityMeter.ts # Dependency-free output-rate meter
318
+ ├── shared/
319
+ │ ├── modelRefs.ts # Model refs, thinking levels, display labels
320
+ │ └── functionKeys.ts # F-key press matching (incl. Kitty encoding)
321
+ ├── config/
322
+ │ ├── settings.ts # Persistent MoA settings
323
+ │ ├── rosters.ts # Agent-roster types, limits, and validation
324
+ │ ├── modelCatalogue.ts # Registry-backed selectable model cache
325
+ │ └── planName.ts # LLM-summarized plan names
326
+ ├── agents/
327
+ │ ├── discovery.ts # User/project agent discovery and parsing
328
+ │ ├── authoritative.ts # Bundled-agent resolution and installation
329
+ │ └── defaults.ts # Installed agent frontmatter defaults
330
+ ├── runtime/
331
+ │ ├── runner.ts # Isolated pi subprocess entry points
332
+ │ ├── processPool.ts # Process tracking, concurrency, kill escalation
333
+ │ ├── wire.ts # JSONL and usage-beacon parsing
334
+ │ ├── activityTracking.ts # Streaming output/activity assembly
335
+ │ ├── results.ts # Runner result classification/output helpers
336
+ │ ├── cancelRun.ts # Per-agent cancellation bookkeeping
337
+ │ └── mutationTripwire.ts # Working-tree mutation detection
338
+ ├── opinion/
339
+ │ ├── runOpinion.ts # Interactive opinion command orchestration
340
+ │ ├── opinionFanout.ts # Parallel read-only opinion agents and retry
341
+ │ ├── opinionContract.ts # Task/retry contract and output detection
342
+ │ ├── opinionResults.ts # Outcome collection and transcript markdown
343
+ │ └── opinionFile.ts # Repo-local opinion artifacts
344
+ ├── debate/
345
+ │ ├── runDebate.ts # Interactive debate command orchestration
346
+ │ ├── debateFanout.ts # Round loop over parallel read-only debater agents
347
+ │ ├── debateContract.ts # Opening/round task builders, stance parsing, retry
348
+ │ ├── debateRounds.ts # Survivor/early-stop/next-round bookkeeping
349
+ │ ├── debateResults.ts # Outcome collection and debate transcript markdown
350
+ │ └── debateFile.ts # Repo-local debate artifacts
351
+ ├── planning/
352
+ │ ├── planMode.ts # Plan-mode state transitions and lifecycle handlers
353
+ │ ├── modeState.ts # Persisted state shape, byte cap, append deduplication
354
+ │ ├── planFile.ts # Slugs, plan files, proposal staging
355
+ │ ├── instructions.ts # Injected 5-phase plan-mode instructions
356
+ │ ├── askUserQuestion.ts # rpiv questionnaire detection and blocked-state tracking
357
+ │ └── tools/
358
+ │ ├── shared.ts
359
+ │ ├── enterPlanMode.ts # Interactive entry flow, ESC listener, agent tool
360
+ │ ├── writePlan.ts
361
+ │ ├── exitPlanMode.ts
362
+ │ └── mfPlanSubagent.ts
363
+ ├── moa/
364
+ │ ├── orchestration.ts # Outer phase sequencer and run cleanup
365
+ │ ├── fanout.ts # Proposer fan-out and planless retry
366
+ │ ├── fanoutWiring.ts # Widget-backed parallel fan-out wiring
367
+ │ ├── synthesis.ts # Synthesis rounds, recovery, verdicts/conflicts
368
+ │ ├── reviewLoop.ts # Review/edit/chat/approve flow
369
+ │ ├── verification.ts # Post-implementation verify + bounded repair phase
370
+ │ ├── verificationCriteria.ts # Frozen criteria contract and generation
371
+ │ ├── verifyGate.ts # check/lint/test script gate + git-diff capture
372
+ │ ├── implementationRetry.ts # Implementation handoff, kickoff, retry flow
373
+ │ ├── runContext.ts # Explicit run-scoped mutable context and host API
374
+ │ ├── modelRuntime.ts # Provider/model resolution
375
+ │ ├── conflicts.ts # Conflict protocol parser
376
+ │ ├── conflictContract.ts # Conflict-surfacing task-text contract
377
+ │ ├── contextContract.ts # Context-subsection (auditable reasoning) contract
378
+ │ ├── planInfo.ts # Persisted MoA metadata validation
379
+ │ ├── verdicts.ts
380
+ │ └── planlessRetry.ts
381
+ └── ui/
382
+ ├── chrome.ts # Shared overlay frame/render primitives
383
+ ├── menu.ts
384
+ ├── agentStatus.ts
385
+ ├── twoPaneModelThinking.ts
386
+ ├── modelLabel.ts
387
+ ├── moaModelPicker.ts
388
+ ├── rosterEditor.ts # Staged agent-roster manager for /mf-plan-settings
389
+ ├── opinionModelPicker.ts
390
+ ├── debateModelPicker.ts
391
+ ├── moaSetupOverlay.ts
392
+ ├── moaProgressWidget.ts
393
+ ├── agentTranscript.ts # Shared Observe/inline-preview transcript formatting
394
+ ├── planReviewOverlay.ts
395
+ ├── conflictOverlay.ts
396
+ ├── observeOverlay.ts
397
+ ├── cancelOverlay.ts
398
+ ├── promptEditor.ts # File-path/@name completion editor
399
+ ├── shimmer.ts
400
+ ├── toolActivity.ts
401
+ └── verificationFindingsOverlay.ts
402
+
403
+ agents/ # Shipped agent definitions
404
+ ├── moa-explore.md
405
+ ├── mf-plan.md
406
+ ├── moa-opinion.md
407
+ ├── moa-debater.md
408
+ ├── moa-proposer.md
409
+ ├── moa-synthesizer.md
410
+ └── moa-verifier.md
411
+ ```
412
+
413
+ **Key design decisions:**
414
+ - **Custom `write_plan` tool** instead of path-guarded `edit`/`write` — guarantees the single-writable-file invariant.
415
+ - **Subprocess subagents** (not in-process) — each agent runs in an isolated `pi --mode json -p --no-session` subprocess with an enforced read-only tool allowlist.
416
+ - **State via `appendEntry`** — plan mode state (enabled, slug, tools snapshot) persists in the session for `/resume` and `/reload`.
417
+ - **Context injection via `before_agent_start`** — the 5-phase instructions are injected as a user message every turn while plan mode is active; the `context` hook strips stale plan-mode messages once it is off.
418
+ - **MoA proposers never pause mid-run** — subprocess subagents are one-shot, so a proposer that hits an ambiguity records it as an assumption and keeps going. Only the synthesizer, which sees every proposal, asks the user anything — keeping fan-out fully parallel.
419
+
420
+ ## Porting Notes
421
+
422
+ Ported from Claude Code's plan mode, adapted to pi's extension primitives:
423
+
424
+ | Claude Code | MoA Fusion | Notes |
425
+ |-------------|------------|-------|
426
+ | `getPlanModeV2Instructions` (messages.ts) | `src/planning/instructions.ts` | Adapted tool names, hardcoded agent counts |
427
+ | `ExitPlanModeV2Tool` | `exit_plan_mode` tool | Simplified: no teammate/mailbox approval routing |
428
+ | `plans.ts` (slug, file management) | `src/planning/planFile.ts` | Simplified: no CCR snapshot recovery |
429
+ | In-process Explore/Plan agents | Subprocess subagents | pi's subprocess pattern (isolated context) |
430
+ | `FileEditTool`/`FileWriteTool` guarded | Custom `write_plan` tool | Safer single-writable-file invariant |
431
+ | Subscription-tier agent counts | Hardcoded constants (3/1) | Bumpable via code change |
432
+ | Plan-length A/B experiment | Standard Phase 4 | Experiment noise skipped |
433
+ | Interview phase variant | Standard 5-phase workflow | Variant skipped |
434
+
435
+ ## License
436
+
437
+ MIT
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: mf-plan
3
+ description: Creates detailed implementation plans from exploration context and requirements. Read-only — never modifies files.
4
+ tools: read, grep, find, ls
5
+ model: claude-sonnet-4-5
6
+ ---
7
+
8
+ You are a planning specialist. You receive context (from explore agents) and requirements, then produce a clear implementation plan.
9
+
10
+ You must NOT make any changes. Only read, analyze, and plan.
11
+
12
+ Input format you'll receive:
13
+ - Context/findings from explore agents
14
+ - Original query or requirements
15
+
16
+ Output format:
17
+
18
+ ## Goal
19
+ One sentence summary of what needs to be done.
20
+
21
+ ## Plan
22
+ Numbered steps, each small and actionable:
23
+ 1. Step one - specific file/function to modify
24
+ 2. Step two - what to add/change
25
+ 3. ...
26
+
27
+ ## Files to Modify
28
+ - `path/to/file.ts` - what changes
29
+ - `path/to/other.ts` - what changes
30
+
31
+ ## New Files (if any)
32
+ - `path/to/new.ts` - purpose
33
+
34
+ ## Existing Code to Reuse
35
+ - `path/to/file.ts:functionName` - what it does and how to use it
36
+
37
+ ## Verification
38
+ How to test the changes end-to-end (specific commands, test files to run).
39
+
40
+ ## Risks
41
+ Anything to watch out for.
42
+
43
+ Keep the plan concrete and actionable. The plan should be detailed enough to execute verbatim but concise enough to scan quickly.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: moa-debater
3
+ description: Argues one side of a multi-round, read-only debate against other models without modifying files.
4
+ tools: read, grep, find, ls
5
+ ---
6
+
7
+ You are one of several debaters in a multi-round debate about a repository. Each round, every debater receives every other debater's clearly labeled prior position and may keep or change their stance. No judge, synthesizer, or verifier follows — your arguments are shown verbatim to the user and reach your peer debaters, so argue to convince them.
8
+
9
+ Round 1: form an independent, repo-grounded position. Explore the repository as needed with `read`, `grep`, `find`, and `ls`, and cite concrete evidence as `path/to/file:line`.
10
+
11
+ Later rounds: you receive every other debater's prior position under explicit `Debater N` labels. Rebut what you disagree with, concede what you cannot defend, and refine your position. Always state explicitly whether you kept or changed your stance relative to your own previous round. Never self-identify your model, family, or provider — your identity is your slot number only.
12
+
13
+ Never edit files and never run commands, builds, or tests. Having only read-only tools is expected and is never a blocker. You are running headless, so resolve open questions with clearly stated assumptions instead of asking the user or waiting for clarification.
14
+
15
+ Use this exact output structure:
16
+
17
+ ## Position
18
+
19
+ Your current argument as one clear paragraph.
20
+
21
+ ## Evidence
22
+
23
+ Ground the position in repository evidence, including `file:line` citations.
24
+
25
+ ## Responses to Other Debaters
26
+
27
+ (Rounds after the first.) Respond to each named `Debater N` position specifically — agreements, rebuttals, concessions.
28
+
29
+ ## Stance
30
+
31
+ **Stance:** initial | kept | switched | refined
32
+
33
+ **Sides with:** Debater N | none
34
+
35
+ ## Concessions & Open Points
36
+
37
+ What you concede to other debaters and what remains unresolved.
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: moa-explore
3
+ description: Fast codebase recon that returns compressed context for planning. Search for existing utilities, patterns, and architecture.
4
+ tools: read, grep, find, ls
5
+ model: claude-haiku-4-5
6
+ ---
7
+
8
+ You are a codebase explorer for a planning task. Quickly investigate a codebase and return structured findings that a planning agent can use without re-reading everything.
9
+
10
+ You must NOT make any changes. Only read, analyze, and report findings.
11
+
12
+ Your output will be passed to a planning agent who has NOT seen the files you explored.
13
+
14
+ Thoroughness (infer from task, default medium):
15
+ - Quick: Targeted lookups, key files only
16
+ - Medium: Follow imports, read critical sections
17
+ - Thorough: Trace all dependencies, check tests/types
18
+
19
+ Strategy:
20
+ 1. grep/find to locate relevant code
21
+ 2. Read key sections (not entire files)
22
+ 3. Identify types, interfaces, key functions
23
+ 4. Note dependencies between files
24
+ 5. **Actively search for existing functions, utilities, and patterns that can be reused** — avoid proposing new code when suitable implementations already exist
25
+
26
+ Output format:
27
+
28
+ ## Files Retrieved
29
+ List with exact line ranges:
30
+ 1. `path/to/file.ts` (lines 10-50) - Description of what's here
31
+ 2. `path/to/other.ts` (lines 100-150) - Description
32
+ 3. ...
33
+
34
+ ## Key Code
35
+ Critical types, interfaces, or functions:
36
+
37
+ ```typescript
38
+ interface Example {
39
+ // actual code from the files
40
+ }
41
+ ```
42
+
43
+ ```typescript
44
+ function keyFunction() {
45
+ // actual implementation
46
+ }
47
+ ```
48
+
49
+ ## Existing Patterns to Reuse
50
+ Any existing utilities, helper functions, or patterns that should be leveraged instead of writing new code.
51
+
52
+ ## Architecture
53
+ Brief explanation of how the pieces connect.
54
+
55
+ ## Start Here
56
+ Which file to look at first and why.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: moa-opinion
3
+ description: Produces an independent, repo-grounded opinion without modifying files.
4
+ tools: read, grep, find, ls
5
+ ---
6
+
7
+ You are one of several independent read-only analysts answering the same question about a repository. Your answer is shown verbatim to the user; no later agent merges, judges, or rewrites it.
8
+
9
+ Explore the repository as needed with `read`, `grep`, `find`, and `ls`. Cite concrete evidence as `path/to/file:line`. Commit to a clear opinion or recommendation rather than merely listing options.
10
+
11
+ Never edit files and never run commands, builds, or tests. Having only read-only tools is expected and is never a blocker. You are running headless, so answer open questions using clearly stated assumptions instead of asking the user or waiting for clarification.
12
+
13
+ Use this exact output structure:
14
+
15
+ ## Opinion
16
+
17
+ State your direct answer and recommendation.
18
+
19
+ ## Evidence
20
+
21
+ Ground the opinion in repository evidence, including `file:line` citations.
22
+
23
+ ## Alternatives Considered
24
+
25
+ Briefly explain credible alternatives and why they are weaker.
26
+
27
+ ## Assumptions & Caveats
28
+
29
+ State assumptions, uncertainty, and material limitations.