@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
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
Symptom / cause / fix, in the order you'll hit them. Quoted text is what neal
|
|
4
|
+
prints. When in doubt: `neal check`, then `.neal/runs/<run-id>/stderr.log`.
|
|
5
|
+
|
|
6
|
+
## Install and first run
|
|
7
|
+
|
|
8
|
+
**Symptom:** install or startup fails on an old Node.
|
|
9
|
+
**Cause:** neal requires Node.js >= 22.13 (`engines`); `.nvmrc` pins `24`.
|
|
10
|
+
**Fix:** `nvm use` in this repo, or upgrade Node before `npm install -g @navels/neal`.
|
|
11
|
+
|
|
12
|
+
**Symptom:** `pnpm: command not found` when running from source.
|
|
13
|
+
**Cause:** the source path uses pnpm >= 11 via corepack.
|
|
14
|
+
**Fix:** `corepack enable && corepack prepare pnpm@11 --activate`, then `pnpm install`.
|
|
15
|
+
|
|
16
|
+
**Symptom:** `neal` not found after `pnpm run dev:link`.
|
|
17
|
+
**Cause:** the dev link registers `bin.neal` with the active Node installation only.
|
|
18
|
+
**Fix:** diagnose with `command -v neal` and `npm list -g --depth 0 --link=true`.
|
|
19
|
+
After source changes, `pnpm build` again so the linked command sees `dist/`.
|
|
20
|
+
|
|
21
|
+
**Symptom:** `neal setup` lists a provider with `- runtime not found`.
|
|
22
|
+
**Cause:** setup detects local runtime surfaces only (the `@openai/codex-sdk`
|
|
23
|
+
entrypoint; an SDK-bundled or on-PATH `claude` executable) — never auth.
|
|
24
|
+
**Fix:** install the provider's SDK/CLI, then rerun `neal setup` and `neal check`.
|
|
25
|
+
|
|
26
|
+
## Provider auth failures (`neal check`)
|
|
27
|
+
|
|
28
|
+
`neal check` sends one small prompt per unique configured provider/model
|
|
29
|
+
(interactive TTY only — non-interactive input prints
|
|
30
|
+
`Provider verification skipped: non-interactive input.`). Known failures:
|
|
31
|
+
|
|
32
|
+
**Symptom:** `Claude Code refused bypass-permissions mode while running as root.`
|
|
33
|
+
**Cause:** the Claude provider uses `permissionMode: bypassPermissions`, which
|
|
34
|
+
Claude Code refuses under root/sudo.
|
|
35
|
+
**Fix:** run neal from a non-root user, then `neal check` again.
|
|
36
|
+
|
|
37
|
+
**Symptom:** `OpenAI Codex has not trusted this directory yet.`
|
|
38
|
+
**Cause:** the Codex CLI's own per-directory trust prompt has not been answered.
|
|
39
|
+
**Fix:** complete the provider's normal local trust/setup step for the current
|
|
40
|
+
directory (e.g. run the `codex` CLI there once), then `neal check` again.
|
|
41
|
+
|
|
42
|
+
**Symptom:** `OpenAI Codex could not persist the check session.`
|
|
43
|
+
**Fix:** transient; run `neal check` again. If it repeats, redo the provider's
|
|
44
|
+
local setup.
|
|
45
|
+
|
|
46
|
+
**Symptom:** a `not logged in` message from either vendor CLI.
|
|
47
|
+
**Cause:** provider auth is provider-owned; neal never collects credentials.
|
|
48
|
+
**Fix:** complete the provider's normal local auth setup (the `codex` / `claude`
|
|
49
|
+
login flows), then `neal check` again.
|
|
50
|
+
|
|
51
|
+
**Symptom:** `Set providers.openai_compatible.base_url (or OPENAI_COMPATIBLE_BASE_URL) and OPENAI_COMPATIBLE_API_KEY before running Neal.`
|
|
52
|
+
(or `No model is resolvable for the openai-compatible ... role`).
|
|
53
|
+
**Cause:** `openai-compatible` / `generic-agentic` resolve settings 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
|
+
**Fix:** set the missing key. For OpenRouter: `base_url: https://openrouter.ai/api/v1`,
|
|
58
|
+
`api_key_env: OPENROUTER_API_KEY`, and export `OPENROUTER_API_KEY`. (OpenRouter
|
|
59
|
+
wraps upstream 429s in HTTP-200 bodies; neal unwraps and retries them.)
|
|
60
|
+
|
|
61
|
+
## Runs that won't start
|
|
62
|
+
|
|
63
|
+
**Symptom:** plan validation errors such as
|
|
64
|
+
`Missing required `## Execution Shape` section.` or
|
|
65
|
+
``## Execution Shape` must contain exactly one non-empty line.`
|
|
66
|
+
**Cause:** every executable plan must declare exactly one of
|
|
67
|
+
`executionShape: one_shot | multi_scope | multi_scope_unknown`; `multi_scope`
|
|
68
|
+
also requires an `## Execution Queue` with contiguous `### Scope N:` headings,
|
|
69
|
+
each carrying `- Goal:` / `- Verification:` / `- Success Condition:` bullets.
|
|
70
|
+
**Fix:** see [plan-format.md](plan-format.md), or let `neal plan` refine the
|
|
71
|
+
document into executable shape.
|
|
72
|
+
|
|
73
|
+
**Symptom:** a missing-config error naming `agent.coder.provider` or
|
|
74
|
+
`agent.reviewer.provider`.
|
|
75
|
+
**Cause:** fresh writer runs require explicit coder and reviewer providers;
|
|
76
|
+
built-in defaults are not enough.
|
|
77
|
+
**Fix:** `neal setup`, then `neal check`.
|
|
78
|
+
|
|
79
|
+
**Symptom:** `Cannot start neal execute with a dirty worktree:` followed by
|
|
80
|
+
`git status` lines (queues: `Cannot continue neal run with a dirty worktree:`).
|
|
81
|
+
**Cause:** writer admission requires a clean worktree; only the selected plan
|
|
82
|
+
document and neal-owned paths (`.neal/`) are exempt. Leftover reviewer scratch
|
|
83
|
+
(`build_review/`, `scratch/`, …) gets a
|
|
84
|
+
`Likely Neal reviewer scratch leakage detected:` diagnostic but still blocks —
|
|
85
|
+
the paths are not proven neal-owned.
|
|
86
|
+
**Fix:** use `neal resume` for in-progress scope work, or commit, stash, move,
|
|
87
|
+
or remove the dirty paths and start clean.
|
|
88
|
+
|
|
89
|
+
**Symptom:** a Git precondition error before any provider runs.
|
|
90
|
+
**Fix:** writer commands require a Git repository with an existing `HEAD`
|
|
91
|
+
commit; create the initial baseline commit first.
|
|
92
|
+
|
|
93
|
+
## Stuck or blocked runs
|
|
94
|
+
|
|
95
|
+
**Symptom:** the run stops with `status: "blocked"` (exit code 2).
|
|
96
|
+
**Cause:** blocked is a controlled state, not a failure: the coder hit
|
|
97
|
+
something it may not resolve alone, and attended runs wait for guidance.
|
|
98
|
+
**Fix:** `neal status` explains the blocker and prints the exact
|
|
99
|
+
`neal resume --run <run-id> --message "..."` command. `--message` is only
|
|
100
|
+
accepted in that waiting-for-guidance state.
|
|
101
|
+
|
|
102
|
+
**Symptom:** `effectiveStatus: "waiting_for_manual_gate"`.
|
|
103
|
+
**Cause:** the scope reached expected human work; instructions are in the
|
|
104
|
+
run-local `GATE-<id>.md` file shown by `neal status`.
|
|
105
|
+
**Fix:** do the manual step, then `neal resume --run <run-id>` — it re-runs
|
|
106
|
+
the gate's checks and resumes the scope when they pass. No `--message` here.
|
|
107
|
+
|
|
108
|
+
**Symptom:** a run seems hung or died silently.
|
|
109
|
+
**Where to look:** raw detail is persisted even when hidden from the terminal:
|
|
110
|
+
`.neal/runs/<run-id>/stderr.log` (full transcript) and
|
|
111
|
+
`.neal/runs/<run-id>/events.ndjson` (event log; startup-silence retries appear
|
|
112
|
+
as `provider.turn_liveness_*` events). On a live TTY, press `v` for the
|
|
113
|
+
low-level detail view. `neal status --json --run <run-id>` carries the latest
|
|
114
|
+
`providerError` classification.
|
|
115
|
+
|
|
116
|
+
## Lock issues
|
|
117
|
+
|
|
118
|
+
The writer lock is `.neal/active-run.lock`; writer processes remove it on
|
|
119
|
+
normal shutdown and on SIGINT/SIGTERM.
|
|
120
|
+
|
|
121
|
+
**Symptom:** `another Neal writer run is active in this checkout`.
|
|
122
|
+
**Fix:** as printed — `neal resume --run <run-id>` to continue that run, or
|
|
123
|
+
wait for it to finish.
|
|
124
|
+
|
|
125
|
+
**Symptom:** `another Neal process is already resuming this run` (with
|
|
126
|
+
`owning pid`). A live same-run lock under another pid is refused, not shared.
|
|
127
|
+
**Fix:** wait for that process, or inspect with `neal status --run <run-id>`.
|
|
128
|
+
|
|
129
|
+
**Symptom:** `stale Neal writer lock found in this checkout` /
|
|
130
|
+
`no process with that PID is running on this host.`
|
|
131
|
+
**Fix:** `neal resume --run <run-id>` clears stale same-host locks itself; if
|
|
132
|
+
you're starting different work instead, inspect the run, then remove the lock
|
|
133
|
+
file the message names.
|
|
134
|
+
|
|
135
|
+
**Symptom:** `Neal writer lock belongs to another host`.
|
|
136
|
+
**Fix:** inspect the other host before removing the lock; the message prints
|
|
137
|
+
the exact resume command for that checkout.
|
|
138
|
+
|
|
139
|
+
**Symptom:** `could not read the active Neal writer lock`.
|
|
140
|
+
**Fix:** as printed: inspect the named lock file before starting another
|
|
141
|
+
writer run; remove it only after confirming no writer process is active.
|
|
142
|
+
|
|
143
|
+
## "It squashed when I didn't want it to"
|
|
144
|
+
|
|
145
|
+
**Symptom:** per-scope commits are gone after a completed run.
|
|
146
|
+
**Cause:** completed `neal execute` / `neal run` runs squash run-owned commits
|
|
147
|
+
by default, without confirmation.
|
|
148
|
+
**Fix:** pass `--no-squash` to keep individual commits. The squashed range is
|
|
149
|
+
recorded in `.neal/runs/<run-id>/SQUASH_RESULT.json` and under `squash`
|
|
150
|
+
(`originalBaseCommit` / `replacementCommit`) in `neal status --json`.
|
|
151
|
+
Standalone `neal squash` is the opposite: it previews, requires interactive TTY
|
|
152
|
+
confirmation, and preserves later commits by replaying them on top.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Compat fixture: fix `add`
|
|
2
|
+
|
|
3
|
+
## Execution Shape
|
|
4
|
+
|
|
5
|
+
executionShape: one_shot
|
|
6
|
+
|
|
7
|
+
## Objective
|
|
8
|
+
|
|
9
|
+
`src/add.js` exports an `add(a, b)` helper that is supposed to return the sum of
|
|
10
|
+
its two arguments, but it currently returns the difference. The test in
|
|
11
|
+
`test/add.test.js` fails because of this bug.
|
|
12
|
+
|
|
13
|
+
Make the smallest complete change to `src/add.js` so that `add(a, b)` returns the
|
|
14
|
+
sum of `a` and `b`, then confirm the test passes.
|
|
15
|
+
|
|
16
|
+
## Boundaries
|
|
17
|
+
|
|
18
|
+
Allowed paths:
|
|
19
|
+
|
|
20
|
+
- `src/add.js`
|
|
21
|
+
|
|
22
|
+
Forbidden:
|
|
23
|
+
|
|
24
|
+
- Do not edit the test file.
|
|
25
|
+
- Do not add dependencies or new files.
|
|
26
|
+
|
|
27
|
+
## Verification
|
|
28
|
+
|
|
29
|
+
Run `node --test test/add.test.js`; it must exit `0`.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
diff --git a/src/add.js b/src/add.js
|
|
2
|
+
index 4125f75..a3e4914 100644
|
|
3
|
+
--- a/src/add.js
|
|
4
|
+
+++ b/src/add.js
|
|
5
|
+
@@ -1,2 +1,2 @@
|
|
6
|
+
// Trivial compat fixture: this addition helper is intentionally buggy.
|
|
7
|
+
-export const add = (a, b) => a - b;
|
|
8
|
+
+export const add = (a, b) => a * b;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
diff --git a/src/add.js b/src/add.js
|
|
2
|
+
index 4125f75..0088c50 100644
|
|
3
|
+
--- a/src/add.js
|
|
4
|
+
+++ b/src/add.js
|
|
5
|
+
@@ -1,2 +1,2 @@
|
|
6
|
+
// Trivial compat fixture: this addition helper is intentionally buggy.
|
|
7
|
+
-export const add = (a, b) => a - b;
|
|
8
|
+
+export const add = (a, b) => a + b;
|
|
@@ -0,0 +1,30 @@
|
|
|
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`.
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"fixtures": [
|
|
3
|
+
{
|
|
4
|
+
"id": "add-edit-verify",
|
|
5
|
+
"roles": ["coder", "reviewer"],
|
|
6
|
+
"projectDir": "add-edit-verify",
|
|
7
|
+
"planDoc": "add-edit-verify/PLAN.md",
|
|
8
|
+
"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
|
+
"referenceFix": {
|
|
22
|
+
"file": "src/strings.js",
|
|
23
|
+
"from": "s.split('').join('')",
|
|
24
|
+
"to": "s.split('').reverse().join('')"
|
|
25
|
+
},
|
|
26
|
+
"reviewer": {
|
|
27
|
+
"goodDiff": "reverse-grep-edit/good.diff",
|
|
28
|
+
"brokenDiff": "reverse-grep-edit/broken.diff"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"id": "is-even-add-test",
|
|
33
|
+
"roles": ["coder", "reviewer"],
|
|
34
|
+
"projectDir": "is-even-add-test",
|
|
35
|
+
"planDoc": "is-even-add-test/PLAN.md",
|
|
36
|
+
"verifyCommand": "node --test test/is-even.test.js",
|
|
37
|
+
"referenceFix": {
|
|
38
|
+
"file": "test/is-even.test.js",
|
|
39
|
+
"from": "assert.ok(false, 'TODO: replace this placeholder with a real test for isEven');",
|
|
40
|
+
"to": "assert.equal(isEven(4), true);"
|
|
41
|
+
},
|
|
42
|
+
"reviewer": {
|
|
43
|
+
"goodDiff": "is-even-add-test/good.diff",
|
|
44
|
+
"brokenDiff": "is-even-add-test/broken.diff"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "plan-greeting",
|
|
49
|
+
"roles": ["planner"],
|
|
50
|
+
"projectDir": "plan-greeting",
|
|
51
|
+
"issuePrompt": "plan-greeting/ISSUE.md",
|
|
52
|
+
"verifyCommand": "node --test test/greet.test.js",
|
|
53
|
+
"referenceFix": {
|
|
54
|
+
"file": "src/greet.js",
|
|
55
|
+
"from": "`Hello!`",
|
|
56
|
+
"to": "`Hello, ${name}!`"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Plan seed: fix the greeting helper
|
|
2
|
+
|
|
3
|
+
## Execution Shape
|
|
4
|
+
|
|
5
|
+
executionShape: one_shot
|
|
6
|
+
|
|
7
|
+
## Objective
|
|
8
|
+
|
|
9
|
+
`src/greet.js` exports `greet(name)`, which should return `Hello, <name>!` but
|
|
10
|
+
currently always returns `Hello!`, ignoring its argument. The test in
|
|
11
|
+
`test/greet.test.js` fails because of this.
|
|
12
|
+
|
|
13
|
+
Produce a one-shot plan that makes the smallest complete change to `src/greet.js`
|
|
14
|
+
so `greet(name)` returns `Hello, <name>!`, verified by
|
|
15
|
+
`node --test test/greet.test.js` exiting `0`.
|
|
16
|
+
|
|
17
|
+
## Boundaries
|
|
18
|
+
|
|
19
|
+
Allowed paths:
|
|
20
|
+
|
|
21
|
+
- `src/greet.js`
|
|
22
|
+
|
|
23
|
+
Forbidden:
|
|
24
|
+
|
|
25
|
+
- Do not edit the test file or add dependencies.
|
|
@@ -0,0 +1,32 @@
|
|
|
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`.
|
|
@@ -0,0 +1,12 @@
|
|
|
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);
|
|
@@ -0,0 +1,12 @@
|
|
|
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);
|
|
@@ -0,0 +1,10 @@
|
|
|
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);
|
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Issue Triage Example Improvement Plan
|
|
2
|
+
|
|
3
|
+
## Execution Shape
|
|
4
|
+
|
|
5
|
+
executionShape: multi_scope
|
|
6
|
+
|
|
7
|
+
## Objective
|
|
8
|
+
|
|
9
|
+
Improve this dependency-free JavaScript issue-triage example in small, reviewable
|
|
10
|
+
steps. Keep the package local to this directory and keep every scope verifiable
|
|
11
|
+
with the example's built-in Node test suite.
|
|
12
|
+
|
|
13
|
+
## Boundaries
|
|
14
|
+
|
|
15
|
+
Allowed paths:
|
|
16
|
+
|
|
17
|
+
- `examples/issue-triage-js/src/issue-triage.js`
|
|
18
|
+
- `examples/issue-triage-js/test/issue-triage.test.js`
|
|
19
|
+
- `examples/issue-triage-js/README.md`
|
|
20
|
+
|
|
21
|
+
`examples/issue-triage-js/PLAN.md` may be updated only if Neal's
|
|
22
|
+
plan-refinement loop makes a necessary structural clarification.
|
|
23
|
+
|
|
24
|
+
Forbidden paths and work:
|
|
25
|
+
|
|
26
|
+
- Do not edit Neal runtime source under `src/`.
|
|
27
|
+
- Do not edit root documentation, root package metadata, workflows, benchmark
|
|
28
|
+
files, or other repository-level files.
|
|
29
|
+
- Do not add dependencies, lockfiles, generated artifacts, provider transcripts,
|
|
30
|
+
or `.neal/` artifacts to Git.
|
|
31
|
+
- Do not call live network services from tests or package code.
|
|
32
|
+
|
|
33
|
+
## Current Behavior
|
|
34
|
+
|
|
35
|
+
The seed implementation parses simple lines such as
|
|
36
|
+
`- [P1] auth: Login fails @web #bug #customer`, summarizes counts, and formats a
|
|
37
|
+
short markdown report. It intentionally leaves several realistic edge cases for
|
|
38
|
+
this plan to improve.
|
|
39
|
+
|
|
40
|
+
## Execution Queue
|
|
41
|
+
|
|
42
|
+
### Scope 1: Add parser edge-case tests and support lowercase priorities, leading/trailing whitespace, and `*` bullets
|
|
43
|
+
- Goal: Add focused parser tests, then update `parseIssueLine` and `parseIssues` so issue lines can use lowercase priorities, leading or trailing whitespace, and either `-` or `*` bullets while preserving normalized `P1`-style priorities.
|
|
44
|
+
- Verification: Run `pnpm test` from `examples/issue-triage-js/`.
|
|
45
|
+
- Success Condition: Parser tests cover the new edge cases, the implementation handles them, existing baseline parsing still works, and the example test suite passes.
|
|
46
|
+
|
|
47
|
+
Implementation notes:
|
|
48
|
+
|
|
49
|
+
- Keep comments and blank lines ignored by `parseIssues`.
|
|
50
|
+
- Preserve the exported function names.
|
|
51
|
+
- Do not broaden the parser beyond issue-triage lines needed by this example.
|
|
52
|
+
|
|
53
|
+
### Scope 2: Add summary tests and fix optional owners, `unassigned` owner grouping, duplicate tag handling, and deterministic ordering
|
|
54
|
+
- Goal: Add summary-focused tests, then update parsing and summarization so owners are optional, missing owners are counted as `unassigned`, duplicate tags on one issue are counted once, and summary count objects are built in deterministic key order.
|
|
55
|
+
- Verification: Run `pnpm test` from `examples/issue-triage-js/`.
|
|
56
|
+
- Success Condition: Summary tests cover optional owners, duplicate tags, and deterministic ordering; `summarizeIssues` returns stable counts by priority, area, owner, and tag; and the example test suite passes.
|
|
57
|
+
|
|
58
|
+
Implementation notes:
|
|
59
|
+
|
|
60
|
+
- Keep `parseIssueLine` returning `owner: null` for issues without an owner.
|
|
61
|
+
- Apply the `unassigned` grouping in `summarizeIssues`.
|
|
62
|
+
- Prefer simple deterministic ordering over a new dependency.
|
|
63
|
+
|
|
64
|
+
### Scope 3: Add formatter tests and make `formatSummary(summary)` produce deterministic markdown sorted by priority, area, owner, and tag
|
|
65
|
+
- Goal: Add formatter tests, then update `formatSummary(summary)` so its markdown sections are deterministic and sorted by priority, area, owner, and tag.
|
|
66
|
+
- Verification: Run `pnpm test` from `examples/issue-triage-js/`.
|
|
67
|
+
- Success Condition: Formatter tests cover stable section ordering, sorted entries, and empty sections where relevant; `formatSummary(summary)` produces deterministic markdown; and the example test suite passes.
|
|
68
|
+
|
|
69
|
+
Implementation notes:
|
|
70
|
+
|
|
71
|
+
- Keep the report compact and readable.
|
|
72
|
+
- Do not change the summary object shape unless the tests require a small
|
|
73
|
+
backward-compatible clarification.
|
|
74
|
+
|
|
75
|
+
### Scope 4: Update the example README or sample usage to match the final behavior and keep the example tests passing
|
|
76
|
+
- Goal: Update `examples/issue-triage-js/README.md` or its sample usage so the documentation matches the final parser, summarizer, and formatter behavior.
|
|
77
|
+
- Verification: Run `pnpm test` from `examples/issue-triage-js/`.
|
|
78
|
+
- Success Condition: The README or sample usage accurately reflects the final behavior, does not direct users outside the example directory for code edits, and the example test suite passes.
|
|
79
|
+
|
|
80
|
+
Implementation notes:
|
|
81
|
+
|
|
82
|
+
- Keep the README focused on running and understanding this example.
|
|
83
|
+
- Do not document behavior that the tests do not cover.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Issue Triage JavaScript Example
|
|
2
|
+
|
|
3
|
+
This is a tiny dependency-free JavaScript package for trying Neal against a
|
|
4
|
+
real but small codebase. The seed package already has passing tests and a
|
|
5
|
+
limited implementation. `PLAN.md` asks Neal to improve the parser, summary, and
|
|
6
|
+
formatter across four local scopes.
|
|
7
|
+
|
|
8
|
+
The package parses issue lines shaped like:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
- [P1] auth: Login fails @web #bug #customer
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Node.js 22 or newer
|
|
17
|
+
- pnpm
|
|
18
|
+
- A Git repository with an initial commit before running Neal
|
|
19
|
+
- Configured Neal providers for the live `neal run` path
|
|
20
|
+
|
|
21
|
+
## Non-Live Verification
|
|
22
|
+
|
|
23
|
+
From the repository root:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pnpm --dir examples/issue-triage-js test
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
From this example directory:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
pnpm test
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
These commands use Node's built-in test runner. They do not call Neal, use
|
|
36
|
+
provider credentials, or spend model budget.
|
|
37
|
+
|
|
38
|
+
## Live Neal Run
|
|
39
|
+
|
|
40
|
+
Use a disposable branch or worktree so the example changes are easy to inspect
|
|
41
|
+
or discard.
|
|
42
|
+
|
|
43
|
+
From the repository root:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
neal setup
|
|
47
|
+
neal check
|
|
48
|
+
cd examples/issue-triage-js
|
|
49
|
+
neal run PLAN.md
|
|
50
|
+
pnpm test
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use `neal run --no-squash PLAN.md` when you want to inspect the per-scope
|
|
54
|
+
commits Neal creates during the run.
|
|
55
|
+
|
|
56
|
+
`neal run` uses the providers configured by `neal setup`. It can take time and
|
|
57
|
+
may spend provider budget. Passing the local tests before the run does not
|
|
58
|
+
guarantee that a live provider-backed run will complete successfully.
|
|
59
|
+
|
|
60
|
+
Normal repository CI validates this example through non-live tests and package
|
|
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.
|