@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.
- package/LICENSE +21 -0
- package/README.md +527 -0
- package/SECURITY.md +91 -0
- package/config.yml +104 -0
- package/dist/neal/activity-footer.js +177 -0
- package/dist/neal/activity-reporting.js +1 -0
- package/dist/neal/adjudicator/artifacts.js +58 -0
- package/dist/neal/adjudicator/blocked-adjudicator.js +223 -0
- package/dist/neal/adjudicator/contracts.js +139 -0
- package/dist/neal/adjudicator/execute.js +611 -0
- package/dist/neal/adjudicator/final-completion.js +104 -0
- package/dist/neal/adjudicator/planning.js +145 -0
- package/dist/neal/adjudicator/specs.js +453 -0
- package/dist/neal/agents/prompts.js +120 -0
- package/dist/neal/agents/rounds.js +706 -0
- package/dist/neal/agents/schemas.js +832 -0
- package/dist/neal/agents/structured-coder.js +82 -0
- package/dist/neal/agents/structured-json.js +528 -0
- package/dist/neal/agents.js +4 -0
- package/dist/neal/atomic-write.js +18 -0
- package/dist/neal/blocked-guidance.js +406 -0
- package/dist/neal/cli.js +471 -0
- package/dist/neal/commands/check.js +401 -0
- package/dist/neal/commands/compat.js +807 -0
- package/dist/neal/commands/interactive-activity.js +57 -0
- package/dist/neal/commands/new-run.js +79 -0
- package/dist/neal/commands/plan-and-execute.js +44 -0
- package/dist/neal/commands/recovery-guidance.js +217 -0
- package/dist/neal/commands/resume-run.js +395 -0
- package/dist/neal/commands/review.js +21 -0
- package/dist/neal/commands/runtime.js +557 -0
- package/dist/neal/commands/setup.js +596 -0
- package/dist/neal/commands/squash.js +113 -0
- package/dist/neal/commands/status.js +33 -0
- package/dist/neal/commands/writer-exit-codes.js +42 -0
- package/dist/neal/commit-message.js +17 -0
- package/dist/neal/config.js +432 -0
- package/dist/neal/context/artifacts.js +140 -0
- package/dist/neal/context/context.js +324 -0
- package/dist/neal/context/inline-review-context.js +131 -0
- package/dist/neal/context/reviewer-context.js +166 -0
- package/dist/neal/context/shared.js +117 -0
- package/dist/neal/context/types.js +1 -0
- package/dist/neal/diagnostic.js +208 -0
- package/dist/neal/execute-finalization.js +5 -0
- package/dist/neal/final-completion-review.js +188 -0
- package/dist/neal/final-completion.js +229 -0
- package/dist/neal/git.js +339 -0
- package/dist/neal/index.js +135 -0
- package/dist/neal/interactive-controls.js +85 -0
- package/dist/neal/logger.js +102 -0
- package/dist/neal/manual-gates.js +121 -0
- package/dist/neal/orchestrator/artifacts.js +70 -0
- package/dist/neal/orchestrator/completion.js +531 -0
- package/dist/neal/orchestrator/failures.js +31 -0
- package/dist/neal/orchestrator/notifications.js +175 -0
- package/dist/neal/orchestrator/phases/coder.js +516 -0
- package/dist/neal/orchestrator/phases/planning.js +540 -0
- package/dist/neal/orchestrator/phases/recovery.js +798 -0
- package/dist/neal/orchestrator/phases/review.js +136 -0
- package/dist/neal/orchestrator/phases/shared.js +279 -0
- package/dist/neal/orchestrator/run-loop.js +113 -0
- package/dist/neal/orchestrator/split-plan.js +235 -0
- package/dist/neal/orchestrator/transitions.js +309 -0
- package/dist/neal/orchestrator.js +215 -0
- package/dist/neal/phase-display.js +27 -0
- package/dist/neal/plan-doc.js +154 -0
- package/dist/neal/plan-queue.js +1092 -0
- package/dist/neal/plan-refinement.js +39 -0
- package/dist/neal/plan-validation.js +525 -0
- package/dist/neal/progress.js +237 -0
- package/dist/neal/prompts/assert-builder.js +13 -0
- package/dist/neal/prompts/execute.js +290 -0
- package/dist/neal/prompts/guidance.js +70 -0
- package/dist/neal/prompts/planning.js +313 -0
- package/dist/neal/prompts/review-doctrine.js +142 -0
- package/dist/neal/prompts/shared.js +101 -0
- package/dist/neal/prompts/specialized.js +212 -0
- package/dist/neal/prompts/specs.js +572 -0
- package/dist/neal/providers/anthropic-claude.js +1599 -0
- package/dist/neal/providers/detection.js +139 -0
- package/dist/neal/providers/generic-agentic-tools.js +586 -0
- package/dist/neal/providers/generic-agentic.js +1238 -0
- package/dist/neal/providers/liveness.js +151 -0
- package/dist/neal/providers/openai-codex.js +1014 -0
- package/dist/neal/providers/openai-compatible.js +654 -0
- package/dist/neal/providers/registry.js +389 -0
- package/dist/neal/providers/telemetry.js +208 -0
- package/dist/neal/providers/types.js +21 -0
- package/dist/neal/recovery-artifacts.js +50 -0
- package/dist/neal/resume-decision.js +220 -0
- package/dist/neal/resume-planner.js +265 -0
- package/dist/neal/retrospective.js +391 -0
- package/dist/neal/review-debt.js +18 -0
- package/dist/neal/review-findings/artifacts.js +173 -0
- package/dist/neal/review-findings/prompts.js +172 -0
- package/dist/neal/review-findings/provider.js +330 -0
- package/dist/neal/review-findings/run.js +373 -0
- package/dist/neal/review-findings/types.js +1 -0
- package/dist/neal/review-mode.js +67 -0
- package/dist/neal/review.js +137 -0
- package/dist/neal/run-lock.js +334 -0
- package/dist/neal/run-metrics.js +355 -0
- package/dist/neal/run-narrative-types.js +1 -0
- package/dist/neal/run-narrative.js +1374 -0
- package/dist/neal/run-registry.js +218 -0
- package/dist/neal/run-status.js +25 -0
- package/dist/neal/scopes.js +451 -0
- package/dist/neal/sensitive-text.js +8 -0
- package/dist/neal/squash-message.js +379 -0
- package/dist/neal/squash.js +591 -0
- package/dist/neal/state-invariants.js +496 -0
- package/dist/neal/state-views.js +344 -0
- package/dist/neal/state.js +887 -0
- package/dist/neal/status-footer.js +258 -0
- package/dist/neal/status.js +1260 -0
- package/dist/neal/storage-paths.js +57 -0
- package/dist/neal/support.js +58 -0
- package/dist/neal/terminal-narrator.js +435 -0
- package/dist/neal/types.js +1 -0
- package/dist/neal/verification-events.js +81 -0
- package/dist/neal/version.js +37 -0
- package/dist/neal/worktree-status.js +137 -0
- package/dist/notifier.js +44 -0
- package/docs/ADJUDICATOR_INVENTORY.md +310 -0
- package/docs/PROMPT_SPECS.md +266 -0
- package/docs/README.md +22 -0
- package/docs/architecture.md +113 -0
- package/docs/assets/neal-execution-flow.png +0 -0
- package/docs/automation.md +65 -0
- package/docs/comparison.md +105 -0
- package/docs/compat.md +269 -0
- package/docs/compatible-models.md +135 -0
- package/docs/demo.md +55 -0
- package/docs/maintenance.md +64 -0
- package/docs/plan-format.md +213 -0
- package/docs/providers.md +751 -0
- package/docs/release.md +147 -0
- package/docs/state-machine.md +266 -0
- package/docs/storage.md +207 -0
- package/docs/troubleshooting.md +152 -0
- package/examples/compat/add-edit-verify/PLAN.md +29 -0
- package/examples/compat/add-edit-verify/broken.diff +8 -0
- package/examples/compat/add-edit-verify/good.diff +8 -0
- package/examples/compat/add-edit-verify/package.json +5 -0
- package/examples/compat/add-edit-verify/src/add.js +2 -0
- package/examples/compat/add-edit-verify/test/add.test.js +9 -0
- package/examples/compat/is-even-add-test/PLAN.md +30 -0
- package/examples/compat/is-even-add-test/broken.diff +11 -0
- package/examples/compat/is-even-add-test/good.diff +11 -0
- package/examples/compat/is-even-add-test/package.json +5 -0
- package/examples/compat/is-even-add-test/src/is-even.js +3 -0
- package/examples/compat/is-even-add-test/test/is-even.test.js +9 -0
- package/examples/compat/manifest.json +60 -0
- package/examples/compat/plan-greeting/ISSUE.md +25 -0
- package/examples/compat/plan-greeting/package.json +5 -0
- package/examples/compat/plan-greeting/src/greet.js +2 -0
- package/examples/compat/plan-greeting/test/greet.test.js +8 -0
- package/examples/compat/reverse-grep-edit/PLAN.md +32 -0
- package/examples/compat/reverse-grep-edit/broken.diff +12 -0
- package/examples/compat/reverse-grep-edit/good.diff +12 -0
- package/examples/compat/reverse-grep-edit/package.json +5 -0
- package/examples/compat/reverse-grep-edit/src/strings.js +10 -0
- package/examples/compat/reverse-grep-edit/test/strings.test.js +15 -0
- package/examples/issue-triage-js/PLAN.md +83 -0
- package/examples/issue-triage-js/README.md +76 -0
- package/examples/issue-triage-js/package.json +9 -0
- package/examples/issue-triage-js/src/issue-triage.js +87 -0
- package/examples/issue-triage-js/test/issue-triage.test.js +107 -0
- 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
|
+
[](https://github.com/navels/neal/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@navels/neal)
|
|
5
|
+
[](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
|
+

|
|
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
|
+

|
|
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.
|