@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
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { renderReviewerContextMarkdown } from '../context/reviewer-context.js';
|
|
1
|
+
import { renderInlinedRangeDiffSection } from '../context/inline-review-context.js';
|
|
3
2
|
import { AUTONOMY_BLOCKED, AUTONOMY_DONE, AUTONOMY_SCOPE_DONE, AUTONOMY_SPLIT_PLAN, buildProgressSection, getCanonicalPlanContractLines, getDerivedPlanSectionContractLines, getExecuteScopeProgressPayloadContractLines, getProtocolMarkerArtifactProhibitionLines, getStandalonePlanPayloadSourceOfTruthLines, getTerminalMarkerArtifactBoundaryLines, getUnattendedAutonomyLines, } from './shared.js';
|
|
4
3
|
import { assertPromptBuilder } from './assert-builder.js';
|
|
5
4
|
import { getUserGuidanceLines } from './guidance.js';
|
|
6
|
-
import { getAdversarialReviewDoctrineLines, getCodeReviewFalsificationLines, getFindingQualityLines, getPreexistingFailureContractLines, getRegressionPreservationLines, getVerificationSkepticismLines,
|
|
5
|
+
import { getAdversarialReviewDoctrineLines, getCodeReviewFalsificationLines, getFindingQualityLines, getPreexistingFailureContractLines, getRegressionPreservationLines, getVerificationSkepticismLines, } from './review-doctrine.js';
|
|
7
6
|
const PROMPT_MODULE_PATH = 'src/neal/prompts/execute.ts';
|
|
8
7
|
export const CODER_REGRESSION_PRESERVATION_LINE = 'Treat existing behavior on the code paths you touch as part of the contract: identify the shared subsystems your change intersects (state, parsing, dispatch, lifecycle, storage, startup) and confirm that adjacent behavior on those paths still works — by running existing tests that exercise them when such tests exist, or by concrete reasoning through representative flows otherwise — before you finish.';
|
|
9
8
|
export const CODER_PREEXISTING_FAILURE_LINES = [
|
|
@@ -115,12 +114,7 @@ export function buildReviewerPrompt(args) {
|
|
|
115
114
|
if (!primaryVariant || !meaningfulProgressVariant) {
|
|
116
115
|
throw new Error('Prompt spec scope_reviewer is missing primary or meaningful-progress coverage');
|
|
117
116
|
}
|
|
118
|
-
const accessMode =
|
|
119
|
-
builder: 'buildReviewerPrompt',
|
|
120
|
-
accessMode: args.accessMode,
|
|
121
|
-
inlineContextSupplied: Boolean(args.inlineContext),
|
|
122
|
-
});
|
|
123
|
-
const noRead = accessMode === 'no-read';
|
|
117
|
+
const accessMode = args.accessMode ?? 'tool-access';
|
|
124
118
|
// A collected diff may legitimately be the empty string (a range with no
|
|
125
119
|
// changes); distinguish "collected" (any string, including '') from "not
|
|
126
120
|
// collected" (null/undefined) so an empty diff still rides the inlined channel
|
|
@@ -158,12 +152,7 @@ export function buildReviewerPrompt(args) {
|
|
|
158
152
|
reviewTarget: 'scope diff',
|
|
159
153
|
mode: accessMode,
|
|
160
154
|
});
|
|
161
|
-
const reviewHistoryLine =
|
|
162
|
-
? 'Prior review history is inlined below if you need earlier reviewer findings or coder responses, but review the inlined diff for the current commit range directly.'
|
|
163
|
-
: `Prior review history is available at ${args.reviewMarkdownPath} if you need earlier reviewer findings or coder responses, but review the current commit range directly.`;
|
|
164
|
-
if (noRead) {
|
|
165
|
-
assertNoReadPromptInstructionText([...falsificationLines, ...skepticismLines, ...regressionLines, ...preexistingLines, reviewHistoryLine].join('\n'), 'buildReviewerPrompt');
|
|
166
|
-
}
|
|
155
|
+
const reviewHistoryLine = `Prior review history is available at ${args.reviewMarkdownPath} if you need earlier reviewer findings or coder responses, but review the current commit range directly.`;
|
|
167
156
|
return [
|
|
168
157
|
`Review the current scope for plan ${args.planDoc}.`,
|
|
169
158
|
`Review round: ${args.round}.`,
|
|
@@ -192,7 +181,7 @@ export function buildReviewerPrompt(args) {
|
|
|
192
181
|
'Changed files:',
|
|
193
182
|
changedFilesText,
|
|
194
183
|
'',
|
|
195
|
-
...getReviewerContextLines(args.reviewerContext
|
|
184
|
+
...getReviewerContextLines(args.reviewerContext),
|
|
196
185
|
`The active parent objective for meaningful-progress evaluation is scope ${args.parentScopeLabel}.`,
|
|
197
186
|
'You are the authority for meaningful-progress gating during this execute review pass, but perform that judgment after the adversarial correctness review above.',
|
|
198
187
|
'Set `meaningfulProgressAction` to `accept` only when either this scope materially advances the active parent objective, or a top-level scope has no required new diff because prior accepted work already satisfies it and you find no issues with sufficient verification evidence.',
|
|
@@ -216,7 +205,6 @@ export function buildReviewerPrompt(args) {
|
|
|
216
205
|
'If prior review history or continuity context describes a finding as fixed, rejected, or deferred, do not reopen the same claim from that history alone.',
|
|
217
206
|
'Before emitting a finding that resembles a prior fixed/rejected/deferred finding, inspect the current code or current diff and cite fresh current evidence showing the defect still exists.',
|
|
218
207
|
'If current evidence is ambiguous for an already-addressed claim, do not use a blocking finding to force another coder loop; use meaningfulProgressAction=`block_for_operator` only when operator judgment is genuinely required.',
|
|
219
|
-
...(args.inlineContext ? ['', renderInlineReviewerContext(args.inlineContext)] : []),
|
|
220
208
|
...(rangeDiffInlined
|
|
221
209
|
? [
|
|
222
210
|
'',
|
|
@@ -228,13 +216,13 @@ export function buildReviewerPrompt(args) {
|
|
|
228
216
|
: []),
|
|
229
217
|
].join('\n');
|
|
230
218
|
}
|
|
231
|
-
function getReviewerContextLines(reviewerContext
|
|
219
|
+
function getReviewerContextLines(reviewerContext) {
|
|
232
220
|
if (!reviewerContext) {
|
|
233
221
|
return [];
|
|
234
222
|
}
|
|
235
223
|
return [
|
|
236
224
|
'Bounded current-run continuity context:',
|
|
237
|
-
|
|
225
|
+
reviewerContext.promptMarkdown,
|
|
238
226
|
'',
|
|
239
227
|
];
|
|
240
228
|
}
|
|
@@ -1,10 +1,45 @@
|
|
|
1
|
-
import { assertNoReadPromptInstructionText, renderInlineReviewerContext, } from '../context/inline-review-context.js';
|
|
2
|
-
import { renderReviewerContextMarkdown } from '../context/reviewer-context.js';
|
|
3
1
|
import { AUTONOMY_BLOCKED, AUTONOMY_DONE, getCanonicalPlanContractLines, getDerivedPlanSectionContractLines, getProtocolMarkerArtifactProhibitionLines, getTerminalMarkerArtifactBoundaryLines, getUnattendedAutonomyLines, } from './shared.js';
|
|
4
2
|
import { assertPromptBuilder } from './assert-builder.js';
|
|
5
3
|
import { getUserGuidanceLines } from './guidance.js';
|
|
6
|
-
import { getAdversarialReviewDoctrineLines, getPlanReviewFalsificationLines, getVerificationSkepticismLines, resolveReviewerPromptAccessMode, } from './review-doctrine.js';
|
|
7
4
|
const PROMPT_MODULE_PATH = 'src/neal/prompts/planning.ts';
|
|
5
|
+
const PLAN_VERIFICATION_NECESSITY_RULE = 'A repository-wide invariant or global regression guarantee belongs in the plan only when it is necessary for the requested change to be correct.';
|
|
6
|
+
function getPlanVerificationScopeLines(role) {
|
|
7
|
+
return [
|
|
8
|
+
PLAN_VERIFICATION_NECESSITY_RULE,
|
|
9
|
+
role === 'planner'
|
|
10
|
+
? 'Otherwise, do not introduce it. If the plan already contains an unnecessary broader guarantee, narrow or remove it instead of expanding the implementation or verification scope to satisfy it.'
|
|
11
|
+
: 'Otherwise, do not require additional implementation or verification to satisfy it. If an unnecessary broader guarantee makes the plan misleading, require the planner to narrow or remove the guarantee rather than expand its coverage.',
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
function getPlanDetailLevelLines() {
|
|
15
|
+
return [
|
|
16
|
+
'Write for both neal and the operator. Prefer the smallest human-reviewable plan that communicates the approach, scope boundaries, and important decisions.',
|
|
17
|
+
'Use moderate-to-high-level implementation detail. Name major subsystems, important files, or key interfaces when they clarify the approach, but leave routine implementation discovery to the coder and reviewer working against the implementation.',
|
|
18
|
+
'Inspect the repository enough to confirm that the approach fits the existing architecture and to identify major dependencies, constraints, and affected subsystems. Do not try to complete the implementation or its full blast-radius analysis in the plan.',
|
|
19
|
+
'Leave routine file, symbol, caller, and test discovery to execution. Avoid line-by-line change lists, exhaustive inventories, exact assertions, pinned values, and fixture recipes unless they preserve a fixed decision or prevent a known failure.',
|
|
20
|
+
'Use allowed-path lists, forbidden-path lists, and detailed blocker handling only when the task has a real boundary or known hazard that needs to survive into execution.',
|
|
21
|
+
...getPlanVerificationScopeLines('planner'),
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
function getPlanResponseDetailLevelLines() {
|
|
25
|
+
return [
|
|
26
|
+
'Keep the revised plan concise, human-reviewable, and at moderate-to-high-level implementation detail.',
|
|
27
|
+
'Resolve material findings without expanding the plan into an exhaustive implementation inventory; leave routine discovery to execution.',
|
|
28
|
+
...getPlanVerificationScopeLines('planner'),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
function getPlanReviewerReadinessLines() {
|
|
32
|
+
return [
|
|
33
|
+
'Review the plan independently and look for material problems before accepting it.',
|
|
34
|
+
'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.',
|
|
35
|
+
'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.',
|
|
36
|
+
'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.',
|
|
37
|
+
'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.',
|
|
38
|
+
'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.',
|
|
39
|
+
...getPlanVerificationScopeLines('reviewer'),
|
|
40
|
+
'Inspect enough repository context to support material findings. Do not audit every implementation path before code has been written.',
|
|
41
|
+
];
|
|
42
|
+
}
|
|
8
43
|
function getPlanningPromptBaseLines(planDoc) {
|
|
9
44
|
return [
|
|
10
45
|
`Refine the existing plan document at ${planDoc} into a stronger future execution plan for neal.`,
|
|
@@ -15,15 +50,17 @@ function getPlanningPromptBaseLines(planDoc) {
|
|
|
15
50
|
'3. Reset your instructions for this turn from the current contents of the plan and referenced context.',
|
|
16
51
|
'',
|
|
17
52
|
'Then identify weaknesses in the current plan and improve it. Look specifically for:',
|
|
18
|
-
'- Underdeveloped scopes that need
|
|
53
|
+
'- Underdeveloped scopes that need enough implementation detail to guide the coder.',
|
|
54
|
+
'- Missing major architectural constraints or dependencies.',
|
|
19
55
|
'- Vague or missing acceptance criteria / completion criteria.',
|
|
20
56
|
'- Ambiguous scope boundaries or hidden assumptions about the repository.',
|
|
21
57
|
'- Poor or unclear sequencing between scopes.',
|
|
22
|
-
'- Verification that
|
|
58
|
+
'- Verification that would not meaningfully establish the scope\'s success.',
|
|
23
59
|
'- Planning-task scaffolding left over from an earlier draft.',
|
|
24
60
|
'Produce a substantively improved revision in the same file.',
|
|
25
61
|
'If the current plan is already strong, do not invent new weaknesses; revise only what actually improves it.',
|
|
26
62
|
"Refine for executability without expanding the author's scope. Include refactoring only when the plan calls for it, the objective genuinely requires it, or implementing the change would otherwise increase complexity such that a refactor is a natural outgrowth — not opportunistically.",
|
|
63
|
+
...getPlanDetailLevelLines(),
|
|
27
64
|
'',
|
|
28
65
|
'Revise only plan-related artifacts.',
|
|
29
66
|
'Do not edit runtime source code outside the plan itself and adjacent planning notes.',
|
|
@@ -31,10 +68,8 @@ function getPlanningPromptBaseLines(planDoc) {
|
|
|
31
68
|
'Your output must be a pure future execution plan, not a planning-task checklist.',
|
|
32
69
|
'Replace the plan in place so the resulting file is meant to be run later with `neal execute`, not `neal plan`.',
|
|
33
70
|
'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.',
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'Do not ask the future executor to perform redundant edits. If an export already propagates through an existing barrel file, say to verify that behavior instead of adding a fake extra edit step.',
|
|
37
|
-
'Make the final plan explicit about scope boundaries, allowed scope, forbidden paths, implementation steps, verification, completion criteria, blocker handling, and any repeated-scope selection rules.',
|
|
71
|
+
'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).',
|
|
72
|
+
'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.',
|
|
38
73
|
'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.',
|
|
39
74
|
'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.',
|
|
40
75
|
'Choose `one_shot` only when the work can realistically be executed, reviewed, and verified as one bounded scope without hidden staging assumptions.',
|
|
@@ -75,10 +110,10 @@ function getPlanReviewerModeLines(args) {
|
|
|
75
110
|
: 'Examples of blocking leftover scaffolding include planning-mode execution headers, planner-only required-input sections, "Verification For This Planning Task", and "Completion Criteria For This Planning Task".',
|
|
76
111
|
focusRule: mode === 'derived-plan'
|
|
77
112
|
? 'Focus on whether the derived plan actually addresses the failure mode, is concrete enough to execute, reduces blast radius, and is truly not a blocker.'
|
|
78
|
-
: 'Focus on plan quality for refinement:
|
|
113
|
+
: 'Focus on plan quality for refinement: a sound implementation approach, material architectural constraints, coherent scopes, clear sequencing, meaningful verification, and reviewable success conditions. Do not turn routine implementation discovery into plan findings.',
|
|
79
114
|
contractRule: mode === 'derived-plan'
|
|
80
115
|
? derivedPlanContractRule
|
|
81
|
-
: 'Focus on whether the plan is now a clean future execution plan, explicit about single-scope vs repeated-scope behavior, and clear about verification and completion.',
|
|
116
|
+
: 'Focus on whether the plan is now a clean, human-reviewable future execution plan, explicit about single-scope vs repeated-scope behavior, and clear about verification and completion.',
|
|
82
117
|
};
|
|
83
118
|
}
|
|
84
119
|
function getAuthoredOneShotPlanningLines(authoredOneShot) {
|
|
@@ -142,49 +177,22 @@ export function buildPlanReviewerPrompt(args) {
|
|
|
142
177
|
if (!spec.variants.some((variant) => variant.kind === expectedVariant)) {
|
|
143
178
|
throw new Error(`Prompt spec ${spec.id} is missing variant ${expectedVariant}`);
|
|
144
179
|
}
|
|
145
|
-
const accessMode =
|
|
146
|
-
builder: 'buildPlanReviewerPrompt',
|
|
147
|
-
accessMode: args.accessMode,
|
|
148
|
-
inlineContextSupplied: Boolean(args.inlineContext),
|
|
149
|
-
});
|
|
150
|
-
const noRead = accessMode === 'no-read';
|
|
180
|
+
const accessMode = args.accessMode ?? 'tool-access';
|
|
151
181
|
const modeLines = getPlanReviewerModeLines({
|
|
152
182
|
mode,
|
|
153
183
|
planDoc: args.planDoc,
|
|
154
184
|
parentPlanDoc: args.parentPlanDoc,
|
|
155
185
|
derivedFromScopeNumber: args.derivedFromScopeNumber,
|
|
156
186
|
});
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
insufficientCoverageTarget: 'planned behavior',
|
|
162
|
-
mode: accessMode,
|
|
163
|
-
});
|
|
164
|
-
const reviewHistoryLine = noRead
|
|
165
|
-
? 'Prior review history and coder responses are inlined below; consider them before finalizing findings.'
|
|
166
|
-
: `Read ${args.reviewMarkdownPath} before finalizing findings so you can inspect prior review history and coder responses.`;
|
|
167
|
-
const planInspectionLine = noRead
|
|
168
|
-
? 'The reviewed plan content (and any parent plan content) is inlined below; finalize findings entirely from the inlined context in this prompt.'
|
|
169
|
-
: accessMode === 'read-only'
|
|
170
|
-
? 'The reviewed plan content is inlined below; use your read-only file tools to inspect directly referenced companion docs and repository source files before finalizing findings.'
|
|
171
|
-
: 'The reviewed plan content is inlined below; use repository tools to inspect directly referenced companion docs and repository source files before finalizing findings.';
|
|
172
|
-
if (noRead) {
|
|
173
|
-
assertNoReadPromptInstructionText([...skepticismLines, reviewHistoryLine, planInspectionLine].join('\n'), 'buildPlanReviewerPrompt');
|
|
174
|
-
}
|
|
187
|
+
const reviewHistoryLine = `Read ${args.reviewMarkdownPath} before finalizing findings so you can inspect prior review history and coder responses.`;
|
|
188
|
+
const planInspectionLine = accessMode === 'read-only'
|
|
189
|
+
? 'The reviewed plan content is inlined below; use your read-only file tools to inspect directly referenced companion docs and repository source files before finalizing findings.'
|
|
190
|
+
: 'The reviewed plan content is inlined below; use repository tools to inspect directly referenced companion docs and repository source files before finalizing findings.';
|
|
175
191
|
return [
|
|
176
192
|
modeLines.heading,
|
|
177
193
|
`Review round: ${args.round}.`,
|
|
178
194
|
'',
|
|
179
|
-
...
|
|
180
|
-
reviewSubject: 'the plan-readiness claim',
|
|
181
|
-
falsificationTarget: 'whether the plan is actually Neal-executable',
|
|
182
|
-
creditPhrase: 'accept it as ready',
|
|
183
|
-
claimSources: 'the plan narrative, prior review history, or operator framing',
|
|
184
|
-
judgmentTarget: 'plan readiness',
|
|
185
|
-
proofTarget: 'the plan will guide safe execution',
|
|
186
|
-
}),
|
|
187
|
-
...skepticismLines,
|
|
195
|
+
...getPlanReviewerReadinessLines(),
|
|
188
196
|
'',
|
|
189
197
|
'Produce only structured review findings.',
|
|
190
198
|
'This is a read-only plan review. Do not edit files, create scratch artifacts, stage changes, commit, or otherwise mutate the repository.',
|
|
@@ -192,41 +200,41 @@ export function buildPlanReviewerPrompt(args) {
|
|
|
192
200
|
'You must confirm the declared execution shape and echo it in the required `executionShape` field of your structured output.',
|
|
193
201
|
'Raise a blocking finding when the declared shape is missing, internally inconsistent, or not safe for neal execution.',
|
|
194
202
|
'Assess execution readiness explicitly across these dimensions: scope granularity, verification concreteness, and resume safety.',
|
|
195
|
-
...getPlanReviewFalsificationLines(),
|
|
196
203
|
'When you raise a blocking finding about execution readiness, name the failing dimension directly in the claim or required action.',
|
|
197
204
|
'Every finding must rest on concrete evidence, not assumption. Any claim about the repository’s current state — whether a file, symbol, export, or test node id exists, or whether a verification command collects or passes — must be verified by direct inspection (read the file, search the tree, collect the tests) and cite what you found; any claim about the plan must quote the exact plan text it rests on. If you cannot verify a claim, state the uncertainty instead of raising it as blocking.',
|
|
198
205
|
'Never infer the repository’s current state from what the plan proposes to change. A plan proposing to add a file, class, or test is not evidence that it already exists; a plan introducing a new abstraction is not evidence that existing code or tests are already organized around it. Confirm presence or absence against the actual tree before asserting it.',
|
|
199
|
-
'Scope granularity means
|
|
200
|
-
'Verification concreteness means
|
|
201
|
-
'Resume safety means scopes have clean stopping points
|
|
206
|
+
'Scope granularity means the work is divided into coherent, bounded scopes. It does not require an exhaustive allowed-path inventory.',
|
|
207
|
+
'Verification concreteness means each scope names checks that can meaningfully establish success. It does not require every possible test, oracle, assertion, or shell command to be designed in advance.',
|
|
208
|
+
'Resume safety means scopes have understandable ordering and clean stopping points. It does not require the plan to prescribe routine Git mechanics.',
|
|
202
209
|
'A plan should generally be forced to `multi_scope` when it changes orchestration behavior, resume semantics, persistence/schema shape, multiple independent subsystems, or naturally staged rollout checkpoints.',
|
|
203
210
|
'A plan should generally be forced to `multi_scope_unknown` when the work is an intentionally open-ended recurring loop that still executes one bounded scope per cycle and ends only when a stated completion condition becomes true.',
|
|
204
211
|
modeLines.blockingRule,
|
|
205
212
|
modeLines.scaffoldingRule,
|
|
206
213
|
modeLines.wideningRule,
|
|
207
214
|
'Use non_blocking severity for clarity improvements that do not block execution.',
|
|
215
|
+
'Classify every finding with a `findingClass` of either `plan_correctness` or `verification_hardening`.',
|
|
216
|
+
'A `verification_hardening` finding asks for a material improvement to how already-specified behavior will be verified. It may block only when the planned checks could allow the requested change itself to be wrong while still appearing complete. Incomplete enforcement of an unnecessary broader guarantee introduced by the plan is non-blocking.',
|
|
217
|
+
'A `plan_correctness` finding means the plan would build the wrong thing, build an unverifiable thing, or contains an impossible or self-contradictory instruction. When you are unsure which class applies, use `plan_correctness`.',
|
|
208
218
|
modeLines.focusRule,
|
|
209
219
|
modeLines.contractRule,
|
|
210
220
|
'If the plan is already Neal-executable, confirm that quickly and return no manufactured findings.',
|
|
211
221
|
reviewHistoryLine,
|
|
212
222
|
...getAuthoredOneShotReviewerLines(args.authoredOneShot),
|
|
213
|
-
...getReviewerContextLines(args.reviewerContext
|
|
223
|
+
...getReviewerContextLines(args.reviewerContext),
|
|
214
224
|
...getUnattendedAutonomyLines(args.unattended),
|
|
215
225
|
...getUserGuidanceLines('reviewer'),
|
|
216
226
|
'',
|
|
217
227
|
planInspectionLine,
|
|
218
228
|
...getReviewedPlanContentLines({
|
|
219
|
-
noRead,
|
|
220
229
|
planDoc: args.planDoc,
|
|
221
230
|
reviewedPlanContent: args.reviewedPlanContent,
|
|
222
231
|
parentPlanDoc: args.parentPlanDoc,
|
|
223
232
|
parentPlanContent: args.parentPlanContent,
|
|
224
233
|
}),
|
|
225
|
-
...(args.inlineContext ? ['', renderInlineReviewerContext(args.inlineContext)] : []),
|
|
226
234
|
].join('\n');
|
|
227
235
|
}
|
|
228
236
|
function getReviewedPlanContentLines(args) {
|
|
229
|
-
if (
|
|
237
|
+
if (!args.reviewedPlanContent) {
|
|
230
238
|
return [];
|
|
231
239
|
}
|
|
232
240
|
return [
|
|
@@ -247,14 +255,14 @@ function getReviewedPlanContentLines(args) {
|
|
|
247
255
|
'Use the inlined plan content above as the authoritative plan text for plan-readiness review. Repository inspection should focus on validating referenced files, symbols, assumptions, and companion docs.',
|
|
248
256
|
];
|
|
249
257
|
}
|
|
250
|
-
function getReviewerContextLines(reviewerContext
|
|
258
|
+
function getReviewerContextLines(reviewerContext) {
|
|
251
259
|
if (!reviewerContext) {
|
|
252
260
|
return [];
|
|
253
261
|
}
|
|
254
262
|
return [
|
|
255
263
|
'',
|
|
256
264
|
'Bounded current-run continuity context:',
|
|
257
|
-
|
|
265
|
+
reviewerContext.promptMarkdown,
|
|
258
266
|
];
|
|
259
267
|
}
|
|
260
268
|
export function buildCoderPlanResponsePrompt(args) {
|
|
@@ -277,6 +285,7 @@ export function buildCoderPlanResponsePrompt(args) {
|
|
|
277
285
|
: 'Edit only the plan document and directly related planning artifacts.',
|
|
278
286
|
'Do not edit runtime source code.',
|
|
279
287
|
'Do not make git commits.',
|
|
288
|
+
...getPlanResponseDetailLevelLines(),
|
|
280
289
|
reviewMode === 'derived-plan'
|
|
281
290
|
? 'Keep the same target, but make the derived plan concrete enough to replace the abandoned scope safely.'
|
|
282
291
|
: 'The final file must be a pure future execution plan for `neal execute`.',
|
|
@@ -285,7 +294,7 @@ export function buildCoderPlanResponsePrompt(args) {
|
|
|
285
294
|
: 'Do not leave planning-task scaffolding behind after you respond to the findings.',
|
|
286
295
|
reviewMode === 'derived-plan'
|
|
287
296
|
? 'Revise the derived plan so it uses the same Neal-executable contract as a top-level plan. Any derived-plan-specific rationale sections are optional additive context only; they must not replace the canonical machine-consumed sections.'
|
|
288
|
-
: '
|
|
297
|
+
: 'Resolve the material finding without adding planning-task scaffolding.',
|
|
289
298
|
...(reviewMode === 'derived-plan' ? getDerivedPlanSectionContractLines() : []),
|
|
290
299
|
...getProtocolMarkerArtifactProhibitionLines(),
|
|
291
300
|
...(reviewMode === 'derived-plan' ? getCanonicalPlanContractLines() : []),
|
|
@@ -1,20 +1,3 @@
|
|
|
1
|
-
// Resolve the effective doctrine access mode for a reviewer prompt builder.
|
|
2
|
-
// Precedence: an explicit accessMode wins; when absent, derive exactly the
|
|
3
|
-
// legacy two-way behavior (inline context present -> 'no-read', else
|
|
4
|
-
// 'tool-access') so existing callers render byte-identically. Inline context
|
|
5
|
-
// combined with an explicit mode other than 'no-read' is mismatched wiring
|
|
6
|
-
// (the call site inlined context for a reviewer the capability registry says
|
|
7
|
-
// can read), which is a bug rather than a render choice.
|
|
8
|
-
export function resolveReviewerPromptAccessMode(args) {
|
|
9
|
-
if (args.inlineContextSupplied && args.accessMode !== undefined && args.accessMode !== 'no-read') {
|
|
10
|
-
throw new Error(`${args.builder} received Neal-inlined reviewer context with explicit access mode ${JSON.stringify(args.accessMode)}; ` +
|
|
11
|
-
"inline context is only valid with the 'no-read' access mode");
|
|
12
|
-
}
|
|
13
|
-
if (args.accessMode !== undefined) {
|
|
14
|
-
return args.accessMode;
|
|
15
|
-
}
|
|
16
|
-
return args.inlineContextSupplied ? 'no-read' : 'tool-access';
|
|
17
|
-
}
|
|
18
1
|
export function getAdversarialReviewDoctrineLines(context) {
|
|
19
2
|
const falsificationTarget = context.falsificationTarget ?? 'the implementation';
|
|
20
3
|
const creditPhrase = context.creditPhrase ?? 'give it credit for working';
|
|
@@ -32,16 +15,11 @@ export function getCodeReviewFalsificationLines(context) {
|
|
|
32
15
|
const rangeDiffInlined = mode === 'read-only' && context.rangeDiffInlined === true;
|
|
33
16
|
const lines = [];
|
|
34
17
|
if (context.rangeLabel) {
|
|
35
|
-
lines.push(mode === '
|
|
36
|
-
?
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
: `Review that ${context.rangeLabel} directly with your read-only repository tools: use the git_diff tool to see exactly what the ${context.rangeLabel} changed (including deletions and renames), and your read tools to verify the surrounding code. The ${context.rangeLabel} is the source of truth for this review.`
|
|
41
|
-
: `Review that ${context.rangeLabel} directly with repository tools. The ${context.rangeLabel} is the source of truth for this review.`);
|
|
42
|
-
}
|
|
43
|
-
if (mode === 'no-read') {
|
|
44
|
-
lines.push('A diff shows only changed hunks; declarations such as imports, struct fields, or helpers may exist in unchanged parts of the file. Never raise a missing-import or missing-declaration finding from absence in the diff alone — only claim one when the diff itself removes the declaration or adds a new file that lacks it. If you cannot verify such a claim from the inlined context, state the uncertainty instead of asserting a defect.');
|
|
18
|
+
lines.push(mode === 'read-only'
|
|
19
|
+
? rangeDiffInlined
|
|
20
|
+
? `The commit-range diff for that ${context.rangeLabel} is inlined below and is the source of truth for exactly what the ${context.rangeLabel} changed (including deletions and renames). Use your read tools to verify the surrounding code; you have no commit-range diff tool, so rely on the inlined diff for what changed.`
|
|
21
|
+
: `Review that ${context.rangeLabel} directly with your read-only repository tools: use the git_diff tool to see exactly what the ${context.rangeLabel} changed (including deletions and renames), and your read tools to verify the surrounding code. The ${context.rangeLabel} is the source of truth for this review.`
|
|
22
|
+
: `Review that ${context.rangeLabel} directly with repository tools. The ${context.rangeLabel} is the source of truth for this review.`);
|
|
45
23
|
}
|
|
46
24
|
if (mode === 'read-only') {
|
|
47
25
|
lines.push('A diff shows only changed hunks; declarations such as imports, struct fields, or helpers may exist in unchanged parts of the file. Absence from the diff is not evidence of absence from the repository — open the affected file with your read tools and verify before claiming a missing import or missing declaration.');
|
|
@@ -56,9 +34,7 @@ export function getCodeReviewFalsificationLines(context) {
|
|
|
56
34
|
: 'Inspect the change with your read-only tools: call git_diff with the base and head commits named in this prompt (stat:true first for the changed-file overview, then per-path diffs), read the changed files in full, and search the tree for affected symbols and callers to verify claims.');
|
|
57
35
|
}
|
|
58
36
|
}
|
|
59
|
-
lines.push(`Trace the changed runtime path far enough to prove the happy path is reachable and that runtime invariants, data-shape transitions, persistence, and error paths line up with the implementation claims.`,
|
|
60
|
-
? `Compare claimed behavior against the actual code and data transitions in the ${reviewTarget}; do not accept summaries when the inlined diff gives a more direct answer.`
|
|
61
|
-
: `Compare claimed behavior against the actual code and data transitions in the ${reviewTarget}; do not accept summaries when repository inspection gives a more direct answer.`, 'For refactors and config/runtime plumbing changes, actively look for implementation-quality regressions, not just behavioral correctness. Examples include replacing a robust library with a weaker hand-rolled parser, introducing repeated disk reads or reparsing in hot paths, silently weakening error handling, or otherwise making the implementation materially less robust than the prior version.');
|
|
37
|
+
lines.push(`Trace the changed runtime path far enough to prove the happy path is reachable and that runtime invariants, data-shape transitions, persistence, and error paths line up with the implementation claims.`, `Compare claimed behavior against the actual code and data transitions in the ${reviewTarget}; do not accept summaries when repository inspection gives a more direct answer.`, 'For refactors and config/runtime plumbing changes, actively look for implementation-quality regressions, not just behavioral correctness. Examples include replacing a robust library with a weaker hand-rolled parser, introducing repeated disk reads or reparsing in hot paths, silently weakening error handling, or otherwise making the implementation materially less robust than the prior version.');
|
|
62
38
|
lines.push('When the requirements enumerate multiple discrete items to change — a list of identifiers, fields, files, endpoints, or call sites — enumerate them yourself and confirm each maps to a concrete change before accepting; do not accept based only on the subset the implementation happened to touch.', 'Treat an unrequested change to a public or exported symbol — a renamed or removed exported function, type, field, constant, or signature that the requirements did not call for — as scope drift and a blocking finding unless the requirements require it: an unrequested public-symbol change widens the blast radius and can break callers the diff does not show.');
|
|
63
39
|
if (context.includeExecuteFailureClasses) {
|
|
64
40
|
lines.push('Bias your search toward execute-mode failure classes in this repository: persistence or state-shape mismatches, resume or recovery transition regressions, split-plan or execution-shape contract violations, artifact or reporting mismatches, and verification that does not actually cover the changed behavior.');
|
|
@@ -77,9 +53,7 @@ export function getVerificationSkepticismLines(context = {}) {
|
|
|
77
53
|
].join(' ')
|
|
78
54
|
: 'Check whether test coverage for the changed behavior degraded. If the change removes, weakens, or fails to preserve meaningful test coverage for the affected behavior, treat that as a review finding. Use blocking severity when the missing or degraded coverage leaves the changed behavior insufficiently protected.';
|
|
79
55
|
return [
|
|
80
|
-
|
|
81
|
-
? 'Do not infer that verification was skipped merely because this prompt does not embed full terminal output. Treat missing verification as a finding only when the inlined context, plan requirements, or review history give concrete evidence that required verification was not run or was insufficient.'
|
|
82
|
-
: 'Do not infer that verification was skipped merely because this prompt does not embed full terminal output. Treat missing verification as a finding only when the repository state, plan requirements, or review history give concrete evidence that required verification was not run or was insufficient.',
|
|
56
|
+
'Do not infer that verification was skipped merely because this prompt does not embed full terminal output. Treat missing verification as a finding only when the repository state, plan requirements, or review history give concrete evidence that required verification was not run or was insufficient.',
|
|
83
57
|
`Look for verification that cannot catch the failure mode, including tests that mock away the risky runtime path or only assert mocked adapters instead of the ${reviewTarget}.`,
|
|
84
58
|
coverageLine,
|
|
85
59
|
];
|
|
@@ -90,11 +64,9 @@ export function getRegressionPreservationLines(context = {}) {
|
|
|
90
64
|
return [
|
|
91
65
|
`Identify the shared subsystems the ${reviewTarget} touches: state machines, event loops, parsers or byte framing, command dispatch, storage or shared-state abstractions, startup/load paths, and long-lived session or connection state.`,
|
|
92
66
|
'Existing behavior that depends on those subsystems remains part of the contract unless the plan explicitly changes it. Do not accept solely because the newly requested behavior appears implemented; also confirm that adjacent behavior sharing those paths still holds.',
|
|
93
|
-
mode === '
|
|
94
|
-
? 'Before accepting, either cite existing tests
|
|
95
|
-
:
|
|
96
|
-
? 'Before accepting, either cite existing tests that cover the plausible regression surfaces — reading them with your read tools — or reason through representative existing flows at the level of state transitions and data ownership.'
|
|
97
|
-
: 'Before accepting, either cite existing tests that cover the plausible regression surfaces — running them when available — or reason through representative existing flows at the level of state transitions and data ownership.',
|
|
67
|
+
mode === 'read-only'
|
|
68
|
+
? 'Before accepting, either cite existing tests that cover the plausible regression surfaces — reading them with your read tools — or reason through representative existing flows at the level of state transitions and data ownership.'
|
|
69
|
+
: 'Before accepting, either cite existing tests that cover the plausible regression surfaces — running them when available — or reason through representative existing flows at the level of state transitions and data ownership.',
|
|
98
70
|
`Expand this regression check only along paths the ${reviewTarget} actually touches or depends on; you do not need to re-audit unrelated parts of the project.`,
|
|
99
71
|
];
|
|
100
72
|
}
|
|
@@ -104,22 +76,13 @@ export function getPreexistingFailureContractLines(context = {}) {
|
|
|
104
76
|
return [
|
|
105
77
|
`When the plan requires existing behavior to keep working, this review is not limited to newly changed lines. Apply an acceptance-surface test to any pre-existing crash, failure, flaky behavior, or anomaly reported in the coder narrative, progress justification, or review history instead of discounting it because it predates the ${reviewTarget}.`,
|
|
106
78
|
"A pre-existing failure is inside the required acceptance surface when the plan explicitly requires the affected existing behavior to keep working, when the plan's stated verification fails because of it, or when the behavior the plan delivers cannot be exercised end-to-end without the failing path. Otherwise it is outside the surface.",
|
|
107
|
-
mode === '
|
|
108
|
-
? "For a reported pre-existing failure inside the required surface,
|
|
109
|
-
:
|
|
110
|
-
? "For a reported pre-existing failure inside the required surface, read the most relevant existing tests and affected code with your read tools and reason through the affected existing flows directly rather than relying on the coder's dismissal."
|
|
111
|
-
: "For a reported pre-existing failure inside the required surface, exercise or reason through the affected existing flows directly — run the most relevant existing tests or reproduce the reported behavior when practical — rather than relying on the coder's dismissal.",
|
|
79
|
+
mode === 'read-only'
|
|
80
|
+
? "For a reported pre-existing failure inside the required surface, read the most relevant existing tests and affected code with your read tools and reason through the affected existing flows directly rather than relying on the coder's dismissal."
|
|
81
|
+
: "For a reported pre-existing failure inside the required surface, exercise or reason through the affected existing flows directly — run the most relevant existing tests or reproduce the reported behavior when practical — rather than relying on the coder's dismissal.",
|
|
112
82
|
'An in-surface pre-existing failure that was neither fixed nor surfaced as a blocking concern is a blocking finding, and a dismissal without a concrete out-of-surface reason is a finding.',
|
|
113
83
|
'Conversely, treat a fix for a pre-existing issue that fails the acceptance-surface test as scope drift rather than extra credit: flag it so the change stays bounded to the plan.',
|
|
114
84
|
];
|
|
115
85
|
}
|
|
116
|
-
export function getPlanReviewFalsificationLines() {
|
|
117
|
-
return [
|
|
118
|
-
'Try to falsify whether the plan would actually guide safe execution before accepting it as ready.',
|
|
119
|
-
'Check whether the proposed scopes, sequencing, and verification would catch the riskiest failure modes instead of merely describing plausible work.',
|
|
120
|
-
'Treat vague verification, hidden state assumptions, broad blast radius, and missing resume boundaries as evidence against plan readiness.',
|
|
121
|
-
];
|
|
122
|
-
}
|
|
123
86
|
export function getFindingQualityLines(context = {}) {
|
|
124
87
|
if (context.outputContract === 'completion_verdict') {
|
|
125
88
|
return [
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { guardStructuredJsonOutputFormatLines } from '../agents/structured-json.js';
|
|
2
|
-
import {
|
|
3
|
-
import { renderReviewerContextMarkdown } from '../context/reviewer-context.js';
|
|
2
|
+
import { renderInlinedRangeDiffSection } from '../context/inline-review-context.js';
|
|
4
3
|
import { assertPromptBuilder } from './assert-builder.js';
|
|
5
4
|
import { getUserGuidanceLines } from './guidance.js';
|
|
6
5
|
import { getUnattendedAutonomyLines } from './shared.js';
|
|
7
|
-
import { getAdversarialReviewDoctrineLines, getCodeReviewFalsificationLines, getFindingQualityLines, getPreexistingFailureContractLines, getRegressionPreservationLines, getVerificationSkepticismLines,
|
|
6
|
+
import { getAdversarialReviewDoctrineLines, getCodeReviewFalsificationLines, getFindingQualityLines, getPreexistingFailureContractLines, getRegressionPreservationLines, getVerificationSkepticismLines, } from './review-doctrine.js';
|
|
8
7
|
const PROMPT_MODULE_PATH = 'src/neal/prompts/specialized.ts';
|
|
9
8
|
// Guarded output-format instruction block shared by the two structured-JSON
|
|
10
9
|
// completion base prompts. It emits only JSON-only framing and a
|
|
@@ -15,7 +14,7 @@ const PROMPT_MODULE_PATH = 'src/neal/prompts/specialized.ts';
|
|
|
15
14
|
// instructions exclusively through this helper. The transport-deferring line is
|
|
16
15
|
// provider-neutral: the neal-json protocol block is appended below the base
|
|
17
16
|
// prompt only on the wrapper path (anthropic-claude and the repair loop), while
|
|
18
|
-
// other transports (e.g.
|
|
17
|
+
// other transports (e.g. openai-compatible) send the base prompt with no protocol
|
|
19
18
|
// below it, so the line must not claim instructions appear "below".
|
|
20
19
|
export function completionJsonOutputFormatLines(label) {
|
|
21
20
|
return guardStructuredJsonOutputFormatLines([
|
|
@@ -80,12 +79,7 @@ export function buildFinalCompletionReviewerPrompt(args) {
|
|
|
80
79
|
if (!finalCompletionVariant) {
|
|
81
80
|
throw new Error('Prompt spec completion_reviewer is missing a final_completion variant');
|
|
82
81
|
}
|
|
83
|
-
const accessMode =
|
|
84
|
-
builder: 'buildFinalCompletionReviewerPrompt',
|
|
85
|
-
accessMode: args.accessMode,
|
|
86
|
-
inlineContextSupplied: Boolean(args.inlineContext),
|
|
87
|
-
});
|
|
88
|
-
const noRead = accessMode === 'no-read';
|
|
82
|
+
const accessMode = args.accessMode ?? 'tool-access';
|
|
89
83
|
// A collected diff may legitimately be the empty string (a range with no
|
|
90
84
|
// changes); distinguish "collected" (any string, including '') from "not
|
|
91
85
|
// collected" (null/undefined) so an empty diff still rides the inlined channel
|
|
@@ -128,9 +122,6 @@ export function buildFinalCompletionReviewerPrompt(args) {
|
|
|
128
122
|
reviewTarget: 'aggregate implementation',
|
|
129
123
|
mode: accessMode,
|
|
130
124
|
});
|
|
131
|
-
if (noRead) {
|
|
132
|
-
assertNoReadPromptInstructionText([...falsificationLines, ...skepticismLines, ...regressionLines, ...preexistingLines].join('\n'), 'buildFinalCompletionReviewerPrompt');
|
|
133
|
-
}
|
|
134
125
|
return [
|
|
135
126
|
`Review whether the execute-mode plan at ${args.planDoc} is complete as a whole.`,
|
|
136
127
|
'',
|
|
@@ -157,7 +148,7 @@ export function buildFinalCompletionReviewerPrompt(args) {
|
|
|
157
148
|
...preexistingLines,
|
|
158
149
|
...getFindingQualityLines({ outputContract: 'completion_verdict' }),
|
|
159
150
|
'Review the whole-plan result for correctness and completeness against the plan objectives, regressions or missing behavior, cross-scope integration issues that may not have been visible in individual scope reviews, code quality, maintainability, and consistency of the final implementation, and adequacy of test coverage and verification for the total change.',
|
|
160
|
-
...getReviewerContextLines(args.reviewerContext
|
|
151
|
+
...getReviewerContextLines(args.reviewerContext),
|
|
161
152
|
'Do not treat prior per-scope acceptance as sufficient evidence that the whole plan is complete or that the aggregate code quality is acceptable.',
|
|
162
153
|
...completionJsonOutputFormatLines('buildFinalCompletionReviewerPrompt'),
|
|
163
154
|
'Use `accept_complete` only when the full plan objectives are satisfied and the aggregate implementation is acceptable under ordinary code review standards.',
|
|
@@ -204,7 +195,6 @@ export function buildFinalCompletionReviewerPrompt(args) {
|
|
|
204
195
|
'',
|
|
205
196
|
'Last non-empty implementation scope reference:',
|
|
206
197
|
lastImplementationScope,
|
|
207
|
-
...(args.inlineContext ? ['', renderInlineReviewerContext(args.inlineContext)] : []),
|
|
208
198
|
...(rangeDiffInlined
|
|
209
199
|
? [
|
|
210
200
|
'',
|
|
@@ -216,13 +206,13 @@ export function buildFinalCompletionReviewerPrompt(args) {
|
|
|
216
206
|
: []),
|
|
217
207
|
].join('\n');
|
|
218
208
|
}
|
|
219
|
-
function getReviewerContextLines(reviewerContext
|
|
209
|
+
function getReviewerContextLines(reviewerContext) {
|
|
220
210
|
if (!reviewerContext) {
|
|
221
211
|
return [];
|
|
222
212
|
}
|
|
223
213
|
return [
|
|
224
214
|
'',
|
|
225
215
|
'Bounded current-run continuity context:',
|
|
226
|
-
|
|
216
|
+
reviewerContext.promptMarkdown,
|
|
227
217
|
];
|
|
228
218
|
}
|