@navels/neal 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 (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +527 -0
  3. package/SECURITY.md +91 -0
  4. package/config.yml +104 -0
  5. package/dist/neal/activity-footer.js +177 -0
  6. package/dist/neal/activity-reporting.js +1 -0
  7. package/dist/neal/adjudicator/artifacts.js +58 -0
  8. package/dist/neal/adjudicator/blocked-adjudicator.js +223 -0
  9. package/dist/neal/adjudicator/contracts.js +139 -0
  10. package/dist/neal/adjudicator/execute.js +611 -0
  11. package/dist/neal/adjudicator/final-completion.js +104 -0
  12. package/dist/neal/adjudicator/planning.js +145 -0
  13. package/dist/neal/adjudicator/specs.js +453 -0
  14. package/dist/neal/agents/prompts.js +120 -0
  15. package/dist/neal/agents/rounds.js +706 -0
  16. package/dist/neal/agents/schemas.js +832 -0
  17. package/dist/neal/agents/structured-coder.js +82 -0
  18. package/dist/neal/agents/structured-json.js +528 -0
  19. package/dist/neal/agents.js +4 -0
  20. package/dist/neal/atomic-write.js +18 -0
  21. package/dist/neal/blocked-guidance.js +406 -0
  22. package/dist/neal/cli.js +471 -0
  23. package/dist/neal/commands/check.js +401 -0
  24. package/dist/neal/commands/compat.js +807 -0
  25. package/dist/neal/commands/interactive-activity.js +57 -0
  26. package/dist/neal/commands/new-run.js +79 -0
  27. package/dist/neal/commands/plan-and-execute.js +44 -0
  28. package/dist/neal/commands/recovery-guidance.js +217 -0
  29. package/dist/neal/commands/resume-run.js +395 -0
  30. package/dist/neal/commands/review.js +21 -0
  31. package/dist/neal/commands/runtime.js +557 -0
  32. package/dist/neal/commands/setup.js +596 -0
  33. package/dist/neal/commands/squash.js +113 -0
  34. package/dist/neal/commands/status.js +33 -0
  35. package/dist/neal/commands/writer-exit-codes.js +42 -0
  36. package/dist/neal/commit-message.js +17 -0
  37. package/dist/neal/config.js +432 -0
  38. package/dist/neal/context/artifacts.js +140 -0
  39. package/dist/neal/context/context.js +324 -0
  40. package/dist/neal/context/inline-review-context.js +131 -0
  41. package/dist/neal/context/reviewer-context.js +166 -0
  42. package/dist/neal/context/shared.js +117 -0
  43. package/dist/neal/context/types.js +1 -0
  44. package/dist/neal/diagnostic.js +208 -0
  45. package/dist/neal/execute-finalization.js +5 -0
  46. package/dist/neal/final-completion-review.js +188 -0
  47. package/dist/neal/final-completion.js +229 -0
  48. package/dist/neal/git.js +339 -0
  49. package/dist/neal/index.js +135 -0
  50. package/dist/neal/interactive-controls.js +85 -0
  51. package/dist/neal/logger.js +102 -0
  52. package/dist/neal/manual-gates.js +121 -0
  53. package/dist/neal/orchestrator/artifacts.js +70 -0
  54. package/dist/neal/orchestrator/completion.js +531 -0
  55. package/dist/neal/orchestrator/failures.js +31 -0
  56. package/dist/neal/orchestrator/notifications.js +175 -0
  57. package/dist/neal/orchestrator/phases/coder.js +516 -0
  58. package/dist/neal/orchestrator/phases/planning.js +540 -0
  59. package/dist/neal/orchestrator/phases/recovery.js +798 -0
  60. package/dist/neal/orchestrator/phases/review.js +136 -0
  61. package/dist/neal/orchestrator/phases/shared.js +279 -0
  62. package/dist/neal/orchestrator/run-loop.js +113 -0
  63. package/dist/neal/orchestrator/split-plan.js +235 -0
  64. package/dist/neal/orchestrator/transitions.js +309 -0
  65. package/dist/neal/orchestrator.js +215 -0
  66. package/dist/neal/phase-display.js +27 -0
  67. package/dist/neal/plan-doc.js +154 -0
  68. package/dist/neal/plan-queue.js +1092 -0
  69. package/dist/neal/plan-refinement.js +39 -0
  70. package/dist/neal/plan-validation.js +525 -0
  71. package/dist/neal/progress.js +237 -0
  72. package/dist/neal/prompts/assert-builder.js +13 -0
  73. package/dist/neal/prompts/execute.js +290 -0
  74. package/dist/neal/prompts/guidance.js +70 -0
  75. package/dist/neal/prompts/planning.js +313 -0
  76. package/dist/neal/prompts/review-doctrine.js +142 -0
  77. package/dist/neal/prompts/shared.js +101 -0
  78. package/dist/neal/prompts/specialized.js +212 -0
  79. package/dist/neal/prompts/specs.js +572 -0
  80. package/dist/neal/providers/anthropic-claude.js +1599 -0
  81. package/dist/neal/providers/detection.js +139 -0
  82. package/dist/neal/providers/generic-agentic-tools.js +586 -0
  83. package/dist/neal/providers/generic-agentic.js +1238 -0
  84. package/dist/neal/providers/liveness.js +151 -0
  85. package/dist/neal/providers/openai-codex.js +1014 -0
  86. package/dist/neal/providers/openai-compatible.js +654 -0
  87. package/dist/neal/providers/registry.js +389 -0
  88. package/dist/neal/providers/telemetry.js +208 -0
  89. package/dist/neal/providers/types.js +21 -0
  90. package/dist/neal/recovery-artifacts.js +50 -0
  91. package/dist/neal/resume-decision.js +220 -0
  92. package/dist/neal/resume-planner.js +265 -0
  93. package/dist/neal/retrospective.js +391 -0
  94. package/dist/neal/review-debt.js +18 -0
  95. package/dist/neal/review-findings/artifacts.js +173 -0
  96. package/dist/neal/review-findings/prompts.js +172 -0
  97. package/dist/neal/review-findings/provider.js +330 -0
  98. package/dist/neal/review-findings/run.js +373 -0
  99. package/dist/neal/review-findings/types.js +1 -0
  100. package/dist/neal/review-mode.js +67 -0
  101. package/dist/neal/review.js +137 -0
  102. package/dist/neal/run-lock.js +334 -0
  103. package/dist/neal/run-metrics.js +355 -0
  104. package/dist/neal/run-narrative-types.js +1 -0
  105. package/dist/neal/run-narrative.js +1374 -0
  106. package/dist/neal/run-registry.js +218 -0
  107. package/dist/neal/run-status.js +25 -0
  108. package/dist/neal/scopes.js +451 -0
  109. package/dist/neal/sensitive-text.js +8 -0
  110. package/dist/neal/squash-message.js +379 -0
  111. package/dist/neal/squash.js +591 -0
  112. package/dist/neal/state-invariants.js +496 -0
  113. package/dist/neal/state-views.js +344 -0
  114. package/dist/neal/state.js +887 -0
  115. package/dist/neal/status-footer.js +258 -0
  116. package/dist/neal/status.js +1260 -0
  117. package/dist/neal/storage-paths.js +57 -0
  118. package/dist/neal/support.js +58 -0
  119. package/dist/neal/terminal-narrator.js +435 -0
  120. package/dist/neal/types.js +1 -0
  121. package/dist/neal/verification-events.js +81 -0
  122. package/dist/neal/version.js +37 -0
  123. package/dist/neal/worktree-status.js +137 -0
  124. package/dist/notifier.js +44 -0
  125. package/docs/ADJUDICATOR_INVENTORY.md +310 -0
  126. package/docs/PROMPT_SPECS.md +266 -0
  127. package/docs/README.md +22 -0
  128. package/docs/architecture.md +113 -0
  129. package/docs/assets/neal-execution-flow.png +0 -0
  130. package/docs/automation.md +65 -0
  131. package/docs/comparison.md +105 -0
  132. package/docs/compat.md +269 -0
  133. package/docs/compatible-models.md +135 -0
  134. package/docs/demo.md +55 -0
  135. package/docs/maintenance.md +64 -0
  136. package/docs/plan-format.md +213 -0
  137. package/docs/providers.md +751 -0
  138. package/docs/release.md +147 -0
  139. package/docs/state-machine.md +266 -0
  140. package/docs/storage.md +207 -0
  141. package/docs/troubleshooting.md +152 -0
  142. package/examples/compat/add-edit-verify/PLAN.md +29 -0
  143. package/examples/compat/add-edit-verify/broken.diff +8 -0
  144. package/examples/compat/add-edit-verify/good.diff +8 -0
  145. package/examples/compat/add-edit-verify/package.json +5 -0
  146. package/examples/compat/add-edit-verify/src/add.js +2 -0
  147. package/examples/compat/add-edit-verify/test/add.test.js +9 -0
  148. package/examples/compat/is-even-add-test/PLAN.md +30 -0
  149. package/examples/compat/is-even-add-test/broken.diff +11 -0
  150. package/examples/compat/is-even-add-test/good.diff +11 -0
  151. package/examples/compat/is-even-add-test/package.json +5 -0
  152. package/examples/compat/is-even-add-test/src/is-even.js +3 -0
  153. package/examples/compat/is-even-add-test/test/is-even.test.js +9 -0
  154. package/examples/compat/manifest.json +60 -0
  155. package/examples/compat/plan-greeting/ISSUE.md +25 -0
  156. package/examples/compat/plan-greeting/package.json +5 -0
  157. package/examples/compat/plan-greeting/src/greet.js +2 -0
  158. package/examples/compat/plan-greeting/test/greet.test.js +8 -0
  159. package/examples/compat/reverse-grep-edit/PLAN.md +32 -0
  160. package/examples/compat/reverse-grep-edit/broken.diff +12 -0
  161. package/examples/compat/reverse-grep-edit/good.diff +12 -0
  162. package/examples/compat/reverse-grep-edit/package.json +5 -0
  163. package/examples/compat/reverse-grep-edit/src/strings.js +10 -0
  164. package/examples/compat/reverse-grep-edit/test/strings.test.js +15 -0
  165. package/examples/issue-triage-js/PLAN.md +83 -0
  166. package/examples/issue-triage-js/README.md +76 -0
  167. package/examples/issue-triage-js/package.json +9 -0
  168. package/examples/issue-triage-js/src/issue-triage.js +87 -0
  169. package/examples/issue-triage-js/test/issue-triage.test.js +107 -0
  170. package/package.json +70 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Lee Nave
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,527 @@
1
+ # neal
2
+
3
+ [![CI](https://github.com/navels/neal/actions/workflows/ci.yml/badge.svg)](https://github.com/navels/neal/actions/workflows/ci.yml)
4
+ [![npm version](https://img.shields.io/npm/v/@navels/neal.svg)](https://www.npmjs.com/package/@navels/neal)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
+
7
+ > **A source-first, multi-agent coding loop.** Separate **planner**, **coder**, and **reviewer** roles — each on the provider and model you choose — drive scoped, reviewed, crash-safe changes to your repository.
8
+
9
+ ![neal driving a planner/coder/reviewer run](https://raw.githubusercontent.com/navels/neal/main/assets/neal-demo.gif)
10
+
11
+ neal is a source-first local planner/coder/reviewer loop for your repo. You write a plan; neal refines it with your configured planner role, runs each scope with your configured coder role, commits the result, and hands the diff to your configured reviewer role before moving on. When every scope is accepted, a final review pass checks the whole plan, and run artifacts stay under `.neal/` so interrupted work can resume.
12
+
13
+ ### What makes it interesting
14
+
15
+ - **Roles, not one monolithic agent.** Planner, coder, and reviewer are independent, separately configurable roles — mix vendors and models per role (e.g. Codex codes, Claude reviews).
16
+ - **The reviewer is read-only** — declared at provider registration and enforced mechanically in each adapter (OS sandbox for Codex, SDK tool allowlist for Claude, a neal-owned jailed toolset for OpenRouter models), pinned by a conformance test — never just prompt-deep. See [SECURITY.md](SECURITY.md) and [docs/providers.md](docs/providers.md).
17
+ - **`neal compat`** — a built-in harness that qualifies any OpenAI-compatible / OpenRouter model across all three roles and emits a dated PASS/FAIL whitelist. See [docs/compatible-models.md](docs/compatible-models.md).
18
+ - **Crash-safe and resumable** — every run's state and artifacts live under `.neal/`; `neal resume` continues an interrupted run.
19
+ - **Bounded autonomous recovery** — neal resolves a class of reviewer/coder deadlocks itself, and escalates genuine blockers.
20
+
21
+ For how the pieces fit together, see the [architecture overview](docs/architecture.md).
22
+ Wondering how this differs from Claude Code, Aider, or OpenHands? See
23
+ [docs/comparison.md](docs/comparison.md).
24
+
25
+ **Contents:** [Quickstart](#quickstart) ·
26
+ [Why neal exists](#why-neal-exists) ·
27
+ [neal is built with neal](#neal-is-built-with-neal) ·
28
+ [Installation](#installation) ·
29
+ [Provider Setup](#provider-setup) ·
30
+ [Command Tour](#command-tour) ·
31
+ [Commands](#commands) ·
32
+ [Exit Codes](#command-exit-codes) ·
33
+ [Configuration](#configuration) ·
34
+ [Artifacts](#artifacts-and-storage) ·
35
+ [Plan Shape](#plan-shape) ·
36
+ [Safety Notes](#safety-notes)
37
+
38
+ ## Quickstart
39
+
40
+ ```bash
41
+ npm install -g @navels/neal
42
+ neal setup # pick providers for the coder and reviewer roles
43
+ neal check # verify config and provider readiness
44
+ ```
45
+
46
+ The cheapest way to try neal is a single OpenRouter API key — no Codex or
47
+ Claude subscription required: run `neal setup --provider generic-agentic
48
+ --all-roles`, set `OPENAI_COMPATIBLE_API_KEY`, and pick a model from the
49
+ [qualified-model whitelist](docs/compatible-models.md). The flagship
50
+ configuration — Codex writes, Claude reviews — uses those two locally
51
+ authenticated CLIs instead; see [Provider Setup](#provider-setup).
52
+
53
+ From a Git repository with at least one commit, write a minimal plan and run
54
+ it:
55
+
56
+ ```md
57
+ # Add a project description
58
+
59
+ ## Execution Shape
60
+
61
+ executionShape: one_shot
62
+
63
+ ## Objective
64
+
65
+ Add a one-line project description to the top of README.md and keep the
66
+ existing content unchanged.
67
+ ```
68
+
69
+ ```bash
70
+ neal run PLAN.md
71
+ ```
72
+
73
+ neal refines the plan through the planner/reviewer loop, executes each scope
74
+ with a fresh-context coder, has the reviewer judge every diff before moving
75
+ on, and persists run state under `.neal/` — interrupt it any time and
76
+ `neal resume` continues where it stopped. Plan shapes, queues, and loops:
77
+ [docs/plan-format.md](docs/plan-format.md). If something misbehaves:
78
+ [docs/troubleshooting.md](docs/troubleshooting.md).
79
+
80
+ ## Why neal exists
81
+
82
+ neal grew out of a large frontend upgrade (Ember 3.28 to Ember 5) where the agent would drift over time from its initial instructions, which led to me wanting to break up the work into smaller chunks and reset the agent context before each chunk. I also wanted to incorporate my typical manual workflow of having Claude review Codex's work, copy/pasting findings and responses until both agents were satisfied with the result, before reviewing myself. I settled on this flow for neal:
83
+
84
+ - start with a plan of what work needs to be done and how to do it
85
+ - neal sends this through the planner/reviewer loop to ensure it is broken into manageable chunks (aka scopes) and formatted for execution by neal
86
+ - each scope is run through the coder/reviewer loop with the coder starting with a fresh context
87
+ - when the reviewer is satisfied, neal moves on to the next scope with the previous scope committed
88
+ - after all scopes are complete, the entire set of changes is run through the coder/reviewer loop a final time
89
+ - if a scope is found to be too large, the coder can split it into a sub-plan
90
+ - if the coder is blocked on something, it can consult the reviewer for assistance
91
+ - if neal exits for any reason, `neal resume` will attempt to continue, prompting for direction if the coder was blocked
92
+ - run artifacts and state are recorded in `.neal/`
93
+
94
+ ![neal execution flow](docs/assets/neal-execution-flow.png)
95
+
96
+ The name comes from `anneal`: repeated controlled adjustment toward a more stable result.
97
+
98
+ ## neal is built with neal
99
+
100
+ neal's development is its own primary proof. The blocked-handling redesign in
101
+ this release — replacing an ad-hoc support loop with the unified, budgeted
102
+ blocked adjudicator — was planned, implemented, and reviewed by neal driving
103
+ itself: Codex wrote each scope from a fresh context, Claude reviewed every
104
+ diff, and the run artifacts under `.neal/` were the working record. Much of
105
+ the code and documentation in this repository was written by coding agents
106
+ under human direction; the architecture, the judgment calls, and the final
107
+ review are human.
108
+
109
+ The public repository begins at a single squashed commit because the
110
+ pre-release history carried private working context; it is preserved
111
+ privately. From v0.1.0 forward, development happens in the open — including
112
+ runs where neal maintains neal.
113
+
114
+ ## Installation
115
+
116
+ ```bash
117
+ npm install -g @navels/neal
118
+ ```
119
+
120
+ neal requires Node.js >= 22.13 and drives your configured provider CLIs/SDKs
121
+ (OpenAI Codex, Anthropic Claude, or any OpenAI-compatible / OpenRouter model) —
122
+ see [Provider Setup](#provider-setup). On Windows, run neal from WSL2 with the
123
+ target repository on the Linux filesystem; direct PowerShell or cmd.exe
124
+ operation is not a supported launch path.
125
+
126
+ ### Run from source / contribute
127
+
128
+ ```bash
129
+ corepack enable && pnpm install && pnpm start -- help
130
+ ```
131
+
132
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for contributor setup, the development
133
+ link, verification commands, CI gates, and canonical doc references.
134
+
135
+ ## Provider Setup
136
+
137
+ neal delegates planning, coding, and reviewing to provider-owned local runtimes, selected by provider id in the `agent.coder.provider` and `agent.reviewer.provider` config keys. The planner inherits the coder provider/model unless `agent.planner` is configured explicitly. Each provider still owns its credentials, account state, model availability, permissions, quotas, and rate limits.
138
+
139
+ | Provider id | Roles it serves | What you need | Docs |
140
+ | --- | --- | --- | --- |
141
+ | `openai-codex` | planner, coder, reviewer | Local OpenAI Codex runtime, authenticated through its own provider-owned setup | [docs/providers.md](docs/providers.md) |
142
+ | `anthropic-claude` | planner, coder, reviewer | Local Anthropic Claude runtime, authenticated through its own provider-owned setup | [docs/providers.md](docs/providers.md) |
143
+ | `openai-compatible` | reviewer only (API-only: no repository tools — neal inlines diff/artifact context — no session resume, no `effort`) | Any OpenAI-compatible Chat Completions endpoint (DeepSeek, OpenRouter, vLLM, and similar) via the `providers.openai_compatible` config block; env fallbacks `OPENAI_COMPATIBLE_BASE_URL`, `OPENAI_COMPATIBLE_API_KEY`, `OPENAI_COMPATIBLE_MODEL` | [docs/providers.md](docs/providers.md#openai-compatible-endpoints) |
144
+ | `generic-agentic` | coder (and the inherited planner); reviewer through a read-only toolset | The same `providers.openai_compatible` block plus a strong tool-calling model | [docs/providers.md](docs/providers.md#generic-agentic-writer), [docs/compat.md](docs/compat.md) |
145
+
146
+ For `generic-agentic`, neal owns the agentic loop and supplies its own file/search/shell tools, so the endpoint only needs reliable tool calling; its reviewer inspects the repository directly through read-only tools instead of judging inlined context — prefer it over `openai-compatible` for reviewer duty when the model calls tools reliably. It never persists provider sessions (`neal resume` restarts the interrupted scope from scratch in a fresh session) and runs with the same trust level as the other writer providers — its coder-role `run` tool is unsandboxed shell. Use paid tool-calling model slugs for coder duty; `:free` pools are reviewer-only. Before trusting a generic-agentic model with real work, qualify it with `neal compat` (see [docs/compat.md](docs/compat.md)) to confirm it can drive the full loop.
147
+
148
+ Run setup once before first writer-run use:
149
+
150
+ ```bash
151
+ neal setup
152
+ ```
153
+
154
+ `neal setup` detects local runtime availability for built-in providers without making live provider calls, asks for coder and reviewer defaults, and writes explicit `agent.coder` and `agent.reviewer` provider/model settings to `~/.neal/config.yml`. The planner inherits coder by default; interactive setup asks before writing an explicit planner override. To script the same provider for every role:
155
+
156
+ ```bash
157
+ neal setup --provider anthropic-claude --all-roles
158
+ ```
159
+
160
+ When a model is omitted, setup writes `model: null` so the provider chooses its default model. Existing effective provider settings are not overwritten unless you confirm interactively or pass `--force`.
161
+
162
+ Authenticate or configure each provider through its normal provider-owned local setup before running provider-backed workflows such as `neal plan`, `neal execute`, `neal run`, or `neal resume`. Neal does not collect or store provider credentials. Provider contract details are in [docs/providers.md](docs/providers.md). External provider adapters are future work.
163
+
164
+ After setup, verify local config and provider readiness:
165
+
166
+ ```bash
167
+ neal check
168
+ ```
169
+
170
+ After the config passes, `neal check` prints the effective planner/coder/reviewer roles and prompts before sending one small prompt to each configured role for live connectivity verification. In non-interactive shells, it validates config and reports that live provider verification was skipped. Common setup and auth failures, with their exact messages and fixes, are collected in [docs/troubleshooting.md](docs/troubleshooting.md).
171
+
172
+ ## Command Tour
173
+
174
+ Writer commands require a Git repository with an existing `HEAD` commit before
175
+ provider execution. Create and commit the repository's initial baseline before
176
+ asking neal to plan, run, execute, resume, or squash work.
177
+
178
+ Use `neal plan` and `neal execute` separately when you want to review the
179
+ normalized plan document before execution:
180
+
181
+ ```bash
182
+ neal plan PLAN.md
183
+ neal execute PLAN.md
184
+ neal execute PLAN.md --no-squash
185
+ ```
186
+
187
+ Refine and execute one or more plans serially:
188
+
189
+ ```bash
190
+ neal run tmp/A.md tmp/B.md
191
+ neal run --no-squash tmp/A.md tmp/B.md
192
+ ```
193
+
194
+ Run headless (CI, cron, or a benchmark harness) with no operator available to
195
+ answer an operator block:
196
+
197
+ ```bash
198
+ neal execute PLAN.md --unattended
199
+ neal run --unattended tmp/A.md tmp/B.md
200
+ ```
201
+
202
+ Try the dependency-free in-repo example without provider calls:
203
+
204
+ ```bash
205
+ pnpm --dir examples/issue-triage-js test
206
+ ```
207
+
208
+ To run the same example through Neal after configuring providers:
209
+
210
+ ```bash
211
+ neal setup
212
+ neal check
213
+ cd examples/issue-triage-js
214
+ neal run PLAN.md
215
+ pnpm test
216
+ ```
217
+
218
+ See [examples/issue-triage-js/README.md](examples/issue-triage-js/README.md)
219
+ for the example guide and safety notes.
220
+
221
+ Resume interrupted work:
222
+
223
+ ```bash
224
+ neal resume
225
+ neal resume --run <run-id>
226
+ ```
227
+
228
+ Give guidance only when `neal status` or `neal resume` says the selected run is waiting for it:
229
+
230
+ ```bash
231
+ neal resume --run <run-id> --message "Keep the change bounded to the failing test and rerun the required validation gate."
232
+ ```
233
+
234
+ Review already-committed work:
235
+
236
+ ```bash
237
+ neal review --last 3
238
+ neal review "Focus on auth/session handling." --since origin/main
239
+ ```
240
+
241
+ Inspect status:
242
+
243
+ ```bash
244
+ neal status
245
+ neal status --run <run-id>
246
+ neal status --json --run <run-id>
247
+ neal status --all
248
+ neal status --json --all
249
+ ```
250
+
251
+ ## Automation Contract
252
+
253
+ neal keeps a stable machine-facing contract for driving it from scripts, CI, and benchmark harnesses: writer exit codes, the `neal status --json` classification schema, patch-submission eligibility, and harness timeout and trace-publishing guidance. See [docs/automation.md](docs/automation.md).
254
+
255
+ ## Commands
256
+
257
+ ```bash
258
+ neal setup
259
+ neal plan <plan.md> [--unattended]
260
+ neal execute <plan.md> [--no-squash] [--unattended]
261
+ neal run [--no-squash] [--unattended] <plan.md> [more-plans...]
262
+ neal resume [--run <run-id>] [--message "..."]
263
+ neal review [message] (--last <n> | --since <base>)
264
+ neal squash [plan.md]
265
+ neal check
266
+ neal compat [--model <slug>] [--role coder|reviewer|planner|all] [--reference openai-codex|anthropic-claude|generic-agentic:<slug>] [--json]
267
+ neal status [--json] [--run <run-id>]
268
+ neal status [--json] --all
269
+ neal version
270
+ neal help
271
+ neal --help
272
+ neal -h
273
+ ```
274
+
275
+ `neal plan` revises the target plan file in place and stores the original-plan backup at `.neal/runs/<run-id>/PLAN_ORIGINAL.md`.
276
+
277
+ `neal execute` runs an already-ready plan. It requires a Git repository with at least one commit and no dirty work outside the selected plan document, and can edit files and create commits. When the selected plan document is repo-local, nonignored, and changed, neal may include it in the run's final tree through ordinary Git staging. Ignored, missing, non-file, or outside-repository plan documents are recorded as metadata only and are not force-added. Completed execute runs squash run-owned commits by default without confirmation; pass `--no-squash` to leave the individual commits in place.
278
+
279
+ `neal run` refines each plan through the planning loop, then executes the accepted plan. It requires a Git repository with at least one commit and uses the same clean-worktree admission as `neal execute`: dirty work outside the selected plan document blocks writer-run start and queue continuation. Queue items run serially. The queue stops at the first blocked, failed, paused, or operator-attention run. Execution children use the same selected-plan-document handling as `neal execute`: eligible repo-local nonignored plan documents may land in the final run tree, while ignored or outside-repository plans remain metadata-only. Execution children squash completed run-owned commits by default; pass `--no-squash` to preserve per-scope commits.
280
+
281
+ `neal resume` continues the selected writer run when it is mechanically resumable, including ordinary failed, paused, and stale-running states. With no `--run`, neal uses the current local run pointer. If the run is waiting for operator guidance, `neal resume` and `neal status` explain the blocker and print the exact `neal resume --run <run-id> --message "..."` command. `--message` is reserved for that waiting-guidance state.
282
+
283
+ If a coder scope reaches expected human work that Neal cannot perform itself, the run can wait in `waiting_for_manual_gate`. `neal status` shows the gate title, reason, run-local `GATE-<id>.md` instructions file, last failed check if any, and the resume command. `neal resume --run <run-id>` runs the gate's configured noninteractive command checks before provider execution; failed checks keep the gate open, and passing checks clear the gate and resume the same coder scope. Manual gates do not use `neal resume --message`.
284
+
285
+ ### Unattended Mode
286
+
287
+ `--unattended` (on `neal plan`, `neal execute`, and `neal run`) runs Neal
288
+ headlessly — CI, cron, or a benchmark harness — when no operator is available:
289
+ eligible blocks auto-resume for a small bounded number of turns with a fixed
290
+ conservative guidance message, and the operator review gates fail cleanly and
291
+ terminally (exit code `3`, produced artifacts left unsubmitted) instead of
292
+ waiting for `neal resume --message`; verification, authorization, and the
293
+ squash/grading paths are never weakened. The resolved value is persisted on run
294
+ state, so a later `neal resume` and the `neal run` plan→execute hand-off keep
295
+ the same behavior without re-passing the flag. The squash preference
296
+ (`--no-squash`) is likewise persisted on run state across resume. See
297
+ [config.yml](config.yml) for the `agent.unattended` config key (default
298
+ `false`; the flag overrides it) and [docs/state-machine.md](docs/state-machine.md)
299
+ for the operator-block and gate states.
300
+
301
+ `neal review` never mutates your repository: candidate findings are drafted on the coder provider and judged by the read-only reviewer, and neal verifies after every provider call that the worktree and neal's own run state are byte-unchanged, failing the review otherwise. It uses neal's built-in adversarial review posture by default; the optional positional message is additive context. The selector is resolved when the command starts, and neal reviews commits ending at the current checkout `HEAD` for `--last` or `--since`. Dirty worktrees are allowed because the selected committed range is the review target. Accepted findings are printed to the terminal and written under `.neal/reviews/<review-id>/`.
302
+
303
+ `neal squash` squashes run-owned commits for a completed plan. With no argument, it selects the latest completed execute-mode run with readable run-local state and uses that run's recorded plan doc. With a plan argument, it selects the latest completed execute-mode run for that plan. It preserves later commits added after the selected neal run by replaying them on top of the replacement squash commit. It previews the selected run, commit range, later commits to preserve, plan-document disposition, commit-message source, and generated semantic commit message, then requires interactive TTY confirmation before rewriting history. The replacement commit is signed when Git signing is configured for commits. Squash result artifacts keep Neal provenance separately from the Git commit message, including the run id, selected and normalized plan paths, plan-document disposition, replacement-tree inclusion, commit-message source, and commit-message subject.
304
+
305
+ `neal setup` configures explicit coder and reviewer provider defaults for fresh writer runs, with an optional planner override. It reports local runtime availability, writes `~/.neal/config.yml` by default, preserves unrelated user config, and recommends provider-owned authentication followed by `neal check` after writing.
306
+
307
+ `neal check` validates the effective config, reports the effective planner, coder, and reviewer provider/model choices, then prompts before making live provider connectivity calls. When the resolved **coder or reviewer** role uses a non-native (generic-agentic / openai-compatible) provider, it prints a one-line pointer to `neal compat`; native adapters (`openai-codex`/`anthropic-claude`) do not. (The planner inherits the coder provider by default, so the coder check already covers the common case; an explicitly configured non-native planner alongside native coder/reviewer is not separately flagged.)
308
+
309
+ `neal compat` is a **compatibility smoke test, not a skill benchmark**: it answers whether an OpenAI-compatible model can drive neal's loop at all as a coder, reviewer, or planner. It reuses `neal check`'s structured pre-filter, then drives the candidate through complete neal runs against bundled trivial fixtures (`examples/compat/`) in throwaway git copies (it never mutates a committed fixture), and emits a binary PASS/FAIL matrix per (model, role) with a structural failure mode for each FAIL. `--model <slug>` runs the slug on the `generic-agentic` provider in the candidate role, and `--reference <id>` names a native provider (`openai-codex` default, or `anthropic-claude`) for the non-candidate roles so a FAIL is attributable to the candidate; `--role` defaults to `all`; `--json` prints a stable machine-readable matrix. It is fully self-contained — the only prerequisites are the neal repo and an API key — forces unattended mode so a model is never penalized for a resumable halt, and exits non-zero on an overall FAIL. See [docs/compat.md](docs/compat.md) for the PASS definition, failure-mode taxonomy, and `--json` schema, and [docs/compatible-models.md](docs/compatible-models.md) for the verified-model whitelist.
310
+
311
+ `neal status` prints a human-readable summary by default. `neal status --all` lists writer runs from `.neal/runs/*/RUN_STATE.json`. `neal status --json` and `neal status --json --all` are the stable automation contracts. Runs waiting on manual gates report `effectiveStatus: "waiting_for_manual_gate"` and include a nullable `manualGate` summary with the gate instructions path and resume command.
312
+
313
+ `neal version` prints the package version.
314
+
315
+ `neal help`, `neal --help`, and `neal -h` print the supported usage surface, including the package version.
316
+
317
+ ## Command Exit Codes
318
+
319
+ The writer commands `neal plan`, `neal execute`, `neal run`, and `neal resume`
320
+ use this shell contract:
321
+
322
+ - `0`: completed writer run, completed `neal run` queue, or resume selection
323
+ that was already done.
324
+ - `1`: invalid CLI usage, missing setup or configuration, pre-run Git/worktree
325
+ precondition failure, or another thrown error before Neal has a writer result.
326
+ - `2`: controlled incomplete state: blocked, waiting for operator guidance,
327
+ waiting for a manual gate, paused, already running under a live lock, or
328
+ manual-gate resume checks still failing.
329
+ - `3`: failed writer run or failed `neal run` queue after Neal has run
330
+ state/result evidence.
331
+
332
+ Use `neal status --json` for the stable detailed automation interface. `neal
333
+ status` exits `0` when it successfully reports status, even if the reported run
334
+ is blocked, paused, waiting for guidance, waiting for a manual gate, or failed.
335
+
336
+ ## Terminal Output
337
+
338
+ neal prints narrative-focused progress by default. The default stream says what the loop is doing at a human level, while raw provider detail, command output, session handles, and reviewer context are kept out of the normal terminal view.
339
+
340
+ Interactive TTY writer runs accept live keys:
341
+
342
+ - `q`: stop after the current scope
343
+ - `v`: switch between narrative and low-level detail views
344
+
345
+ The read-only long-running `neal review` command also supports the `v` detail toggle. Toggling views is process-local terminal state only; provider prompts, run state, resume behavior, artifacts, and command semantics stay unchanged.
346
+
347
+ Low-level detail is still persisted for debugging. Inspect `.neal/runs/<run-id>/stderr.log` and `.neal/runs/<run-id>/events.ndjson` for writer runs, or the corresponding review artifact directory for read-only review loops.
348
+
349
+ ## Configuration
350
+
351
+ Config precedence is:
352
+
353
+ 1. repo `config.yml`
354
+ 2. `~/.neal/config.yml`
355
+ 3. built-in defaults
356
+
357
+ Fresh writer-run commands require explicit `agent.coder.provider` and `agent.reviewer.provider` settings from either user or repo config. The built-in defaults remain for compatibility paths, but they are not enough to start new plan, execute, run, or check workflows. If either role is missing, neal reports the missing config key. Use `neal setup` for first-time provider/model defaults; edit YAML manually only when you need precise control.
358
+
359
+ The checked-in [config.yml](config.yml) is a commented template. Machine-local overrides usually belong in `~/.neal/config.yml`.
360
+
361
+ Manual writer-provider config shape:
362
+
363
+ ```yaml
364
+ agent:
365
+ coder:
366
+ provider: openai-codex
367
+ model: null
368
+ reviewer:
369
+ provider: anthropic-claude
370
+ model: null
371
+ ```
372
+
373
+ In that simple config, the effective planner role inherits the coder provider
374
+ and model:
375
+
376
+ ```yaml
377
+ agent:
378
+ planner:
379
+ provider: openai-codex
380
+ model: null
381
+ coder:
382
+ provider: openai-codex
383
+ model: null
384
+ reviewer:
385
+ provider: anthropic-claude
386
+ model: null
387
+ ```
388
+
389
+ `model: null` means "let the provider choose its default model." You can keep other settings, such as `neal.notify_bin`, in the same file. neal currently ships built-in writer-run adapters for OpenAI Codex and Anthropic Claude, plus two adapters for OpenAI-compatible Chat Completions endpoints: the reviewer-only `openai-compatible` adapter and the `generic-agentic` writer adapter, which runs the coder role through a neal-owned agentic loop and tool set and the reviewer role through a read-only subset of those tools. See [docs/providers.md](docs/providers.md) for the provider contract, capability checks, telemetry/error mapping, and testing checklist.
390
+
391
+ The reviewer role can target an OpenAI-compatible endpoint with a `providers.openai_compatible` block (DeepSeek shown; config first, environment fallbacks `OPENAI_COMPATIBLE_BASE_URL`, `OPENAI_COMPATIBLE_API_KEY`, and `OPENAI_COMPATIBLE_MODEL`):
392
+
393
+ ```yaml
394
+ providers:
395
+ openai_compatible:
396
+ base_url: https://api.deepseek.com
397
+ api_key_env: DEEPSEEK_API_KEY
398
+ default_model: deepseek-chat
399
+
400
+ agent:
401
+ coder:
402
+ provider: openai-codex
403
+ model: null
404
+ reviewer:
405
+ provider: openai-compatible
406
+ model: deepseek-chat
407
+ ```
408
+
409
+ `openai-compatible` is reviewer/structured-advisor only: coder or planner selection fails the capability check, it has no repository tool access (neal inlines diff and artifact context into reviewer prompts, so the reviewer cannot independently run verification), no session resume, and no `effort` support. Behavior, model quality, and rate limits vary by upstream provider.
410
+
411
+ Advanced configs can override the planner independently:
412
+
413
+ ```yaml
414
+ agent:
415
+ planner:
416
+ provider: openai-codex
417
+ model: gpt-plan
418
+ coder:
419
+ provider: openai-codex
420
+ model: gpt-code
421
+ reviewer:
422
+ provider: anthropic-claude
423
+ model: null
424
+ ```
425
+
426
+ Each role also accepts an optional `effort` reasoning-depth override. Omitting it
427
+ or setting `effort: null` keeps the provider default. Supported values are
428
+ `minimal, low, medium, high, xhigh` for `openai-codex` and
429
+ `low, medium, high, xhigh, max` for `anthropic-claude`; an unsupported value is
430
+ rejected before a run starts. Planner effort inheritance mirrors planner model
431
+ inheritance: the planner inherits the coder effort only when
432
+ `agent.planner.provider` is not configured explicitly and `agent.planner.effort`
433
+ is omitted. When `agent.planner.provider` is set explicitly, an omitted
434
+ `agent.planner.effort` resolves to the provider default (`null`), so set
435
+ `agent.planner.effort` explicitly to override it.
436
+
437
+ ```yaml
438
+ agent:
439
+ coder:
440
+ provider: openai-codex
441
+ model: null
442
+ effort: high
443
+ reviewer:
444
+ provider: anthropic-claude
445
+ model: null
446
+ effort: xhigh
447
+ ```
448
+
449
+ ### Custom Guidance
450
+
451
+ neal supports additive guidance files for local preferences alongside the built-in protocol prompts:
452
+
453
+ - `~/.neal/guidance/coder.md`
454
+ - `~/.neal/guidance/reviewer.md`
455
+ - `~/.neal/guidance/planner.md`
456
+
457
+ Set `NEAL_GUIDANCE_DIR=/path/to/guidance` to load those same `coder.md`, `reviewer.md`, and `planner.md` files from another directory. neal records applied guidance roles, selected paths, and byte counts in run artifacts; guidance contents stay out of terminal output.
458
+
459
+ ## Artifacts And Storage
460
+
461
+ Writer run artifacts live under `.neal/runs/<run-id>/`, including the original-plan backup at `.neal/runs/<run-id>/PLAN_ORIGINAL.md` and reviewer scratch space under `.neal/runs/<run-id>/scratch/`. Queue artifacts live under `.neal/queues/<queue-id>/`. Review findings artifacts live under `.neal/reviews/<review-id>/`.
462
+
463
+ Reviewer scratch is for temporary verification artifacts, copied tests, scratch builds, logs, and modified throwaway files. Root-level scratch directories such as `build_review/` are still ordinary project-tree dirtiness and must be cleaned up by the operator or committed through the normal accepted-scope flow.
464
+
465
+ Project-local `.neal/` is the source of truth for runs, queues, reviews, progress, and audit history. Keep `.neal/` ignored by Git. It may contain prompts, diffs, command output, local paths, provider responses, reviewer scratch files, copied tests, build logs, and project-specific context. Use `neal status --all` to discover run IDs, and use `--run <run-id>` to select a run for `resume` or `status`.
466
+
467
+ For what may (and may not) be published from a run as public automation or benchmark traces, see [docs/automation.md](docs/automation.md).
468
+
469
+ The storage layout, artifact classifications, run pointers, and retention guidance are documented in [docs/storage.md](docs/storage.md). Persisted run and queue state boundaries are documented in [docs/state-machine.md](docs/state-machine.md).
470
+
471
+ ## Known Limitations
472
+
473
+ - Writer providers currently run with broad local permissions. See [docs/providers.md](docs/providers.md) and Safety Notes for the current provider permission boundaries.
474
+ - neal stores project-local artifacts under `.neal/`. Those artifacts may contain prompts, diffs, command output, paths, provider responses, and local context; see [docs/storage.md](docs/storage.md) for artifact retention and privacy details.
475
+ - External provider plugins are future work.
476
+ - Provider accounts and authentication come from local provider SDK/CLI sessions.
477
+
478
+ ## Plan Shape
479
+
480
+ Every executable neal plan must declare exactly one execution shape in a literal `## Execution Shape` section.
481
+ The full executable-plan format reference is [docs/plan-format.md](docs/plan-format.md).
482
+
483
+ Use `executionShape: one_shot` when the full task can be implemented, reviewed, and verified as one bounded scope:
484
+
485
+ ```md
486
+ ## Execution Shape
487
+
488
+ executionShape: one_shot
489
+ ```
490
+
491
+ Use `executionShape: multi_scope` when the work is a finite ordered queue:
492
+
493
+ ```md
494
+ ## Execution Shape
495
+
496
+ executionShape: multi_scope
497
+
498
+ ## Execution Queue
499
+
500
+ ### Scope 1: Add parser support
501
+ - Goal: Parse the new contract safely.
502
+ - Verification: `pnpm typecheck`
503
+ - Success Condition: The parser accepts valid input and rejects malformed input.
504
+
505
+ ### Scope 2: Add regression coverage
506
+ - Goal: Lock the new behavior in with tests.
507
+ - Verification: `pnpm test`
508
+ - Success Condition: The new path is covered and existing shapes still pass.
509
+ ```
510
+
511
+ Use `executionShape: multi_scope_unknown` when the work repeats one bounded recurring slice at a time, but the total number of slices is intentionally unknown until a stop rule becomes true.
512
+
513
+ ## Safety Notes
514
+
515
+ Writer commands can edit files and create commits in the target repository. Run neal in a disposable checkout, branch, worktree, container, or VM when the repository or provider credentials are sensitive.
516
+
517
+ Current writer providers run with broad local permissions. The OpenAI Codex provider is configured with `approvalPolicy: never` and `sandboxMode: danger-full-access`; the Claude provider uses `permissionMode: bypassPermissions`. Treat planner and coder providers as capable of modifying the checkout unless you have added external sandboxing. The reviewer role is read-only — OS-sandboxed for the Codex reviewer, and enforced at the SDK/tool-wiring level for the others, so outside Codex the guarantee is only as strong as the adapter. Reviewers can also read files outside the repository unless the adapter jails reads (only `generic-agentic` does); see [SECURITY.md](SECURITY.md).
518
+
519
+ `neal execute` and `neal run` can create commits and rewrite run-owned commits into a final squash commit by default. Squashed commit messages are semantic summaries of the implemented project change; plan provenance is kept in Neal artifacts instead of commit subjects, bullets, or trailers. Repo-local nonignored selected plan documents may be included in the run's final tree when they changed. Ignored, missing, non-file, or outside-repository plan documents are metadata-only and are not force-added. `neal squash` rewrites history for plan-owned commits after printing a preview and receiving interactive confirmation. Neal rejects finalization and squash attempts that would include files matching `.gitignore` rules, even if those files were force-added.
520
+
521
+ Read-only commands are intentionally narrower: `neal status` and `neal review` skip the writer lock. `neal review` writes only review artifacts under `.neal/reviews/`.
522
+
523
+ Roles carry very different privilege: the coder role (and the inherited planner) executes shell commands and writes files with your privileges in the working directory, while the reviewer role is structurally read-only, enforced per provider adapter. Running an unknown or untrusted model in the coder role — for example via `neal compat` against an arbitrary OpenAI-compatible / OpenRouter slug — grants that model coder-level shell access, so run untrusted models inside a container or disposable sandbox. See [SECURITY.md](SECURITY.md) for the full trust model and how to report a suspected vulnerability.
524
+
525
+ ## Notifications
526
+
527
+ Notifications are opt-in. If `neal.notify_bin` is configured, neal runs that command with the notification text for `blocked`, `complete`, `done`, and `retry`. With no configured path, notifications stay disabled.
package/SECURITY.md ADDED
@@ -0,0 +1,91 @@
1
+ # Security
2
+
3
+ neal is a local planner/coder/reviewer loop that delegates work to
4
+ provider-owned agent runtimes on your machine. This document describes neal's
5
+ trust model so you can run it safely, and how to report a suspected
6
+ vulnerability.
7
+
8
+ ## Trust Model
9
+
10
+ neal assigns providers to roles, and the roles have very different privilege
11
+ levels. Understand this boundary before pointing neal at a sensitive repository
12
+ or an untrusted model.
13
+
14
+ ### Coder role: full local privileges
15
+
16
+ The coder role (and the planner, which inherits the coder provider by default)
17
+ executes shell commands and writes files with the **invoking user's
18
+ privileges** in the working directory. neal does not add its own sandbox around
19
+ these providers:
20
+
21
+ - The Claude coder runs with `permissionMode: bypassPermissions`.
22
+ - The Codex coder runs with `approvalPolicy: never` and
23
+ `sandboxMode: danger-full-access`.
24
+ - The `generic-agentic` coder drives a neal-owned agentic loop whose `run` tool
25
+ is unsandboxed shell.
26
+
27
+ Treat any provider acting in the coder or planner role as capable of running
28
+ arbitrary commands and modifying anything the current user can reach, unless you
29
+ have added external sandboxing yourself.
30
+
31
+ ### Reviewer role: read-only
32
+
33
+ The reviewer role is **read-only**, enforced in two layers:
34
+
35
+ - **Declared capability.** Every provider definition must declare its reviewer
36
+ (structured-advisor) capability with `write:false, shell:false`; the registry
37
+ validates this at every provider resolution, so a writable reviewer
38
+ definition cannot be handed out.
39
+ - **Adapter wiring.** Each adapter enforces the declaration mechanically:
40
+ - The Codex reviewer runs under `sandboxMode: read-only`, which Codex
41
+ enforces with an OS-level sandbox (Seatbelt on macOS, Landlock on Linux) —
42
+ the strongest guarantee of the four.
43
+ - The Claude reviewer is limited to the `Read`, `Grep`, and `Glob` tools at
44
+ the SDK level; no write or shell tool exists in the reviewer session.
45
+ - The `generic-agentic` reviewer is bound to a neal-owned read-only toolset
46
+ (`read_file`, `list_dir`, `grep`, and a read-only `git_diff` over a commit
47
+ range); write and shell tools are absent from that toolset by construction.
48
+ - The `openai-compatible` reviewer has no tools at all; it judges
49
+ neal-inlined context.
50
+
51
+ Both layers are pinned by tests, including a registry-driven conformance test
52
+ (`test/reviewer-readonly-conformance.test.ts`) that fails if a provider is
53
+ registered without read-only wiring verification. Apart from the OS-sandboxed
54
+ Codex reviewer, enforcement is process-level (SDK and tool wiring), not an
55
+ external sandbox, so it is only as strong as the adapter and the runtime under
56
+ it.
57
+
58
+ **Read-only is not read-jailed.** Only the `generic-agentic` reviewer restricts
59
+ *reads* to the repository (path-jailed, with symlink resolution). The Claude
60
+ and Codex reviewers can read anything the invoking user can read — including
61
+ files outside the repository such as `~/.ssh` or cloud credentials — and file
62
+ contents they read are sent to the provider's API. On sensitive machines,
63
+ follow the conservative guidance in the README
64
+ [Safety Notes](README.md#safety-notes): run neal in a disposable checkout,
65
+ branch, worktree, container, or VM.
66
+
67
+ **`neal review` drafts with the coder.** The read-only `neal review` command
68
+ judges findings with the read-only reviewer adapter, but the agent that
69
+ *drafts* candidate findings runs on the coder provider with coder privileges.
70
+ neal verifies after every drafting call that the worktree and neal's own run
71
+ state are byte-unchanged and fails the review otherwise — detection, not
72
+ prevention. See [docs/providers.md](docs/providers.md) for the exact guarantee
73
+ split.
74
+
75
+ ### Untrusted or unknown models
76
+
77
+ Running an unknown or untrusted model in the coder role — for example via
78
+ `neal compat` against an arbitrary OpenAI-compatible / OpenRouter slug on the
79
+ `generic-agentic` provider — grants that model **coder-level unsandboxed shell
80
+ access** in the working directory. Run untrusted models inside a container or
81
+ disposable sandbox; do not point a coder-role untrusted model at a repository or
82
+ machine you care about.
83
+
84
+ See [docs/providers.md](docs/providers.md) for the per-provider permission
85
+ boundaries, capability checks, and adapter contracts.
86
+
87
+ ## Reporting a Vulnerability
88
+
89
+ Please report suspected vulnerabilities **privately**, not in public issues. Use
90
+ the GitHub repository's Security Advisories "Report a vulnerability" flow so the
91
+ report stays confidential until a fix is available.