@navels/neal 0.1.0 → 0.3.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/README.md +206 -209
- package/SECURITY.md +16 -19
- package/dist/neal/adjudicator/{blocked-adjudicator.js → consultant.js} +21 -21
- package/dist/neal/adjudicator/execute.js +33 -33
- package/dist/neal/adjudicator/final-completion.js +2 -31
- package/dist/neal/adjudicator/planning.js +264 -24
- package/dist/neal/agents/prompts.js +7 -15
- package/dist/neal/agents/rounds.js +51 -73
- package/dist/neal/agents/schemas.js +615 -502
- package/dist/neal/agents/structured-json.js +36 -0
- package/dist/neal/blocked-guidance.js +16 -9
- package/dist/neal/cli.js +2 -2
- package/dist/neal/commands/check.js +2 -2
- package/dist/neal/commands/compat.js +100 -36
- package/dist/neal/commands/interactive-activity.js +2 -2
- package/dist/neal/commands/recovery-guidance.js +20 -8
- package/dist/neal/commands/runtime.js +4 -2
- package/dist/neal/config.js +40 -7
- package/dist/neal/context/inline-review-context.js +13 -28
- package/dist/neal/context/reviewer-context.js +19 -14
- package/dist/neal/eval/reviewer-eval-manifest.js +86 -0
- package/dist/neal/eval/reviewer-eval.js +155 -0
- package/dist/neal/git.js +9 -3
- package/dist/neal/interactive-controls.js +5 -0
- package/dist/neal/orchestrator/completion.js +215 -113
- package/dist/neal/orchestrator/failures.js +7 -0
- package/dist/neal/orchestrator/notifications.js +9 -9
- package/dist/neal/orchestrator/phases/planning.js +124 -112
- package/dist/neal/orchestrator/phases/recovery.js +151 -115
- package/dist/neal/orchestrator/phases/review.js +28 -1
- package/dist/neal/orchestrator/split-plan.js +12 -11
- package/dist/neal/orchestrator/transitions.js +36 -71
- package/dist/neal/orchestrator.js +3 -0
- package/dist/neal/plan-doc.js +24 -1
- package/dist/neal/plan-queue.js +29 -1
- package/dist/neal/prompts/assert-builder.js +8 -1
- package/dist/neal/prompts/execute.js +11 -19
- package/dist/neal/prompts/planning.js +64 -55
- package/dist/neal/prompts/review-doctrine.js +13 -50
- package/dist/neal/prompts/specialized.js +28 -22
- package/dist/neal/prompts/specs.js +223 -17
- package/dist/neal/providers/agent-settings-isolation.js +35 -0
- package/dist/neal/providers/anthropic-claude.js +309 -248
- package/dist/neal/providers/detection.js +3 -7
- package/dist/neal/providers/git-config-isolation.js +83 -0
- package/dist/neal/providers/openai-codex.js +102 -204
- package/dist/neal/providers/{generic-agentic-tools.js → openai-compatible-tools.js} +11 -5
- package/dist/neal/providers/openai-compatible.js +1079 -403
- package/dist/neal/providers/openrouter-routing.js +68 -0
- package/dist/neal/providers/pricing.js +124 -0
- package/dist/neal/providers/rate-card.js +2275 -0
- package/dist/neal/providers/registry.js +6 -17
- package/dist/neal/providers/telemetry.js +4 -0
- package/dist/neal/providers/types.js +12 -0
- package/dist/neal/resume-decision.js +7 -6
- package/dist/neal/resume-planner.js +9 -0
- package/dist/neal/retrospective.js +36 -7
- package/dist/neal/review-debt.js +30 -0
- package/dist/neal/review-findings/provider.js +17 -29
- package/dist/neal/review.js +17 -1
- package/dist/neal/run-metrics.js +74 -9
- package/dist/neal/state-invariants.js +11 -3
- package/dist/neal/state-views.js +27 -5
- package/dist/neal/state.js +59 -15
- package/dist/neal/status.js +28 -1
- package/dist/neal/support.js +3 -3
- package/docs/README.md +22 -18
- package/docs/{ADJUDICATOR_INVENTORY.md → adjudicator-inventory.md} +58 -57
- package/docs/architecture.md +79 -83
- package/docs/automation.md +11 -11
- package/docs/compat.md +91 -61
- package/docs/compatible-models.md +145 -110
- package/docs/demo.md +15 -5
- package/docs/maintenance.md +74 -32
- package/docs/plan-format.md +61 -33
- package/docs/prompt-evals.md +96 -0
- package/docs/{PROMPT_SPECS.md → prompt-specs.md} +52 -48
- package/docs/providers.md +330 -283
- package/docs/release.md +43 -40
- package/docs/review-convergence.md +246 -0
- package/docs/state-machine.md +61 -59
- package/docs/storage.md +40 -31
- package/docs/troubleshooting.md +32 -29
- package/examples/compat/add-edit-verify/PLAN.md +2 -0
- package/examples/compat/add-edit-verify/broken.diff +2 -2
- package/examples/compat/add-edit-verify/good.diff +2 -2
- package/examples/compat/add-edit-verify/src/add.js +1 -1
- package/examples/compat/manifest.json +25 -29
- package/examples/compat/sum-grep-edit/PLAN.md +33 -0
- package/examples/compat/sum-grep-edit/broken.diff +12 -0
- package/examples/compat/sum-grep-edit/good.diff +12 -0
- package/examples/compat/sum-grep-edit/package.json +5 -0
- package/examples/compat/sum-grep-edit/src/numbers.js +9 -0
- package/examples/compat/sum-grep-edit/test/numbers.test.js +15 -0
- package/examples/issue-triage-js/README.md +0 -15
- package/examples/reviewer-eval/clean-doc/base/src/clamp.ts +3 -0
- package/examples/reviewer-eval/clean-doc/change.diff +9 -0
- package/examples/reviewer-eval/clean-extract/base/src/greet.ts +3 -0
- package/examples/reviewer-eval/clean-extract/change.diff +13 -0
- package/examples/reviewer-eval/dropped-error/base/src/load.ts +4 -0
- package/examples/reviewer-eval/dropped-error/change.diff +15 -0
- package/examples/reviewer-eval/manifest.json +45 -0
- package/examples/reviewer-eval/off-by-one/base/src/paginate.ts +5 -0
- package/examples/reviewer-eval/off-by-one/change.diff +11 -0
- package/{config.yml → neal.yml} +1 -1
- package/package.json +20 -15
- package/dist/neal/providers/generic-agentic.js +0 -1238
- package/docs/comparison.md +0 -105
- package/examples/compat/is-even-add-test/PLAN.md +0 -30
- package/examples/compat/is-even-add-test/broken.diff +0 -11
- package/examples/compat/is-even-add-test/good.diff +0 -11
- package/examples/compat/is-even-add-test/package.json +0 -5
- package/examples/compat/is-even-add-test/src/is-even.js +0 -3
- package/examples/compat/is-even-add-test/test/is-even.test.js +0 -9
- package/examples/compat/reverse-grep-edit/PLAN.md +0 -32
- package/examples/compat/reverse-grep-edit/broken.diff +0 -12
- package/examples/compat/reverse-grep-edit/good.diff +0 -12
- package/examples/compat/reverse-grep-edit/package.json +0 -5
- package/examples/compat/reverse-grep-edit/src/strings.js +0 -10
- package/examples/compat/reverse-grep-edit/test/strings.test.js +0 -15
package/docs/comparison.md
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
# Why neal instead of X?
|
|
2
|
-
|
|
3
|
-
neal is a harness, not an agent. It runs three independent roles — planner,
|
|
4
|
-
coder, reviewer — each bound to whatever provider and model you choose
|
|
5
|
-
([providers.md](providers.md)), and drives them with a deterministic state
|
|
6
|
-
machine ([architecture.md](architecture.md)) rather than letting a model decide
|
|
7
|
-
the control flow. Verdicts are schema-validated structured output, not prose an
|
|
8
|
-
orchestrator model interprets. Every run is persisted under `.neal/` and
|
|
9
|
-
resumable after a crash ([storage.md](storage.md)). The reviewer is read-only by
|
|
10
|
-
construction: the provider registry rejects any reviewer capability that
|
|
11
|
-
declares write or shell access, so a reviewer structurally cannot mutate the
|
|
12
|
-
repo regardless of prompt. Most alternatives are agents; neal is the loop that
|
|
13
|
-
holds agents accountable to a plan.
|
|
14
|
-
|
|
15
|
-
## Claude Code
|
|
16
|
-
|
|
17
|
-
What it's great at: interactive, conversational coding with a single very
|
|
18
|
-
capable agent. Its subagents delegate work, plan mode gates execution behind an
|
|
19
|
-
approved plan, and hooks let you inject your own checks into the tool loop.
|
|
20
|
-
|
|
21
|
-
The structural difference: Claude Code is a single-vendor agent product.
|
|
22
|
-
Its subagents are prompt-scoped delegates inside one product, sharing a vendor
|
|
23
|
-
and orchestrated by a model — the top-level agent decides when to delegate and
|
|
24
|
-
how to weigh what comes back. There is no cross-vendor adversarial review: the
|
|
25
|
-
judge and the judged are the same vendor, often the same model family. neal is
|
|
26
|
-
not a competitor to Claude Code; it is a consumer of it. The `anthropic-claude`
|
|
27
|
-
adapter drives Claude Code's SDK as a coder or reviewer, and the common
|
|
28
|
-
configuration is exactly the adversarial split Claude Code cannot express:
|
|
29
|
-
Codex codes, Claude reviews, and a deterministic orchestrator — not a model —
|
|
30
|
-
decides what happens with the verdict.
|
|
31
|
-
|
|
32
|
-
Pick Claude Code when the work is exploratory or conversational, when you want
|
|
33
|
-
a human in the loop turn by turn, or when you have no plan yet. neal wants a
|
|
34
|
-
plan document; Claude Code is a good place to figure one out.
|
|
35
|
-
|
|
36
|
-
## Aider (architect/editor mode)
|
|
37
|
-
|
|
38
|
-
What it's great at: fast, terminal-native pair programming. Its
|
|
39
|
-
architect/editor mode was an early demonstration that splitting reasoning from
|
|
40
|
-
editing across two models improves results.
|
|
41
|
-
|
|
42
|
-
The structural difference: Aider's two models cooperate on one change — the
|
|
43
|
-
architect proposes, the editor applies — and the control flow between them is
|
|
44
|
-
mediated by the models within a chat session. There is no independent reviewer
|
|
45
|
-
producing a structured verdict that a state machine acts on, no scoped plan
|
|
46
|
-
queue where each scope starts the coder from a fresh context, and continuity is
|
|
47
|
-
conversation-shaped rather than a persisted run ledger. neal's roles are
|
|
48
|
-
adversarial rather than cooperative: the reviewer judges committed diffs it had
|
|
49
|
-
no hand in producing, findings route back to the coder until a schema-validated
|
|
50
|
-
accept, and `neal resume` reconstructs an interrupted run from the `.neal/`
|
|
51
|
-
ledgers rather than replaying a chat.
|
|
52
|
-
|
|
53
|
-
Pick Aider for tight interactive edits where you are the reviewer and the loop
|
|
54
|
-
is you. neal earns its overhead on multi-scope work where drift over a long
|
|
55
|
-
session is the failure mode.
|
|
56
|
-
|
|
57
|
-
## OpenHands and autonomous agents
|
|
58
|
-
|
|
59
|
-
What they're great at: sandboxed, hands-off execution — hand an issue to an
|
|
60
|
-
agent in an isolated runtime and come back to a pull request. The sandbox makes
|
|
61
|
-
broad autonomy defensible.
|
|
62
|
-
|
|
63
|
-
The structural difference: these systems bet on maximizing agent autonomy and
|
|
64
|
-
containing it with a sandbox. neal bets the opposite way: local-first execution
|
|
65
|
-
in your checkout, a human-authored plan as the contract for what may happen,
|
|
66
|
-
and bounded autonomy with structural escalation — blocked states that wait for
|
|
67
|
-
`neal resume --message`, manual gates for work only a human can do, and a
|
|
68
|
-
bounded adjudicator that resolves a narrow recoverable class and escalates
|
|
69
|
-
genuine walls. Even `--unattended` mode only bounds how long neal persists
|
|
70
|
-
before failing cleanly; it never widens authorization.
|
|
71
|
-
|
|
72
|
-
Pick an autonomous agent when you want isolation and don't need to constrain
|
|
73
|
-
the path taken. Pick neal when the plan is the point — when you want to
|
|
74
|
-
specify the decomposition, the verification per scope, and the stop conditions,
|
|
75
|
-
and have the machine enforce them.
|
|
76
|
-
|
|
77
|
-
## If you just want CI review
|
|
78
|
-
|
|
79
|
-
PR-review bots comment on diffs after they reach the forge. neal's review is
|
|
80
|
-
inside the loop: every scope's committed diff is judged before the run moves
|
|
81
|
-
on, and a final-completion review checks the whole plan before the squash — so
|
|
82
|
-
findings are fixed by the same coder in the same run, not triaged later.
|
|
83
|
-
`neal review` also works standalone against any committed range, role-symmetric
|
|
84
|
-
(the coder provider drafts findings, the read-only reviewer adjudicates them),
|
|
85
|
-
local, and provider-agnostic — no forge integration or CI required. The two are
|
|
86
|
-
complementary: neal reviews before you push, bots review after.
|
|
87
|
-
|
|
88
|
-
## What neal does not do
|
|
89
|
-
|
|
90
|
-
- **No GUI.** neal is a CLI with narrative terminal output; state lives in
|
|
91
|
-
files under `.neal/`.
|
|
92
|
-
- **No sandbox of its own for the coder.** Writer providers run with broad
|
|
93
|
-
local permissions (Codex under `danger-full-access`, Claude under
|
|
94
|
-
`bypassPermissions`, the generic writer's `run` tool is unsandboxed shell).
|
|
95
|
-
Bring your own isolation — disposable checkout, container, or VM. See
|
|
96
|
-
[SECURITY.md](../SECURITY.md).
|
|
97
|
-
- **Serial scopes only, today.** Scopes execute one at a time, and `neal run`
|
|
98
|
-
queues run plans serially. There is no parallel scope execution.
|
|
99
|
-
- **It requires a plan document.** There is no "just fix it" mode — the
|
|
100
|
-
authored plan, with its mandatory `## Execution Shape` section
|
|
101
|
-
([plan-format.md](plan-format.md)), is the product's opinion. If writing a
|
|
102
|
-
plan feels like overhead, neal is the wrong tool for that task.
|
|
103
|
-
- **No provider plugins yet.** Adapters are built-in (`openai-codex`,
|
|
104
|
-
`anthropic-claude`, `openai-compatible`, `generic-agentic`); external
|
|
105
|
-
provider plugins are future work.
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
# Compat fixture: replace the placeholder test
|
|
2
|
-
|
|
3
|
-
## Execution Shape
|
|
4
|
-
|
|
5
|
-
executionShape: one_shot
|
|
6
|
-
|
|
7
|
-
## Objective
|
|
8
|
-
|
|
9
|
-
`src/is-even.js` exports a correct `isEven(n)` helper. Its test in
|
|
10
|
-
`test/is-even.test.js` is only a placeholder that always fails
|
|
11
|
-
(`assert.ok(false, ...)`).
|
|
12
|
-
|
|
13
|
-
Replace the placeholder assertion with a real test that exercises `isEven` —
|
|
14
|
-
asserting `isEven(4)` is `true` is enough — so the test suite passes. Keep the
|
|
15
|
-
existing `test(...)` block; only the placeholder assertion needs to change.
|
|
16
|
-
|
|
17
|
-
## Boundaries
|
|
18
|
-
|
|
19
|
-
Allowed paths:
|
|
20
|
-
|
|
21
|
-
- `test/is-even.test.js`
|
|
22
|
-
|
|
23
|
-
Forbidden:
|
|
24
|
-
|
|
25
|
-
- Do not edit `src/is-even.js` (it is already correct).
|
|
26
|
-
- Do not add dependencies or new files.
|
|
27
|
-
|
|
28
|
-
## Verification
|
|
29
|
-
|
|
30
|
-
Run `node --test test/is-even.test.js`; it must exit `0`.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
diff --git a/test/is-even.test.js b/test/is-even.test.js
|
|
2
|
-
index 52c2a94..0e9eec5 100644
|
|
3
|
-
--- a/test/is-even.test.js
|
|
4
|
-
+++ b/test/is-even.test.js
|
|
5
|
-
@@ -5,5 +5,5 @@ import { isEven } from '../src/is-even.js';
|
|
6
|
-
|
|
7
|
-
test('isEven identifies even numbers', () => {
|
|
8
|
-
// TODO: replace this placeholder with a real assertion on isEven.
|
|
9
|
-
- assert.ok(false, 'TODO: replace this placeholder with a real test for isEven');
|
|
10
|
-
+ assert.equal(isEven(4), false);
|
|
11
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
diff --git a/test/is-even.test.js b/test/is-even.test.js
|
|
2
|
-
index 52c2a94..28d1d73 100644
|
|
3
|
-
--- a/test/is-even.test.js
|
|
4
|
-
+++ b/test/is-even.test.js
|
|
5
|
-
@@ -5,5 +5,5 @@ import { isEven } from '../src/is-even.js';
|
|
6
|
-
|
|
7
|
-
test('isEven identifies even numbers', () => {
|
|
8
|
-
// TODO: replace this placeholder with a real assertion on isEven.
|
|
9
|
-
- assert.ok(false, 'TODO: replace this placeholder with a real test for isEven');
|
|
10
|
-
+ assert.equal(isEven(4), true);
|
|
11
|
-
});
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
|
|
4
|
-
import { isEven } from '../src/is-even.js';
|
|
5
|
-
|
|
6
|
-
test('isEven identifies even numbers', () => {
|
|
7
|
-
// TODO: replace this placeholder with a real assertion on isEven.
|
|
8
|
-
assert.ok(false, 'TODO: replace this placeholder with a real test for isEven');
|
|
9
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# Compat fixture: fix the broken string helper
|
|
2
|
-
|
|
3
|
-
## Execution Shape
|
|
4
|
-
|
|
5
|
-
executionShape: one_shot
|
|
6
|
-
|
|
7
|
-
## Objective
|
|
8
|
-
|
|
9
|
-
`src/strings.js` exports several small string helpers. Exactly one of them is
|
|
10
|
-
buggy: `reverse(s)` is supposed to return the string with its characters
|
|
11
|
-
reversed, but it returns the string unchanged. The `reverse` test in
|
|
12
|
-
`test/strings.test.js` fails because of this.
|
|
13
|
-
|
|
14
|
-
Read `src/strings.js`, locate the faulty `reverse` helper, and make the smallest
|
|
15
|
-
complete change so it returns the reversed string. Do not touch the other
|
|
16
|
-
helpers, which already pass their tests.
|
|
17
|
-
|
|
18
|
-
## Boundaries
|
|
19
|
-
|
|
20
|
-
Allowed paths:
|
|
21
|
-
|
|
22
|
-
- `src/strings.js`
|
|
23
|
-
|
|
24
|
-
Forbidden:
|
|
25
|
-
|
|
26
|
-
- Do not edit the test file.
|
|
27
|
-
- Do not change the other (already-correct) helpers.
|
|
28
|
-
- Do not add dependencies or new files.
|
|
29
|
-
|
|
30
|
-
## Verification
|
|
31
|
-
|
|
32
|
-
Run `node --test test/strings.test.js`; it must exit `0`.
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
diff --git a/src/strings.js b/src/strings.js
|
|
2
|
-
index c338691..fbfe71b 100644
|
|
3
|
-
--- a/src/strings.js
|
|
4
|
-
+++ b/src/strings.js
|
|
5
|
-
@@ -5,6 +5,6 @@ export const upper = (s) => s.toUpperCase();
|
|
6
|
-
export const lower = (s) => s.toLowerCase();
|
|
7
|
-
|
|
8
|
-
// BUG: this does not actually reverse the string.
|
|
9
|
-
-export const reverse = (s) => s.split('').join('');
|
|
10
|
-
+export const reverse = (s) => s.split('').join('-');
|
|
11
|
-
|
|
12
|
-
export const repeat = (s, n) => s.repeat(n);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
diff --git a/src/strings.js b/src/strings.js
|
|
2
|
-
index c338691..d17fc16 100644
|
|
3
|
-
--- a/src/strings.js
|
|
4
|
-
+++ b/src/strings.js
|
|
5
|
-
@@ -5,6 +5,6 @@ export const upper = (s) => s.toUpperCase();
|
|
6
|
-
export const lower = (s) => s.toLowerCase();
|
|
7
|
-
|
|
8
|
-
// BUG: this does not actually reverse the string.
|
|
9
|
-
-export const reverse = (s) => s.split('').join('');
|
|
10
|
-
+export const reverse = (s) => s.split('').reverse().join('');
|
|
11
|
-
|
|
12
|
-
export const repeat = (s, n) => s.repeat(n);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Trivial compat fixture: several string helpers live here. Exactly one of them
|
|
2
|
-
// is buggy, so an agent must read/grep to locate the faulty function.
|
|
3
|
-
export const upper = (s) => s.toUpperCase();
|
|
4
|
-
|
|
5
|
-
export const lower = (s) => s.toLowerCase();
|
|
6
|
-
|
|
7
|
-
// BUG: this does not actually reverse the string.
|
|
8
|
-
export const reverse = (s) => s.split('').join('');
|
|
9
|
-
|
|
10
|
-
export const repeat = (s, n) => s.repeat(n);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import assert from 'node:assert/strict';
|
|
2
|
-
import test from 'node:test';
|
|
3
|
-
|
|
4
|
-
import { lower, repeat, reverse, upper } from '../src/strings.js';
|
|
5
|
-
|
|
6
|
-
test('upper/lower/repeat helpers are correct', () => {
|
|
7
|
-
assert.equal(upper('abc'), 'ABC');
|
|
8
|
-
assert.equal(lower('ABC'), 'abc');
|
|
9
|
-
assert.equal(repeat('ab', 3), 'ababab');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('reverse returns the string reversed', () => {
|
|
13
|
-
assert.equal(reverse('abc'), 'cba');
|
|
14
|
-
assert.equal(reverse('neal'), 'laen');
|
|
15
|
-
});
|