@navels/neal 0.2.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 +230 -38
- package/dist/neal/agents/prompts.js +6 -17
- package/dist/neal/agents/rounds.js +43 -73
- package/dist/neal/agents/schemas.js +47 -13
- 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 +16 -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/interactive-controls.js +5 -0
- package/dist/neal/orchestrator/completion.js +49 -2
- package/dist/neal/orchestrator/failures.js +7 -0
- package/dist/neal/orchestrator/notifications.js +9 -9
- package/dist/neal/orchestrator/phases/planning.js +117 -80
- package/dist/neal/orchestrator/phases/recovery.js +151 -115
- package/dist/neal/orchestrator/phases/review.js +28 -1
- package/dist/neal/orchestrator/transitions.js +7 -1
- package/dist/neal/orchestrator.js +3 -0
- package/dist/neal/plan-queue.js +29 -1
- package/dist/neal/prompts/execute.js +7 -19
- package/dist/neal/prompts/planning.js +64 -55
- package/dist/neal/prompts/review-doctrine.js +13 -50
- package/dist/neal/prompts/specialized.js +7 -17
- package/dist/neal/prompts/specs.js +180 -32
- package/dist/neal/providers/agent-settings-isolation.js +35 -0
- package/dist/neal/providers/anthropic-claude.js +18 -1
- 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 +25 -3
- package/dist/neal/providers/{generic-agentic-tools.js → openai-compatible-tools.js} +11 -5
- package/dist/neal/providers/openai-compatible.js +1078 -430
- package/dist/neal/providers/openrouter-routing.js +68 -0
- package/dist/neal/providers/pricing.js +1 -1
- package/dist/neal/providers/rate-card.js +6 -32
- package/dist/neal/providers/registry.js +6 -17
- 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 +3 -3
- 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/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 -121
- package/docs/demo.md +15 -5
- package/docs/maintenance.md +65 -34
- 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 +279 -349
- package/docs/release.md +18 -19
- 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 +15 -14
- package/dist/neal/providers/generic-agentic.js +0 -1256
- package/docs/comparison.md +0 -105
- package/docs/issue-pipeline.md +0 -124
- 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/storage.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Storage contract
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
neal uses project-local `.neal/` storage as the source of truth for runs, queues,
|
|
4
4
|
review artifacts, recovery artifacts, progress, and audit history. User-level
|
|
5
5
|
storage is reserved for configuration, guidance, caches, logs, and future
|
|
6
6
|
optional discovery helpers.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
and validation details
|
|
8
|
+
The storage contract here is product-level. Run and queue ledger state
|
|
9
|
+
transition and validation details are documented separately in
|
|
10
10
|
[state-machine.md](state-machine.md).
|
|
11
11
|
|
|
12
|
-
## Public
|
|
12
|
+
## Public automation surface
|
|
13
13
|
|
|
14
14
|
`neal status --json` and `neal status --json --all` are the stable automation
|
|
15
15
|
contracts. Scripts should prefer them over parsing raw files under `.neal/`.
|
|
@@ -37,9 +37,9 @@ know a run id. Important stable fields include:
|
|
|
37
37
|
- `providerError` with the latest provider failure or unclassified phase error,
|
|
38
38
|
including timestamp, provider id, role, label, session handle, normalized
|
|
39
39
|
error kind, bounded message, and retryability where available.
|
|
40
|
-
- `build` with
|
|
40
|
+
- `build` with neal package version, neal source Git SHA when available, Node
|
|
41
41
|
version, source marker (`meta` or `live_fallback`), and the persisted
|
|
42
|
-
coder/reviewer agent config.
|
|
42
|
+
planner/coder/reviewer agent config.
|
|
43
43
|
- `artifacts` with run-local paths for the human narrative, review, progress,
|
|
44
44
|
support, and related diagnostic artifacts.
|
|
45
45
|
|
|
@@ -61,30 +61,38 @@ command output.
|
|
|
61
61
|
Storage classifications used below are: stable CLI surface, user-facing human
|
|
62
62
|
artifact, support/debug artifact, internal state, and lock/concurrency artifact.
|
|
63
63
|
The stable CLI surfaces in this storage contract are `neal status --json` and
|
|
64
|
-
`neal status --json --all
|
|
65
|
-
|
|
64
|
+
`neal status --json --all`. The project-local files are artifacts that support
|
|
65
|
+
neal operations and diagnostics.
|
|
66
66
|
|
|
67
|
-
## Project-
|
|
67
|
+
## Project-local layout
|
|
68
68
|
|
|
69
69
|
| Path | Classification | Contract |
|
|
70
70
|
| --- | --- | --- |
|
|
71
|
-
| `.neal/runs/<run-id>/RUN_STATE.json` | Internal state | Child-run ledger.
|
|
71
|
+
| `.neal/runs/<run-id>/RUN_STATE.json` | Internal state | Child-run ledger. neal validates current v1 state on read, but scripts should use `neal status --json` rather than depend on this file as a public API. |
|
|
72
72
|
| `.neal/runs/<run-id>/events.ndjson` | Support/debug artifact | Append-only event log for audit, diagnostics, command output references, and provider/runtime events. Readers should tolerate malformed or partial final lines where implemented. |
|
|
73
73
|
| `.neal/runs/<run-id>/stderr.log` | Support/debug artifact | Append-only stderr transcript for writer runs. It includes visible narrative lines plus low-level detail such as provider/tool telemetry, command output, reviewer context, and heartbeat diagnostics that may be hidden from the normal terminal stream. |
|
|
74
|
-
| `.neal/runs/<run-id>/meta.json` | Support/debug artifact | Run metadata used for diagnostics. New writes include `version: 1
|
|
74
|
+
| `.neal/runs/<run-id>/meta.json` | Support/debug artifact | Run metadata used for diagnostics. New writes include `version: 1`. Metadata alone cannot make a run selectable for squash or status. It is not the stable automation surface. |
|
|
75
75
|
| `.neal/runs/<run-id>/PLAN_ORIGINAL.md` | Support/debug artifact | Original plan document backup for `neal plan` runs, written before in-place plan refinement so the pre-refinement input remains inspectable. |
|
|
76
|
-
| `.neal/runs/<run-id>/
|
|
77
|
-
| `.neal/runs/<run-id>/
|
|
76
|
+
| `.neal/runs/<run-id>/DERIVED_PLAN_SCOPE_<scope>.md` | User-facing human artifact | Replacement execution plan produced when the coder splits an active scope. |
|
|
77
|
+
| `.neal/runs/<run-id>/SCOPE_<scope>_INVALID_DERIVED_PLAN.md` | Support/debug artifact | Rejected split-plan payload and its validation errors. Written only when the returned replacement plan is invalid. |
|
|
78
|
+
| `.neal/runs/<run-id>/SCOPE_<scope>_DISCARDED.diff` | Support/debug artifact | Scope work preserved before neal resets it while adopting a replacement plan. |
|
|
79
|
+
| `.neal/runs/<run-id>/GATE-<id>.md` | User-facing human artifact | Instructions and resume checks for an active manual gate. |
|
|
80
|
+
| `.neal/runs/<run-id>/scratch/` | Support/debug artifact | Reserved run-local scratch root for execute-scope and final-completion review. Read-only reviewer prompts do not use it. It is not durable state, but it remains project-local `.neal/` data for retention and privacy purposes. |
|
|
81
|
+
| `.neal/runs/<run-id>/plan-progress.json` | Internal state | Machine-readable v1 progress artifact used by neal context and summaries. |
|
|
78
82
|
| `.neal/runs/<run-id>/PLAN_PROGRESS.md` | User-facing human artifact | Human-readable progress summary for the active plan or scope. |
|
|
79
83
|
| `.neal/runs/<run-id>/RETROSPECTIVE.md` | User-facing human artifact | Human-readable retrospective or checkpoint summary. Archived variants such as `RETROSPECTIVE-scope-*.md` may also exist. |
|
|
84
|
+
| `.neal/runs/<run-id>/RUN_METRICS.json` | Support/debug artifact | Machine-readable metrics paired with the current retrospective. Archived variants such as `RUN_METRICS-scope-*.json` may also exist. |
|
|
80
85
|
| `.neal/runs/<run-id>/RUN_NARRATIVE.md` | User-facing human artifact | Human-readable run narrative. It includes a benchmark trace section with status, patch-policy, provider-error, and reproducibility summaries suitable for public result bundles. |
|
|
81
|
-
| `.neal/runs/<run-id>/RUN_NARRATIVE.json` | Internal state | Narrative source data that
|
|
86
|
+
| `.neal/runs/<run-id>/RUN_NARRATIVE.json` | Internal state | Narrative source data that neal may read to update the human narrative. It is not a public trace artifact. |
|
|
82
87
|
| `.neal/runs/<run-id>/REVIEW.md` | User-facing human artifact | Scope or plan review history and findings. |
|
|
88
|
+
| `.neal/runs/<run-id>/REVIEW-<commit>.md` | User-facing human artifact | Archived review history for an accepted scope commit. |
|
|
89
|
+
| `.neal/runs/<run-id>/REVIEWER_CONTEXT.md` | Support/debug artifact | Bounded reviewer-continuity packet rendered for inspection. |
|
|
90
|
+
| `.neal/runs/<run-id>/REVIEWER_CONTEXT.json` | Support/debug artifact | Machine-readable reviewer-continuity packet without the rendered prompt markdown. |
|
|
83
91
|
| `.neal/runs/<run-id>/RECOVERY.md` | User-facing human artifact | Interactive blocked-recovery transcript/history for a run. |
|
|
84
92
|
| `.neal/runs/<run-id>/FINAL_COMPLETION_REVIEW.md` | User-facing human artifact | Whole-plan final completion review. |
|
|
85
93
|
| `.neal/runs/<run-id>/SQUASH_RESULT.json` | Support/debug artifact | Versioned audit artifact from `neal squash`. It records the squash decision/result but is not the stable automation surface. |
|
|
86
94
|
| `.neal/runs/<run-id>/QUEUE_LINK.json` | Internal state | Link from a child run back to its parent plan-and-execute queue item. |
|
|
87
|
-
| `.neal/queues/<queue-id>/QUEUE_STATE.json` | Internal state | Parent queue ledger.
|
|
95
|
+
| `.neal/queues/<queue-id>/QUEUE_STATE.json` | Internal state | Parent queue ledger. neal validates it on read, but it is not a public JSON API. |
|
|
88
96
|
| `.neal/queues/<queue-id>/QUEUE_SUMMARY.md` | User-facing human artifact | Human-readable summary for a plan-and-execute queue. |
|
|
89
97
|
| `.neal/reviews/<review-id>/meta.json` | Support/debug artifact | Review metadata for a read-only `neal review` request. |
|
|
90
98
|
| `.neal/reviews/<review-id>/events.ndjson` | Support/debug artifact | Append-only review event log. |
|
|
@@ -97,19 +105,20 @@ Neal operations and diagnostics.
|
|
|
97
105
|
| `.neal/current.json` | Internal state | Default writer-run pointer for commands that need the current run. |
|
|
98
106
|
| `.neal/current-queue.json` | Internal state | Preferred current plan-and-execute queue pointer. |
|
|
99
107
|
| `.neal/active-run.lock` | Lock/concurrency artifact | Active writer-run lock. It prevents unrelated writer commands from mutating the same checkout concurrently. |
|
|
108
|
+
| `.neal/NOTES.md` | User-facing human artifact | Optional operator-authored notes included in bounded context packets. neal reads this file but does not create it. |
|
|
100
109
|
|
|
101
110
|
Writer processes remove their own active lock during normal shutdown and on
|
|
102
|
-
`SIGINT`/`SIGTERM`. Timeout wrappers should still launch
|
|
111
|
+
`SIGINT`/`SIGTERM`. Timeout wrappers should still launch neal in a process group
|
|
103
112
|
and terminate the group, because provider-owned child processes are outside the
|
|
104
113
|
lock file contract. After a timeout, call `neal status --json --run <run-id>`
|
|
105
|
-
when the run id is known
|
|
106
|
-
using `status`, `health`, and `lock.kind` to record whether
|
|
114
|
+
when the run id is known. Treat the wrapper timeout as the primary result while
|
|
115
|
+
using `status`, `health`, and `lock.kind` to record whether neal's run state is
|
|
107
116
|
still running, cleaned up, live, stale, cross-host, or unreadable.
|
|
108
117
|
|
|
109
|
-
## Patch
|
|
118
|
+
## Patch automation policy
|
|
110
119
|
|
|
111
120
|
Default public prediction submission should use only
|
|
112
|
-
`patch.defaultSubmissionEligible: true`.
|
|
121
|
+
`patch.defaultSubmissionEligible: true`. neal sets that value only for clean
|
|
113
122
|
completed execute runs with a non-empty readable patch range.
|
|
114
123
|
|
|
115
124
|
When a completed run has a successful squash artifact, the status read model
|
|
@@ -124,28 +133,28 @@ runs may still report patch-bearing metadata for diagnostics or private
|
|
|
124
133
|
analysis. They are not default-submission eligible, and `patch.reason` explains
|
|
125
134
|
why.
|
|
126
135
|
|
|
127
|
-
## Source
|
|
136
|
+
## Source of truth
|
|
128
137
|
|
|
129
138
|
Project-local `.neal/` remains the source of truth for run, queue, review,
|
|
130
139
|
recovery, progress, and audit artifacts.
|
|
131
140
|
|
|
132
141
|
Run-local `.neal/runs/<run-id>/RUN_STATE.json` is the only writer-run ledger
|
|
133
|
-
path
|
|
142
|
+
path neal writes. `.neal/current.json` points at the default writer run. It is a
|
|
134
143
|
pointer, not a copy of the ledger.
|
|
135
144
|
|
|
136
145
|
There is no required global run index in v1. Future global discovery, if added,
|
|
137
146
|
must be optional and rebuildable from project-local data. It must not become the
|
|
138
147
|
only place where run or queue history can be recovered.
|
|
139
148
|
|
|
140
|
-
## Ledgers
|
|
149
|
+
## Ledgers and pointers
|
|
141
150
|
|
|
142
151
|
`.neal/runs/<run-id>/RUN_STATE.json` and
|
|
143
|
-
`.neal/queues/<queue-id>/QUEUE_STATE.json` are persisted ledgers.
|
|
152
|
+
`.neal/queues/<queue-id>/QUEUE_STATE.json` are persisted ledgers. neal validates
|
|
144
153
|
them on read. Child-run state uses strict current v1 hydration: missing or
|
|
145
154
|
malformed required child-run fields fail instead of receiving defaults. These
|
|
146
155
|
ledgers are not public JSON APIs.
|
|
147
156
|
|
|
148
|
-
|
|
157
|
+
neal does not write, read, migrate, or repair a session mirror. Use
|
|
149
158
|
`.neal/current.json` as the default writer-run pointer, `neal status --all` to
|
|
150
159
|
discover run IDs, and `--run <run-id>` when selecting a specific run for
|
|
151
160
|
`resume` or `status`.
|
|
@@ -154,9 +163,9 @@ Squash discovery requires readable run-local state. Run metadata and progress
|
|
|
154
163
|
artifacts can help humans inspect a run, but they cannot make a run selectable
|
|
155
164
|
for `neal squash` without `.neal/runs/<run-id>/RUN_STATE.json`.
|
|
156
165
|
|
|
157
|
-
## Schema
|
|
166
|
+
## Schema versions and writes
|
|
158
167
|
|
|
159
|
-
|
|
168
|
+
neal-owned JSON schemas use `version: 1` where they are read back as durable
|
|
160
169
|
state or audit data. That includes child-run state, current run pointers, queue
|
|
161
170
|
state, current queue pointers, queue child links, progress summaries, run
|
|
162
171
|
narratives, squash audit results, review artifacts, and the active writer lock.
|
|
@@ -172,7 +181,7 @@ files such as state, progress, reviews, and pointers can briefly disagree if a
|
|
|
172
181
|
process stops between writes. Append-only event logs remain append-only, and the
|
|
173
182
|
active writer lock keeps exclusive file creation for acquisition.
|
|
174
183
|
|
|
175
|
-
## Retention
|
|
184
|
+
## Retention and privacy
|
|
176
185
|
|
|
177
186
|
`.neal/` may contain prompts, local paths, command output, diffs, review text,
|
|
178
187
|
provider responses, user guidance diagnostics, reviewer scratch files, copied
|
|
@@ -188,7 +197,7 @@ Run and review artifacts are intentionally inspectable, but they should be
|
|
|
188
197
|
treated as project data. Apply the same retention and access controls you use
|
|
189
198
|
for source, logs, and local debugging output.
|
|
190
199
|
|
|
191
|
-
## Manual
|
|
200
|
+
## Manual cleanup
|
|
192
201
|
|
|
193
202
|
Manual cleanup is safe only when you no longer need resume, history, diagnostics,
|
|
194
203
|
or audit data for the item being removed.
|
|
@@ -202,6 +211,6 @@ Reasonable manual cleanup options:
|
|
|
202
211
|
- remove stale `.neal/current.json` or `.neal/current-queue.json` pointers only
|
|
203
212
|
after confirming they do not point to work you still intend to resume
|
|
204
213
|
|
|
205
|
-
Deleting run or queue state removes
|
|
214
|
+
Deleting run or queue state removes neal's resume and history for that run or
|
|
206
215
|
queue. Prefer keeping the full directory until the related work has been merged,
|
|
207
216
|
archived, or otherwise recorded somewhere durable.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -6,7 +6,7 @@ prints. When in doubt: `neal check`, then `.neal/runs/<run-id>/stderr.log`.
|
|
|
6
6
|
## Install and first run
|
|
7
7
|
|
|
8
8
|
**Symptom:** install or startup fails on an old Node.
|
|
9
|
-
**Cause:** neal requires Node.js >=
|
|
9
|
+
**Cause:** neal requires Node.js >= 24.18.0 (`engines`). `.nvmrc` pins `24.18.0`.
|
|
10
10
|
**Fix:** `nvm use` in this repo, or upgrade Node before `npm install -g @navels/neal`.
|
|
11
11
|
|
|
12
12
|
**Symptom:** `pnpm: command not found` when running from source.
|
|
@@ -20,13 +20,13 @@ After source changes, `pnpm build` again so the linked command sees `dist/`.
|
|
|
20
20
|
|
|
21
21
|
**Symptom:** `neal setup` lists a provider with `- runtime not found`.
|
|
22
22
|
**Cause:** setup detects local runtime surfaces only (the `@openai/codex-sdk`
|
|
23
|
-
entrypoint
|
|
23
|
+
entrypoint, an SDK-bundled or on-PATH `claude` executable), never auth.
|
|
24
24
|
**Fix:** install the provider's SDK/CLI, then rerun `neal setup` and `neal check`.
|
|
25
25
|
|
|
26
26
|
## Provider auth failures (`neal check`)
|
|
27
27
|
|
|
28
28
|
`neal check` sends one small prompt per unique configured provider/model
|
|
29
|
-
(interactive TTY only
|
|
29
|
+
(interactive TTY only. Non-interactive input prints
|
|
30
30
|
`Provider verification skipped: non-interactive input.`). Known failures:
|
|
31
31
|
|
|
32
32
|
**Symptom:** `Claude Code refused bypass-permissions mode while running as root.`
|
|
@@ -40,31 +40,34 @@ Claude Code refuses under root/sudo.
|
|
|
40
40
|
directory (e.g. run the `codex` CLI there once), then `neal check` again.
|
|
41
41
|
|
|
42
42
|
**Symptom:** `OpenAI Codex could not persist the check session.`
|
|
43
|
-
**Fix:** transient
|
|
43
|
+
**Fix:** transient. Run `neal check` again. If it repeats, redo the provider's
|
|
44
44
|
local setup.
|
|
45
45
|
|
|
46
46
|
**Symptom:** a `not logged in` message from either vendor CLI.
|
|
47
|
-
**Cause:** provider auth is provider-owned
|
|
47
|
+
**Cause:** provider auth is provider-owned, so neal never collects credentials.
|
|
48
48
|
**Fix:** complete the provider's normal local auth setup (the `codex` / `claude`
|
|
49
49
|
login flows), then `neal check` again.
|
|
50
50
|
|
|
51
51
|
**Symptom:** `Set providers.openai_compatible.base_url (or OPENAI_COMPATIBLE_BASE_URL) and OPENAI_COMPATIBLE_API_KEY before running Neal.`
|
|
52
52
|
(or `No model is resolvable for the openai-compatible ... role`).
|
|
53
|
-
**Cause:** `openai-compatible`
|
|
54
|
-
with env fallbacks: `base_url` → `OPENAI_COMPATIBLE_BASE_URL
|
|
55
|
-
from the env var named by `api_key_env` (default `OPENAI_COMPATIBLE_API_KEY`)
|
|
56
|
-
|
|
53
|
+
**Cause:** `openai-compatible` resolves settings from config first,
|
|
54
|
+
with env fallbacks: `base_url` → `OPENAI_COMPATIBLE_BASE_URL`. The key is read
|
|
55
|
+
from the env var named by `api_key_env` (default `OPENAI_COMPATIBLE_API_KEY`).
|
|
56
|
+
Model from `agent.<role>.model` → `default_model` → `OPENAI_COMPATIBLE_MODEL`.
|
|
57
57
|
**Fix:** set the missing key. For OpenRouter: `base_url: https://openrouter.ai/api/v1`,
|
|
58
58
|
`api_key_env: OPENROUTER_API_KEY`, and export `OPENROUTER_API_KEY`. (OpenRouter
|
|
59
|
-
wraps upstream 429s in HTTP-200 bodies
|
|
59
|
+
wraps upstream 429s in HTTP-200 bodies, so neal unwraps and retries them.)
|
|
60
60
|
|
|
61
61
|
## Runs that won't start
|
|
62
62
|
|
|
63
|
-
**Symptom:** plan validation errors such as
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
**Symptom:** plan validation errors such as:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Missing required `## Execution Shape` section.
|
|
67
|
+
`## Execution Shape` must contain exactly one non-empty line.
|
|
68
|
+
```
|
|
66
69
|
**Cause:** every executable plan must declare exactly one of
|
|
67
|
-
`executionShape: one_shot | multi_scope | multi_scope_unknown
|
|
70
|
+
`executionShape: one_shot | multi_scope | multi_scope_unknown`. `multi_scope`
|
|
68
71
|
also requires an `## Execution Queue` with contiguous `### Scope N:` headings,
|
|
69
72
|
each carrying `- Goal:` / `- Verification:` / `- Success Condition:` bullets.
|
|
70
73
|
**Fix:** see [plan-format.md](plan-format.md), or let `neal plan` refine the
|
|
@@ -72,23 +75,23 @@ document into executable shape.
|
|
|
72
75
|
|
|
73
76
|
**Symptom:** a missing-config error naming `agent.coder.provider` or
|
|
74
77
|
`agent.reviewer.provider`.
|
|
75
|
-
**Cause:** fresh writer runs require explicit coder and reviewer providers
|
|
76
|
-
|
|
78
|
+
**Cause:** fresh writer runs require explicit coder and reviewer providers.
|
|
79
|
+
Built-in defaults are not enough.
|
|
77
80
|
**Fix:** `neal setup`, then `neal check`.
|
|
78
81
|
|
|
79
82
|
**Symptom:** `Cannot start neal execute with a dirty worktree:` followed by
|
|
80
83
|
`git status` lines (queues: `Cannot continue neal run with a dirty worktree:`).
|
|
81
|
-
**Cause:** writer admission requires a clean worktree
|
|
84
|
+
**Cause:** writer admission requires a clean worktree. Only the selected plan
|
|
82
85
|
document and neal-owned paths (`.neal/`) are exempt. Leftover reviewer scratch
|
|
83
86
|
(`build_review/`, `scratch/`, …) gets a
|
|
84
|
-
`Likely Neal reviewer scratch leakage detected:` diagnostic but still blocks
|
|
85
|
-
the paths are not proven neal-owned.
|
|
87
|
+
`Likely Neal reviewer scratch leakage detected:` diagnostic but still blocks,
|
|
88
|
+
because the paths are not proven neal-owned.
|
|
86
89
|
**Fix:** use `neal resume` for in-progress scope work, or commit, stash, move,
|
|
87
90
|
or remove the dirty paths and start clean.
|
|
88
91
|
|
|
89
92
|
**Symptom:** a Git precondition error before any provider runs.
|
|
90
93
|
**Fix:** writer commands require a Git repository with an existing `HEAD`
|
|
91
|
-
commit
|
|
94
|
+
commit. Create the initial baseline commit first.
|
|
92
95
|
|
|
93
96
|
## Stuck or blocked runs
|
|
94
97
|
|
|
@@ -100,26 +103,26 @@ something it may not resolve alone, and attended runs wait for guidance.
|
|
|
100
103
|
accepted in that waiting-for-guidance state.
|
|
101
104
|
|
|
102
105
|
**Symptom:** `effectiveStatus: "waiting_for_manual_gate"`.
|
|
103
|
-
**Cause:** the scope reached expected human work
|
|
106
|
+
**Cause:** the scope reached expected human work. Instructions are in the
|
|
104
107
|
run-local `GATE-<id>.md` file shown by `neal status`.
|
|
105
|
-
**Fix:** do the manual step, then `neal resume --run <run-id
|
|
108
|
+
**Fix:** do the manual step, then `neal resume --run <run-id>`, which re-runs
|
|
106
109
|
the gate's checks and resumes the scope when they pass. No `--message` here.
|
|
107
110
|
|
|
108
111
|
**Symptom:** a run seems hung or died silently.
|
|
109
112
|
**Where to look:** raw detail is persisted even when hidden from the terminal:
|
|
110
113
|
`.neal/runs/<run-id>/stderr.log` (full transcript) and
|
|
111
|
-
`.neal/runs/<run-id>/events.ndjson` (event log
|
|
112
|
-
as `provider.turn_liveness_*` events). On a live TTY, press `v` for the
|
|
114
|
+
`.neal/runs/<run-id>/events.ndjson` (event log, where startup-silence retries
|
|
115
|
+
appear as `provider.turn_liveness_*` events). On a live TTY, press `v` for the
|
|
113
116
|
low-level detail view. `neal status --json --run <run-id>` carries the latest
|
|
114
117
|
`providerError` classification.
|
|
115
118
|
|
|
116
119
|
## Lock issues
|
|
117
120
|
|
|
118
|
-
The writer lock is `.neal/active-run.lock
|
|
121
|
+
The writer lock is `.neal/active-run.lock`. Writer processes remove it on
|
|
119
122
|
normal shutdown and on SIGINT/SIGTERM.
|
|
120
123
|
|
|
121
124
|
**Symptom:** `another Neal writer run is active in this checkout`.
|
|
122
|
-
**Fix:** as printed
|
|
125
|
+
**Fix:** as printed: `neal resume --run <run-id>` to continue that run, or
|
|
123
126
|
wait for it to finish.
|
|
124
127
|
|
|
125
128
|
**Symptom:** `another Neal process is already resuming this run` (with
|
|
@@ -128,17 +131,17 @@ wait for it to finish.
|
|
|
128
131
|
|
|
129
132
|
**Symptom:** `stale Neal writer lock found in this checkout` /
|
|
130
133
|
`no process with that PID is running on this host.`
|
|
131
|
-
**Fix:** `neal resume --run <run-id>` clears stale same-host locks itself
|
|
134
|
+
**Fix:** `neal resume --run <run-id>` clears stale same-host locks itself. If
|
|
132
135
|
you're starting different work instead, inspect the run, then remove the lock
|
|
133
136
|
file the message names.
|
|
134
137
|
|
|
135
138
|
**Symptom:** `Neal writer lock belongs to another host`.
|
|
136
|
-
**Fix:** inspect the other host before removing the lock
|
|
139
|
+
**Fix:** inspect the other host before removing the lock. The message prints
|
|
137
140
|
the exact resume command for that checkout.
|
|
138
141
|
|
|
139
142
|
**Symptom:** `could not read the active Neal writer lock`.
|
|
140
143
|
**Fix:** as printed: inspect the named lock file before starting another
|
|
141
|
-
writer run
|
|
144
|
+
writer run. Remove it only after confirming no writer process is active.
|
|
142
145
|
|
|
143
146
|
## "It squashed when I didn't want it to"
|
|
144
147
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
diff --git a/src/add.js b/src/add.js
|
|
2
|
-
index
|
|
2
|
+
index 6946b9a..e9fa11d 100644
|
|
3
3
|
--- a/src/add.js
|
|
4
4
|
+++ b/src/add.js
|
|
5
5
|
@@ -1,2 +1,2 @@
|
|
6
|
-
// Trivial compat fixture:
|
|
6
|
+
// Trivial compat fixture: an arithmetic helper exercised by test/add.test.js.
|
|
7
7
|
-export const add = (a, b) => a - b;
|
|
8
8
|
+export const add = (a, b) => a * b;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
diff --git a/src/add.js b/src/add.js
|
|
2
|
-
index
|
|
2
|
+
index 6946b9a..ee66238 100644
|
|
3
3
|
--- a/src/add.js
|
|
4
4
|
+++ b/src/add.js
|
|
5
5
|
@@ -1,2 +1,2 @@
|
|
6
|
-
// Trivial compat fixture:
|
|
6
|
+
// Trivial compat fixture: an arithmetic helper exercised by test/add.test.js.
|
|
7
7
|
-export const add = (a, b) => a - b;
|
|
8
8
|
+export const add = (a, b) => a + b;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// Trivial compat fixture:
|
|
1
|
+
// Trivial compat fixture: an arithmetic helper exercised by test/add.test.js.
|
|
2
2
|
export const add = (a, b) => a - b;
|
|
@@ -2,51 +2,47 @@
|
|
|
2
2
|
"fixtures": [
|
|
3
3
|
{
|
|
4
4
|
"id": "add-edit-verify",
|
|
5
|
-
"roles": [
|
|
5
|
+
"roles": [
|
|
6
|
+
"coder",
|
|
7
|
+
"reviewer"
|
|
8
|
+
],
|
|
6
9
|
"projectDir": "add-edit-verify",
|
|
7
10
|
"planDoc": "add-edit-verify/PLAN.md",
|
|
8
11
|
"verifyCommand": "node --test test/add.test.js",
|
|
9
|
-
"referenceFix": { "file": "src/add.js", "from": "a - b", "to": "a + b" },
|
|
10
|
-
"reviewer": {
|
|
11
|
-
"goodDiff": "add-edit-verify/good.diff",
|
|
12
|
-
"brokenDiff": "add-edit-verify/broken.diff"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"id": "reverse-grep-edit",
|
|
17
|
-
"roles": ["coder", "reviewer"],
|
|
18
|
-
"projectDir": "reverse-grep-edit",
|
|
19
|
-
"planDoc": "reverse-grep-edit/PLAN.md",
|
|
20
|
-
"verifyCommand": "node --test test/strings.test.js",
|
|
21
12
|
"referenceFix": {
|
|
22
|
-
"file": "src/
|
|
23
|
-
"from": "
|
|
24
|
-
"to": "
|
|
13
|
+
"file": "src/add.js",
|
|
14
|
+
"from": "a - b",
|
|
15
|
+
"to": "a + b"
|
|
25
16
|
},
|
|
26
17
|
"reviewer": {
|
|
27
|
-
"goodDiff": "
|
|
28
|
-
"brokenDiff": "
|
|
18
|
+
"goodDiff": "add-edit-verify/good.diff",
|
|
19
|
+
"brokenDiff": "add-edit-verify/broken.diff"
|
|
29
20
|
}
|
|
30
21
|
},
|
|
31
22
|
{
|
|
32
|
-
"id": "
|
|
33
|
-
"roles": [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
"id": "sum-grep-edit",
|
|
24
|
+
"roles": [
|
|
25
|
+
"coder",
|
|
26
|
+
"reviewer"
|
|
27
|
+
],
|
|
28
|
+
"projectDir": "sum-grep-edit",
|
|
29
|
+
"planDoc": "sum-grep-edit/PLAN.md",
|
|
30
|
+
"verifyCommand": "node --test test/numbers.test.js",
|
|
37
31
|
"referenceFix": {
|
|
38
|
-
"file": "
|
|
39
|
-
"from": "
|
|
40
|
-
"to": "
|
|
32
|
+
"file": "src/numbers.js",
|
|
33
|
+
"from": "(total, n) => total",
|
|
34
|
+
"to": "(total, n) => total + n"
|
|
41
35
|
},
|
|
42
36
|
"reviewer": {
|
|
43
|
-
"goodDiff": "
|
|
44
|
-
"brokenDiff": "
|
|
37
|
+
"goodDiff": "sum-grep-edit/good.diff",
|
|
38
|
+
"brokenDiff": "sum-grep-edit/broken.diff"
|
|
45
39
|
}
|
|
46
40
|
},
|
|
47
41
|
{
|
|
48
42
|
"id": "plan-greeting",
|
|
49
|
-
"roles": [
|
|
43
|
+
"roles": [
|
|
44
|
+
"planner"
|
|
45
|
+
],
|
|
50
46
|
"projectDir": "plan-greeting",
|
|
51
47
|
"issuePrompt": "plan-greeting/ISSUE.md",
|
|
52
48
|
"verifyCommand": "node --test test/greet.test.js",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Compat fixture: fix the number helper that never adds
|
|
2
|
+
|
|
3
|
+
> Fixture note: this plan describes the pre-fix state and is intentionally not updated after the fix lands.
|
|
4
|
+
|
|
5
|
+
## Execution Shape
|
|
6
|
+
|
|
7
|
+
executionShape: one_shot
|
|
8
|
+
|
|
9
|
+
## Objective
|
|
10
|
+
|
|
11
|
+
`src/numbers.js` exports several small number helpers. One of them is faulty:
|
|
12
|
+
`sumAll(ns)` is supposed to return the total of the list, but it always returns
|
|
13
|
+
`0`. The `sumAll` test in `test/numbers.test.js` fails because of this.
|
|
14
|
+
|
|
15
|
+
Read `src/numbers.js`, locate the faulty `sumAll` helper, and make the smallest
|
|
16
|
+
complete change so it returns the sum of the list. Do not touch the other
|
|
17
|
+
helpers, which already pass their tests.
|
|
18
|
+
|
|
19
|
+
## Boundaries
|
|
20
|
+
|
|
21
|
+
Allowed paths:
|
|
22
|
+
|
|
23
|
+
- `src/numbers.js`
|
|
24
|
+
|
|
25
|
+
Forbidden:
|
|
26
|
+
|
|
27
|
+
- Do not edit the test file.
|
|
28
|
+
- Do not change the other (already-correct) helpers.
|
|
29
|
+
- Do not add dependencies or new files.
|
|
30
|
+
|
|
31
|
+
## Verification
|
|
32
|
+
|
|
33
|
+
Run `node --test test/numbers.test.js`; it must exit `0`.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
diff --git a/src/numbers.js b/src/numbers.js
|
|
2
|
+
index e6677cc..6a5102c 100644
|
|
3
|
+
--- a/src/numbers.js
|
|
4
|
+
+++ b/src/numbers.js
|
|
5
|
+
@@ -4,6 +4,6 @@ export const double = (n) => n * 2;
|
|
6
|
+
|
|
7
|
+
export const negate = (n) => -n;
|
|
8
|
+
|
|
9
|
+
-export const sumAll = (ns) => ns.reduce((total, n) => total, 0);
|
|
10
|
+
+export const sumAll = (ns) => ns.reduce((total, n) => total + 1, 0);
|
|
11
|
+
|
|
12
|
+
export const countOf = (ns) => ns.length;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
diff --git a/src/numbers.js b/src/numbers.js
|
|
2
|
+
index e6677cc..89f58ba 100644
|
|
3
|
+
--- a/src/numbers.js
|
|
4
|
+
+++ b/src/numbers.js
|
|
5
|
+
@@ -4,6 +4,6 @@ export const double = (n) => n * 2;
|
|
6
|
+
|
|
7
|
+
export const negate = (n) => -n;
|
|
8
|
+
|
|
9
|
+
-export const sumAll = (ns) => ns.reduce((total, n) => total, 0);
|
|
10
|
+
+export const sumAll = (ns) => ns.reduce((total, n) => total + n, 0);
|
|
11
|
+
|
|
12
|
+
export const countOf = (ns) => ns.length;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Trivial compat fixture: small number helpers. test/numbers.test.js is the
|
|
2
|
+
// source of truth for their behavior.
|
|
3
|
+
export const double = (n) => n * 2;
|
|
4
|
+
|
|
5
|
+
export const negate = (n) => -n;
|
|
6
|
+
|
|
7
|
+
export const sumAll = (ns) => ns.reduce((total, n) => total, 0);
|
|
8
|
+
|
|
9
|
+
export const countOf = (ns) => ns.length;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { countOf, double, negate, sumAll } from '../src/numbers.js';
|
|
5
|
+
|
|
6
|
+
test('double/negate/countOf helpers are correct', () => {
|
|
7
|
+
assert.equal(double(4), 8);
|
|
8
|
+
assert.equal(negate(3), -3);
|
|
9
|
+
assert.equal(countOf([1, 2, 3]), 3);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('sumAll returns the total of the list', () => {
|
|
13
|
+
assert.equal(sumAll([1, 2, 3]), 6);
|
|
14
|
+
assert.equal(sumAll([]), 0);
|
|
15
|
+
});
|
|
@@ -59,18 +59,3 @@ guarantee that a live provider-backed run will complete successfully.
|
|
|
59
59
|
|
|
60
60
|
Normal repository CI validates this example through non-live tests and package
|
|
61
61
|
checks without running providers.
|
|
62
|
-
|
|
63
|
-
## Manual Canary Workflow
|
|
64
|
-
|
|
65
|
-
Maintainers can dispatch the `Example Canary` GitHub Actions workflow when they
|
|
66
|
-
want a live provider-backed smoke test for this example. The workflow is
|
|
67
|
-
manual-only, uses the `example-canary` environment, and requires the
|
|
68
|
-
environment to provide `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or both depending
|
|
69
|
-
on the selected coder and reviewer providers.
|
|
70
|
-
|
|
71
|
-
The canary builds Neal, writes a temporary `~/.neal/config.yml` from the
|
|
72
|
-
selected provider roles, runs the example baseline tests, runs
|
|
73
|
-
`node ../../dist/neal/index.js run PLAN.md --no-squash` from this directory,
|
|
74
|
-
and uploads only curated markdown support artifacts from the example-local
|
|
75
|
-
`.neal/` directory. Scheduled canaries are deferred until cost and flakiness are
|
|
76
|
-
understood from intentional manual runs.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
diff --git a/src/clamp.ts b/src/clamp.ts
|
|
2
|
+
index 58793c4..c7a624d 100644
|
|
3
|
+
--- a/src/clamp.ts
|
|
4
|
+
+++ b/src/clamp.ts
|
|
5
|
+
@@ -1,3 +1,4 @@
|
|
6
|
+
+/** Restrict `value` to the inclusive range [lo, hi]. */
|
|
7
|
+
export function clamp(value: number, lo: number, hi: number): number {
|
|
8
|
+
return Math.max(lo, Math.min(hi, value));
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
diff --git a/src/greet.ts b/src/greet.ts
|
|
2
|
+
index 1c1e070..b768208 100644
|
|
3
|
+
--- a/src/greet.ts
|
|
4
|
+
+++ b/src/greet.ts
|
|
5
|
+
@@ -1,3 +1,7 @@
|
|
6
|
+
+function normalize(name: string): string {
|
|
7
|
+
+ return name.trim();
|
|
8
|
+
+}
|
|
9
|
+
+
|
|
10
|
+
export function greet(name: string): string {
|
|
11
|
+
- return 'Hello, ' + name.trim() + '!';
|
|
12
|
+
+ return 'Hello, ' + normalize(name) + '!';
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
diff --git a/src/load.ts b/src/load.ts
|
|
2
|
+
index 3da1e73..d7835c0 100644
|
|
3
|
+
--- a/src/load.ts
|
|
4
|
+
+++ b/src/load.ts
|
|
5
|
+
@@ -1,4 +1,8 @@
|
|
6
|
+
export async function loadConfig(read: () => Promise<string>): Promise<string> {
|
|
7
|
+
- const raw = await read();
|
|
8
|
+
- return raw.trim();
|
|
9
|
+
+ try {
|
|
10
|
+
+ const raw = await read();
|
|
11
|
+
+ return raw.trim();
|
|
12
|
+
+ } catch {
|
|
13
|
+
+ return '';
|
|
14
|
+
+ }
|
|
15
|
+
}
|