@navels/neal 0.6.7 → 0.6.9
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.
|
@@ -35,6 +35,7 @@ export function buildScopePrompt(planDoc, progressText) {
|
|
|
35
35
|
'Use `blocked` for unexpected impasses; use `manual_gate` for intentional waits where `manualGate.resumeChecks` can prove the external work is complete.',
|
|
36
36
|
'When action=`manual_gate`, include a non-null `manualGate` object with non-empty `id`, `title`, `reason`, `instructionsMarkdown`, and at least one command resume check. Keep `derivedPlan` and `blockedReason` empty.',
|
|
37
37
|
'When action is anything other than `manual_gate`, set `manualGate` to null.',
|
|
38
|
+
'Do not open a manual gate on tooling built in this same scope (a test harness, a procedure, a script): it has not been reviewed yet. Check for this before you start building, and set action=`split_plan` with a derived plan that builds and verifies the tooling in its own scope and opens the gate at the start of the next. Use `blocked` only when no such derived plan is practical.',
|
|
38
39
|
`If the target remains viable but the current scope has proven to be the wrong execution shape, set action=\`split_plan\` instead of forcing the bad shape or using action=\`blocked\`.`,
|
|
39
40
|
'Use action=`split_plan` only when the current scope result should be discarded and replaced by a safer derived plan for the same target.',
|
|
40
41
|
'When action=`split_plan`, put the complete derived plan body in `derivedPlan`.',
|
|
@@ -35,6 +35,7 @@ function getPlanReviewerReadinessLines() {
|
|
|
35
35
|
'A ready plan preserves the requested objective, proposes a sound approach, accounts for major architectural constraints and dependencies, uses a valid execution shape with coherent scopes, and gives each scope meaningful verification and a reviewable success condition.',
|
|
36
36
|
'The plan is written for both neal and the operator. It should be concise enough for a person to review, specific enough to guide implementation, and open enough for the coder to make local choices after inspecting the code.',
|
|
37
37
|
'Raise a blocking finding only when an omission is likely to produce the wrong implementation, make a scope unsafe or impractical, hide a major dependency, leave sequencing materially unclear, or allow incorrect work to appear complete.',
|
|
38
|
+
'Raise a blocking scope granularity finding when a single scope both builds tooling for the operator to use (a test harness, a procedure, a script) and opens a manual gate on its use. A gate opens before its scope is reviewed, so that tooling belongs in its own scope, reviewed and accepted first, with the gate opening at the start of the next scope.',
|
|
38
39
|
'Missing routine implementation detail is not a finding. Do not require exhaustive file, symbol, caller, test, command, assertion, line-number, pinned-value, or fixture inventories.',
|
|
39
40
|
'More detail can make a plan worse by turning tentative implementation choices into acceptance requirements. Ask for low-level detail only when it records a fixed decision, preserves compatibility, or prevents a known failure.',
|
|
40
41
|
...getPlanVerificationScopeLines('reviewer'),
|
|
@@ -71,6 +72,7 @@ function getPlanningPromptBaseLines(planDoc) {
|
|
|
71
72
|
'Do not leave planning-only scaffolding in the final file. Remove or replace sections such as planning mode instructions, Required Inputs for the planner, Verification For This Planning Task, and Completion Criteria For This Planning Task.',
|
|
72
73
|
'Your refined plan will be reviewed for execution readiness on three dimensions; satisfy each before finalizing: scope granularity (the work is divided into coherent, bounded scopes without exhaustive path inventories), verification concreteness (each scope names meaningful checks without specifying every possible oracle), and resume safety (scopes have understandable ordering and clean stopping points).',
|
|
73
74
|
'Make the final plan explicit about its execution shape, scope goals and approach, sequencing, meaningful verification, and success conditions. Add constraints, non-goals, or blocker handling only where the task needs them.',
|
|
75
|
+
'A manual gate pauses a scope for operator work outside the agent process, and it opens before that scope has been reviewed. So when the plan needs operator work that depends on something the run builds (a test harness, a procedure, a script), split it into two scopes: the first builds that tooling and verifies it as far as it can without the operator, and is reviewed and accepted like any other scope; the next scope opens the manual gate at its start and works with the results.',
|
|
74
76
|
'Choose `multi_scope` when the work changes orchestration or state-machine behavior, resume semantics, persistence or schema shape, multiple independent subsystems, or otherwise naturally falls into staged rollout checkpoints.',
|
|
75
77
|
'Choose `multi_scope_unknown` when the work repeats one bounded recurring slice at a time and the total number of scopes is intentionally unknown until an explicit completion condition is satisfied.',
|
|
76
78
|
'Choose `one_shot` only when the work can realistically be executed, reviewed, and verified as one bounded scope without hidden staging assumptions.',
|
|
@@ -123,6 +125,7 @@ function getAuthoredOneShotPlanningLines(authoredOneShot) {
|
|
|
123
125
|
}
|
|
124
126
|
return [
|
|
125
127
|
'This plan was authored as a single-scope (`one_shot`) plan; keep it one scope, make the smallest complete change, and do not restructure it into multiple scopes.',
|
|
128
|
+
'The one exception is operator work that depends on something the run builds: that plan cannot stay one scope, so declare `multi_scope`, expand only as far as the tooling scope and the manual-gate scope require, and say why in `message`.',
|
|
126
129
|
];
|
|
127
130
|
}
|
|
128
131
|
function getAuthoredOneShotReviewerLines(authoredOneShot) {
|
|
@@ -131,6 +134,7 @@ function getAuthoredOneShotReviewerLines(authoredOneShot) {
|
|
|
131
134
|
}
|
|
132
135
|
return [
|
|
133
136
|
'This plan was authored `one_shot`; raise a blocking finding if the document declares any other execution shape or adds orchestration sections.',
|
|
137
|
+
'The one exception is a plan that needs operator work that depends on something the run builds: accept `multi_scope` there when the expansion goes only as far as the tooling scope and the manual-gate scope require, and do not ask for that work to be folded back into one scope.',
|
|
134
138
|
];
|
|
135
139
|
}
|
|
136
140
|
export function buildPlanningPrompt(planDoc, planDocument, options) {
|
|
@@ -90,7 +90,7 @@ const CONSULTANT_CONTEXT = context('ConsultantPromptContext', [
|
|
|
90
90
|
export const PROMPT_SPECS = [
|
|
91
91
|
{
|
|
92
92
|
id: 'plan_author',
|
|
93
|
-
version:
|
|
93
|
+
version: 6,
|
|
94
94
|
changelog: [
|
|
95
95
|
{
|
|
96
96
|
version: 1,
|
|
@@ -112,6 +112,10 @@ export const PROMPT_SPECS = [
|
|
|
112
112
|
version: 5,
|
|
113
113
|
renderSha: '148ed793be3f39c4a5505289ab3045ff124d8c44a53bf5fa9ccc8c3c5f20d408',
|
|
114
114
|
},
|
|
115
|
+
{
|
|
116
|
+
version: 6,
|
|
117
|
+
renderSha: '7c302d4befbb252b8346fce67c47dbab38668c9a232f92a715831ddc11da59ec',
|
|
118
|
+
},
|
|
115
119
|
],
|
|
116
120
|
role: 'coder',
|
|
117
121
|
purpose: 'Author or revise concise, human-reviewable Neal-executable plans at moderate-to-high-level implementation detail.',
|
|
@@ -186,7 +190,7 @@ export const PROMPT_SPECS = [
|
|
|
186
190
|
},
|
|
187
191
|
{
|
|
188
192
|
id: 'plan_reviewer',
|
|
189
|
-
version:
|
|
193
|
+
version: 5,
|
|
190
194
|
changelog: [
|
|
191
195
|
{
|
|
192
196
|
version: 1,
|
|
@@ -204,6 +208,10 @@ export const PROMPT_SPECS = [
|
|
|
204
208
|
version: 4,
|
|
205
209
|
renderSha: '65ad05a8bbe1f4a6d631db8778bf6bed82249151f3412a7773f9568ae2d40f11',
|
|
206
210
|
},
|
|
211
|
+
{
|
|
212
|
+
version: 5,
|
|
213
|
+
renderSha: '45730ee47b7cb5dc93bc776a6db4a3fb1800160b0c6173d41b43b81c6244f85a',
|
|
214
|
+
},
|
|
207
215
|
],
|
|
208
216
|
role: 'reviewer',
|
|
209
217
|
purpose: 'Review human-reviewable Neal-executable plans for material approach, scope, verification, and resume-safety defects.',
|
|
@@ -289,7 +297,7 @@ export const PROMPT_SPECS = [
|
|
|
289
297
|
},
|
|
290
298
|
{
|
|
291
299
|
id: 'scope_coder',
|
|
292
|
-
version:
|
|
300
|
+
version: 4,
|
|
293
301
|
changelog: [
|
|
294
302
|
{
|
|
295
303
|
version: 1,
|
|
@@ -303,6 +311,10 @@ export const PROMPT_SPECS = [
|
|
|
303
311
|
version: 3,
|
|
304
312
|
renderSha: '8fb94430bf9d9abcb11f905106a3a04fc1b81bd101104c88f84a8693f705c5ea',
|
|
305
313
|
},
|
|
314
|
+
{
|
|
315
|
+
version: 4,
|
|
316
|
+
renderSha: '7c413f0bd9a71f77cc2dc93c44af6f672717324d8e4071bde93ecc25756b2841',
|
|
317
|
+
},
|
|
306
318
|
],
|
|
307
319
|
role: 'coder',
|
|
308
320
|
purpose: 'Execute exactly one bounded implementation scope and respond to in-scope review feedback without starting new scopes.',
|
package/docs/maintenance.md
CHANGED
|
@@ -10,7 +10,7 @@ Grouped so at most a handful of dependency PRs are ever open at once:
|
|
|
10
10
|
| Bucket | Contents | Cadence | Update posture |
|
|
11
11
|
| --- | --- | --- | --- |
|
|
12
12
|
| **Weekly non-major** | everything except the native SDKs (minor/patch/pin/digest) | weekly, one grouped PR | auto-merge after CI and the live smoke pass, subject to a 3-day soak |
|
|
13
|
-
| **Native SDKs** | `@openai/codex-sdk` and `@anthropic-ai/claude-agent-sdk`, both exact-pinned. `ai`, `@ai-sdk/openai-compatible`, and `zod` also stay exact-pinned. | one grouped PR, opened after the 3-day soak instead of waiting for the weekly schedule | qualify on a subscription-authenticated machine with `scripts/qualify-sdk.sh`. Never auto-merge.
|
|
13
|
+
| **Native SDKs** | `@openai/codex-sdk` and `@anthropic-ai/claude-agent-sdk`, both exact-pinned. `ai`, `@ai-sdk/openai-compatible`, and `zod` also stay exact-pinned. | one grouped PR, opened after the 3-day soak instead of waiting for the weekly schedule | qualify on a subscription-authenticated machine with `scripts/qualify-sdk.sh`. Never auto-merge. The CI smoke skips itself on these PRs because it does not exercise the native adapters. |
|
|
14
14
|
| **Library majors** | every npm major except the native SDKs (`typescript`, `@types/node`, `ai`, `@ai-sdk/openai-compatible`, `zod`, etc.) | monthly, one grouped PR | review manually because some need code changes |
|
|
15
15
|
| **GitHub Actions majors** | `actions/checkout`, `actions/setup-node`, `actions/upload-artifact`, etc. | monthly, one grouped PR separate from library majors | review and merge on green CI. Do not auto-merge because a major action bump can still change behavior. |
|
|
16
16
|
|
|
@@ -19,7 +19,7 @@ tool-calling, structured output, or sandbox behavior. That breaks neal's loop
|
|
|
19
19
|
**without** breaking compilation. And CI can't behaviorally exercise the
|
|
20
20
|
native adapters: their auth is subscription-based and lives only on a
|
|
21
21
|
maintainer's machine. Everything else is behaviorally exercised in CI: the
|
|
22
|
-
live smoke runs on
|
|
22
|
+
live smoke runs on package.json/lockfile PRs that change something it exercises, so the weekly grouped PR
|
|
23
23
|
is gated on it as a whole.
|
|
24
24
|
|
|
25
25
|
## The update flow
|
|
@@ -31,7 +31,7 @@ is gated on it as a whole.
|
|
|
31
31
|
2. **Verify (automatic).** CI (`.github/workflows/ci.yml`) runs typecheck + lint
|
|
32
32
|
+ unit tests + package verification on Node 24.18.0, which catches
|
|
33
33
|
**API-shape / contract** breaks. The live smoke
|
|
34
|
-
(`.github/workflows/smoke.yml`) runs on
|
|
34
|
+
(`.github/workflows/smoke.yml`) runs on package.json / lockfile PRs that change something it exercises (a version bump or a native-SDK pin bump skips it): a
|
|
35
35
|
real `neal compat` run against a cheap OpenRouter model through
|
|
36
36
|
`openai-compatible`, catching **behavioral** breaks in the AI-SDK tier. The
|
|
37
37
|
weekly non-major PR auto-merges when both are green.
|
package/docs/plan-format.md
CHANGED
|
@@ -61,6 +61,8 @@ planner is instructed to keep the plan one scope and make the smallest complete
|
|
|
61
61
|
change, and the plan reviewer is instructed to raise a blocking finding if the
|
|
62
62
|
refined document declares any other execution shape or adds orchestration
|
|
63
63
|
sections. That finding routes through the normal revision loop like any other.
|
|
64
|
+
The one exception is operator work that depends on something the run builds;
|
|
65
|
+
see [Manual gates](#manual-gates).
|
|
64
66
|
|
|
65
67
|
There is deliberately no hard mechanical clamp: if the review loop converges on
|
|
66
68
|
a different shape (the reviewer accepts an expansion), neal adopts the refined
|
|
@@ -172,6 +174,46 @@ complete. It is not a prose summary of the goal. It is the reviewable exit
|
|
|
172
174
|
criterion. Good success conditions mention the changed surface, the expected
|
|
173
175
|
behavior or docs state, and the verification evidence required for acceptance.
|
|
174
176
|
|
|
177
|
+
## Manual gates
|
|
178
|
+
|
|
179
|
+
A manual gate is how the coder pauses a scope for work only the operator can do:
|
|
180
|
+
running something on real hardware, flipping a setting in an external console,
|
|
181
|
+
making a call the plan left to a person. The coder writes instructions and one
|
|
182
|
+
or more resume checks, neal saves the instructions to a run-local `GATE-<id>.md`
|
|
183
|
+
file and stops, and `neal resume --run <run-id>` re-runs the checks and hands the
|
|
184
|
+
scope back to the coder when they pass.
|
|
185
|
+
|
|
186
|
+
A gate opens during the coder's first pass on a scope, before any review. The
|
|
187
|
+
reviewer sees nothing from that scope until the coder says the scope is done. So
|
|
188
|
+
anything the operator is asked to use at the gate has to come from a scope that
|
|
189
|
+
was already reviewed and accepted.
|
|
190
|
+
|
|
191
|
+
When a plan needs operator work that depends on something the run builds (a test
|
|
192
|
+
harness, a procedure, a script), split it into two scopes. The first builds that
|
|
193
|
+
tooling and verifies it as far as it can without the operator, and is reviewed
|
|
194
|
+
and accepted like any other scope. The next scope opens the manual gate at its
|
|
195
|
+
start and works with the results.
|
|
196
|
+
|
|
197
|
+
```md
|
|
198
|
+
### Scope 1: Build the sensor test harness
|
|
199
|
+
- Goal: Add `scripts/sensor-harness.sh`, which runs the calibration sweep against an attached board and writes `tmp/sensor-results.json`.
|
|
200
|
+
- Verification: `pnpm test`, plus a harness dry run against the recorded fixture.
|
|
201
|
+
- Success Condition: The harness runs end to end against the fixture and its output matches the documented result format.
|
|
202
|
+
|
|
203
|
+
### Scope 2: Run the harness on hardware and apply the results
|
|
204
|
+
- Goal: Open a manual gate asking the operator to run the harness on the bench board. Then set the calibration constants from `tmp/sensor-results.json`.
|
|
205
|
+
- Verification: The gate's resume check confirms `tmp/sensor-results.json` exists and parses; then `pnpm test`.
|
|
206
|
+
- Success Condition: The calibration constants come from a real hardware run, and the tests pass with them.
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
The planner, the plan reviewer, and the coder all hold to this. The planner
|
|
210
|
+
splits the plan this way. The plan reviewer raises a blocking finding on a scope
|
|
211
|
+
that both builds operator-facing tooling and gates on the operator using it. A
|
|
212
|
+
coder that lands in such a scope anyway returns `split_plan` with the two-scope
|
|
213
|
+
version instead of opening the gate. A plan authored `one_shot` may expand to
|
|
214
|
+
`multi_scope` for this, only as far as the tooling scope and the gate scope
|
|
215
|
+
require.
|
|
216
|
+
|
|
175
217
|
## Planning normalization
|
|
176
218
|
|
|
177
219
|
`neal plan` revises the selected plan file in place. It should preserve the
|
package/docs/troubleshooting.md
CHANGED
|
@@ -121,6 +121,15 @@ run-local `GATE-<id>.md` file shown by `neal status`.
|
|
|
121
121
|
**Fix:** do the manual step, then `neal resume --run <run-id>`, which re-runs
|
|
122
122
|
the gate's checks and resumes the scope when they pass. No `--message` here.
|
|
123
123
|
|
|
124
|
+
**Symptom:** the same gate keeps reopening: you do the step, resume, the coder
|
|
125
|
+
patches the script or procedure it handed you, and the gate opens again.
|
|
126
|
+
**Cause:** the tooling you were handed was built in the same scope that opened
|
|
127
|
+
the gate. A gate opens before its scope is reviewed, so that tooling reached you
|
|
128
|
+
unreviewed, and each fix-and-reopen round skips the reviewer too.
|
|
129
|
+
**Fix:** don't resume again. Split the plan so the tooling gets its own scope
|
|
130
|
+
ahead of the gate scope, then start a new run on the revised plan. See
|
|
131
|
+
[Manual gates](plan-format.md#manual-gates).
|
|
132
|
+
|
|
124
133
|
**Symptom:** a run seems hung or died silently.
|
|
125
134
|
**Where to look:** raw detail is persisted even when hidden from the terminal:
|
|
126
135
|
`.neal/runs/<run-id>/stderr.log` (full transcript) and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@navels/neal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "A source-first multi-agent CLI for planning, executing, reviewing, and resuming scoped code changes.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"author": "Lee Nave",
|
|
10
10
|
"type": "module",
|
|
11
|
-
"packageManager": "pnpm@11.
|
|
11
|
+
"packageManager": "pnpm@11.26.0",
|
|
12
12
|
"homepage": "https://github.com/navels/neal#readme",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"examples"
|
|
41
41
|
],
|
|
42
42
|
"engines": {
|
|
43
|
-
"node": ">=24.
|
|
44
|
-
"pnpm": ">=11.
|
|
43
|
+
"node": ">=24.21.0",
|
|
44
|
+
"pnpm": ">=11.26.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"build": "rm -rf dist && node node_modules/typescript-7/bin/tsc -p tsconfig.json && chmod +x dist/neal/index.js",
|
|
@@ -55,21 +55,21 @@
|
|
|
55
55
|
"typecheck": "node node_modules/typescript-7/bin/tsc --noEmit -p tsconfig.json && node node_modules/typescript-7/bin/tsc -p tsconfig.test.json"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@ai-sdk/openai-compatible": "3.0.
|
|
59
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
60
|
-
"@openai/codex-sdk": "0.
|
|
61
|
-
"ai": "7.0.
|
|
58
|
+
"@ai-sdk/openai-compatible": "3.0.47",
|
|
59
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.274",
|
|
60
|
+
"@openai/codex-sdk": "0.154.0",
|
|
61
|
+
"ai": "7.0.97",
|
|
62
62
|
"dotenv": "^17.4.2",
|
|
63
63
|
"yaml": "^2.9.0",
|
|
64
|
-
"zod": "4.
|
|
64
|
+
"zod": "4.6.2"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@eslint/js": "^10.0.1",
|
|
68
|
-
"@types/node": "^24.13.
|
|
69
|
-
"eslint": "^10.
|
|
68
|
+
"@types/node": "^24.13.4",
|
|
69
|
+
"eslint": "^10.10.0",
|
|
70
70
|
"tsx": "^4.23.13",
|
|
71
71
|
"typescript": "^6.0.3",
|
|
72
72
|
"typescript-7": "npm:typescript@^7.0.2",
|
|
73
|
-
"typescript-eslint": "^8.
|
|
73
|
+
"typescript-eslint": "^8.70.0"
|
|
74
74
|
}
|
|
75
75
|
}
|