@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.
Files changed (170) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +527 -0
  3. package/SECURITY.md +91 -0
  4. package/config.yml +104 -0
  5. package/dist/neal/activity-footer.js +177 -0
  6. package/dist/neal/activity-reporting.js +1 -0
  7. package/dist/neal/adjudicator/artifacts.js +58 -0
  8. package/dist/neal/adjudicator/blocked-adjudicator.js +223 -0
  9. package/dist/neal/adjudicator/contracts.js +139 -0
  10. package/dist/neal/adjudicator/execute.js +611 -0
  11. package/dist/neal/adjudicator/final-completion.js +104 -0
  12. package/dist/neal/adjudicator/planning.js +145 -0
  13. package/dist/neal/adjudicator/specs.js +453 -0
  14. package/dist/neal/agents/prompts.js +120 -0
  15. package/dist/neal/agents/rounds.js +706 -0
  16. package/dist/neal/agents/schemas.js +832 -0
  17. package/dist/neal/agents/structured-coder.js +82 -0
  18. package/dist/neal/agents/structured-json.js +528 -0
  19. package/dist/neal/agents.js +4 -0
  20. package/dist/neal/atomic-write.js +18 -0
  21. package/dist/neal/blocked-guidance.js +406 -0
  22. package/dist/neal/cli.js +471 -0
  23. package/dist/neal/commands/check.js +401 -0
  24. package/dist/neal/commands/compat.js +807 -0
  25. package/dist/neal/commands/interactive-activity.js +57 -0
  26. package/dist/neal/commands/new-run.js +79 -0
  27. package/dist/neal/commands/plan-and-execute.js +44 -0
  28. package/dist/neal/commands/recovery-guidance.js +217 -0
  29. package/dist/neal/commands/resume-run.js +395 -0
  30. package/dist/neal/commands/review.js +21 -0
  31. package/dist/neal/commands/runtime.js +557 -0
  32. package/dist/neal/commands/setup.js +596 -0
  33. package/dist/neal/commands/squash.js +113 -0
  34. package/dist/neal/commands/status.js +33 -0
  35. package/dist/neal/commands/writer-exit-codes.js +42 -0
  36. package/dist/neal/commit-message.js +17 -0
  37. package/dist/neal/config.js +432 -0
  38. package/dist/neal/context/artifacts.js +140 -0
  39. package/dist/neal/context/context.js +324 -0
  40. package/dist/neal/context/inline-review-context.js +131 -0
  41. package/dist/neal/context/reviewer-context.js +166 -0
  42. package/dist/neal/context/shared.js +117 -0
  43. package/dist/neal/context/types.js +1 -0
  44. package/dist/neal/diagnostic.js +208 -0
  45. package/dist/neal/execute-finalization.js +5 -0
  46. package/dist/neal/final-completion-review.js +188 -0
  47. package/dist/neal/final-completion.js +229 -0
  48. package/dist/neal/git.js +339 -0
  49. package/dist/neal/index.js +135 -0
  50. package/dist/neal/interactive-controls.js +85 -0
  51. package/dist/neal/logger.js +102 -0
  52. package/dist/neal/manual-gates.js +121 -0
  53. package/dist/neal/orchestrator/artifacts.js +70 -0
  54. package/dist/neal/orchestrator/completion.js +531 -0
  55. package/dist/neal/orchestrator/failures.js +31 -0
  56. package/dist/neal/orchestrator/notifications.js +175 -0
  57. package/dist/neal/orchestrator/phases/coder.js +516 -0
  58. package/dist/neal/orchestrator/phases/planning.js +540 -0
  59. package/dist/neal/orchestrator/phases/recovery.js +798 -0
  60. package/dist/neal/orchestrator/phases/review.js +136 -0
  61. package/dist/neal/orchestrator/phases/shared.js +279 -0
  62. package/dist/neal/orchestrator/run-loop.js +113 -0
  63. package/dist/neal/orchestrator/split-plan.js +235 -0
  64. package/dist/neal/orchestrator/transitions.js +309 -0
  65. package/dist/neal/orchestrator.js +215 -0
  66. package/dist/neal/phase-display.js +27 -0
  67. package/dist/neal/plan-doc.js +154 -0
  68. package/dist/neal/plan-queue.js +1092 -0
  69. package/dist/neal/plan-refinement.js +39 -0
  70. package/dist/neal/plan-validation.js +525 -0
  71. package/dist/neal/progress.js +237 -0
  72. package/dist/neal/prompts/assert-builder.js +13 -0
  73. package/dist/neal/prompts/execute.js +290 -0
  74. package/dist/neal/prompts/guidance.js +70 -0
  75. package/dist/neal/prompts/planning.js +313 -0
  76. package/dist/neal/prompts/review-doctrine.js +142 -0
  77. package/dist/neal/prompts/shared.js +101 -0
  78. package/dist/neal/prompts/specialized.js +212 -0
  79. package/dist/neal/prompts/specs.js +572 -0
  80. package/dist/neal/providers/anthropic-claude.js +1599 -0
  81. package/dist/neal/providers/detection.js +139 -0
  82. package/dist/neal/providers/generic-agentic-tools.js +586 -0
  83. package/dist/neal/providers/generic-agentic.js +1238 -0
  84. package/dist/neal/providers/liveness.js +151 -0
  85. package/dist/neal/providers/openai-codex.js +1014 -0
  86. package/dist/neal/providers/openai-compatible.js +654 -0
  87. package/dist/neal/providers/registry.js +389 -0
  88. package/dist/neal/providers/telemetry.js +208 -0
  89. package/dist/neal/providers/types.js +21 -0
  90. package/dist/neal/recovery-artifacts.js +50 -0
  91. package/dist/neal/resume-decision.js +220 -0
  92. package/dist/neal/resume-planner.js +265 -0
  93. package/dist/neal/retrospective.js +391 -0
  94. package/dist/neal/review-debt.js +18 -0
  95. package/dist/neal/review-findings/artifacts.js +173 -0
  96. package/dist/neal/review-findings/prompts.js +172 -0
  97. package/dist/neal/review-findings/provider.js +330 -0
  98. package/dist/neal/review-findings/run.js +373 -0
  99. package/dist/neal/review-findings/types.js +1 -0
  100. package/dist/neal/review-mode.js +67 -0
  101. package/dist/neal/review.js +137 -0
  102. package/dist/neal/run-lock.js +334 -0
  103. package/dist/neal/run-metrics.js +355 -0
  104. package/dist/neal/run-narrative-types.js +1 -0
  105. package/dist/neal/run-narrative.js +1374 -0
  106. package/dist/neal/run-registry.js +218 -0
  107. package/dist/neal/run-status.js +25 -0
  108. package/dist/neal/scopes.js +451 -0
  109. package/dist/neal/sensitive-text.js +8 -0
  110. package/dist/neal/squash-message.js +379 -0
  111. package/dist/neal/squash.js +591 -0
  112. package/dist/neal/state-invariants.js +496 -0
  113. package/dist/neal/state-views.js +344 -0
  114. package/dist/neal/state.js +887 -0
  115. package/dist/neal/status-footer.js +258 -0
  116. package/dist/neal/status.js +1260 -0
  117. package/dist/neal/storage-paths.js +57 -0
  118. package/dist/neal/support.js +58 -0
  119. package/dist/neal/terminal-narrator.js +435 -0
  120. package/dist/neal/types.js +1 -0
  121. package/dist/neal/verification-events.js +81 -0
  122. package/dist/neal/version.js +37 -0
  123. package/dist/neal/worktree-status.js +137 -0
  124. package/dist/notifier.js +44 -0
  125. package/docs/ADJUDICATOR_INVENTORY.md +310 -0
  126. package/docs/PROMPT_SPECS.md +266 -0
  127. package/docs/README.md +22 -0
  128. package/docs/architecture.md +113 -0
  129. package/docs/assets/neal-execution-flow.png +0 -0
  130. package/docs/automation.md +65 -0
  131. package/docs/comparison.md +105 -0
  132. package/docs/compat.md +269 -0
  133. package/docs/compatible-models.md +135 -0
  134. package/docs/demo.md +55 -0
  135. package/docs/maintenance.md +64 -0
  136. package/docs/plan-format.md +213 -0
  137. package/docs/providers.md +751 -0
  138. package/docs/release.md +147 -0
  139. package/docs/state-machine.md +266 -0
  140. package/docs/storage.md +207 -0
  141. package/docs/troubleshooting.md +152 -0
  142. package/examples/compat/add-edit-verify/PLAN.md +29 -0
  143. package/examples/compat/add-edit-verify/broken.diff +8 -0
  144. package/examples/compat/add-edit-verify/good.diff +8 -0
  145. package/examples/compat/add-edit-verify/package.json +5 -0
  146. package/examples/compat/add-edit-verify/src/add.js +2 -0
  147. package/examples/compat/add-edit-verify/test/add.test.js +9 -0
  148. package/examples/compat/is-even-add-test/PLAN.md +30 -0
  149. package/examples/compat/is-even-add-test/broken.diff +11 -0
  150. package/examples/compat/is-even-add-test/good.diff +11 -0
  151. package/examples/compat/is-even-add-test/package.json +5 -0
  152. package/examples/compat/is-even-add-test/src/is-even.js +3 -0
  153. package/examples/compat/is-even-add-test/test/is-even.test.js +9 -0
  154. package/examples/compat/manifest.json +60 -0
  155. package/examples/compat/plan-greeting/ISSUE.md +25 -0
  156. package/examples/compat/plan-greeting/package.json +5 -0
  157. package/examples/compat/plan-greeting/src/greet.js +2 -0
  158. package/examples/compat/plan-greeting/test/greet.test.js +8 -0
  159. package/examples/compat/reverse-grep-edit/PLAN.md +32 -0
  160. package/examples/compat/reverse-grep-edit/broken.diff +12 -0
  161. package/examples/compat/reverse-grep-edit/good.diff +12 -0
  162. package/examples/compat/reverse-grep-edit/package.json +5 -0
  163. package/examples/compat/reverse-grep-edit/src/strings.js +10 -0
  164. package/examples/compat/reverse-grep-edit/test/strings.test.js +15 -0
  165. package/examples/issue-triage-js/PLAN.md +83 -0
  166. package/examples/issue-triage-js/README.md +76 -0
  167. package/examples/issue-triage-js/package.json +9 -0
  168. package/examples/issue-triage-js/src/issue-triage.js +87 -0
  169. package/examples/issue-triage-js/test/issue-triage.test.js +107 -0
  170. package/package.json +70 -0
@@ -0,0 +1,572 @@
1
+ function field(key, source, required, description) {
2
+ return { key, source, required, description };
3
+ }
4
+ function context(shapeName, fields) {
5
+ return { shapeName, fields };
6
+ }
7
+ const SHARED_PROVIDER_VARIANTS = [
8
+ {
9
+ provider: 'shared',
10
+ status: 'default',
11
+ notes: 'Default wording should stay shared across providers until fixture evidence justifies divergence.',
12
+ },
13
+ {
14
+ provider: 'openai-codex',
15
+ status: 'reserved_for_justified_divergence',
16
+ notes: 'Provider-specific overrides belong in prompt specs only when OpenAI Codex behavior demonstrably differs.',
17
+ },
18
+ {
19
+ provider: 'anthropic-claude',
20
+ status: 'reserved_for_justified_divergence',
21
+ notes: 'Provider-specific overrides belong in prompt specs only when Anthropic Claude behavior demonstrably differs.',
22
+ },
23
+ ];
24
+ const PLAN_AUTHOR_CONTEXT = context('PlanAuthorPromptContext', [
25
+ field('planDoc', 'prompt_argument', true, 'Path to the draft or candidate plan artifact being rewritten.'),
26
+ field('companionDocs', 'repository_state', true, 'Companion docs explicitly referenced by the active plan.'),
27
+ field('repositoryState', 'repository_state', true, 'Current repository symbols and file structure that the plan must target concretely.'),
28
+ field('openFindings', 'review_history', false, 'Prior plan-review findings when refining the same plan artifact.'),
29
+ field('reviewMode', 'orchestrator_state', false, 'Plan review mode for ordinary vs derived-plan response wording.'),
30
+ ]);
31
+ const PLAN_REVIEWER_CONTEXT = context('PlanReviewerPromptContext', [
32
+ field('planDoc', 'prompt_argument', true, 'Path to the plan artifact being reviewed.'),
33
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review history artifact used to inspect prior findings and responses.'),
34
+ field('round', 'orchestrator_state', true, 'Review round number for the current plan-review loop.'),
35
+ field('mode', 'orchestrator_state', true, 'Plan review mode: ordinary plan or derived-plan.'),
36
+ field('parentPlanDoc', 'prompt_argument', false, 'Path to the parent plan when reviewing a derived plan.'),
37
+ field('derivedFromScopeNumber', 'orchestrator_state', false, 'Parent scope number when reviewing a derived plan.'),
38
+ field('repositoryState', 'repository_state', true, 'Current repository context and directly referenced companion docs.'),
39
+ field('inlineContext', 'repository_state', false, "Neal-inlined plan document, parent plan, and review-history sections for reviewers without repository read access; only valid with the 'no-read' access mode."),
40
+ field('accessMode', 'orchestrator_state', false, "Three-way reviewer doctrine access mode derived from the reviewer provider's structured-advisor tool access: 'tool-access' (inspect and execute), 'read-only' (read tools only; no command execution, test runs, or scratch work), or 'no-read' (judge entirely from Neal-inlined context). When absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
41
+ ]);
42
+ const SCOPE_CODER_CONTEXT = context('ScopeCoderPromptContext', [
43
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
44
+ field('progressText', 'run_artifact', true, 'Current Neal progress markdown used to keep the scope bounded.'),
45
+ field('openFindings', 'review_history', false, 'Open reviewer findings when responding inside the same scope.'),
46
+ field('verificationHint', 'orchestrator_state', false, 'Wrapper-provided verification guidance for reviewer-response rounds.'),
47
+ field('operatorGuidance', 'operator_input', false, 'Interactive blocked-recovery guidance when the scope is waiting on operator input.'),
48
+ field('recoveryMarkdownPath', 'run_artifact', false, 'Interactive blocked-recovery history artifact path.'),
49
+ field('blockedReason', 'orchestrator_state', false, 'Current blocked reason for interactive blocked recovery.'),
50
+ field('maxTurns', 'orchestrator_state', false, 'Blocked-recovery turn cap.'),
51
+ field('turnsTaken', 'orchestrator_state', false, 'Blocked-recovery turns already used.'),
52
+ field('terminalOnly', 'orchestrator_state', false, 'Whether only terminal replacement/block actions remain allowed.'),
53
+ ]);
54
+ const SCOPE_REVIEWER_CONTEXT = context('ScopeReviewerPromptContext', [
55
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
56
+ field('baseCommit', 'orchestrator_state', true, 'Commit that defines the scope start.'),
57
+ field('headCommit', 'orchestrator_state', true, 'Commit that defines the scope head under review.'),
58
+ field('commits', 'orchestrator_state', true, 'Commits created during the current scope.'),
59
+ field('previousHeadCommit', 'orchestrator_state', false, 'Previous reviewer head commit when reviewing subsequent rounds.'),
60
+ field('diffStat', 'repository_state', true, 'Repo-derived diff summary for the scope commit range.'),
61
+ field('changedFiles', 'repository_state', true, 'Files changed in the scope commit range.'),
62
+ field('round', 'orchestrator_state', true, 'Review round number for the current scope.'),
63
+ field('parentScopeLabel', 'orchestrator_state', true, 'Active parent objective label for meaningful-progress review.'),
64
+ field('progressJustification', 'review_history', true, 'Coder-authored meaningful-progress JSON payload for the scope.'),
65
+ field('recentHistorySummary', 'review_history', true, 'Accepted-scope history for the active parent objective.'),
66
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review artifact that carries prior findings and coder responses.'),
67
+ field('scratchDir', 'run_artifact', true, 'Run-local reviewer scratch directory for temporary verification artifacts.'),
68
+ field('inlineContext', 'repository_state', false, "Neal-inlined full diff, plan document, and review-history sections for reviewers without repository read access; only valid with the 'no-read' access mode."),
69
+ field('accessMode', 'orchestrator_state', false, "Three-way reviewer doctrine access mode derived from the reviewer provider's structured-advisor tool access: 'tool-access' (inspect and execute), 'read-only' (read tools only; no command execution, test runs, or scratch work), or 'no-read' (judge entirely from Neal-inlined context). When absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
70
+ ]);
71
+ const COMPLETION_CODER_CONTEXT = context('CompletionCoderPromptContext', [
72
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan being evaluated for final completion.'),
73
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet assembled from Neal run state.'),
74
+ field('repositoryState', 'repository_state', true, 'Current repository state used to ground the completion summary.'),
75
+ ]);
76
+ const COMPLETION_REVIEWER_CONTEXT = context('CompletionReviewerPromptContext', [
77
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan being evaluated for final completion.'),
78
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet assembled from Neal run state.'),
79
+ field('summary', 'review_history', true, 'Coder-authored whole-plan completion summary under review.'),
80
+ field('scratchDir', 'run_artifact', true, 'Run-local final-completion reviewer scratch directory for temporary verification artifacts.'),
81
+ field('repositoryState', 'repository_state', true, 'Current repository state used to judge whole-plan completion.'),
82
+ field('inlineContext', 'repository_state', false, "Neal-inlined aggregate diff (or evidence-gap statement) and plan-document sections for reviewers without repository read access; only valid with the 'no-read' access mode."),
83
+ field('accessMode', 'orchestrator_state', false, "Three-way reviewer doctrine access mode derived from the reviewer provider's structured-advisor tool access: 'tool-access' (inspect and execute), 'read-only' (read tools only; no command execution, test runs, or scratch work), or 'no-read' (judge entirely from Neal-inlined context). When absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
84
+ ]);
85
+ export const PROMPT_SPECS = [
86
+ {
87
+ id: 'plan_author',
88
+ role: 'coder',
89
+ purpose: 'Author or revise Neal-executable plans without leaking planning-task scaffolding into final artifacts.',
90
+ requiredContext: PLAN_AUTHOR_CONTEXT,
91
+ schemaTarget: {
92
+ kind: 'structured_json',
93
+ schemaBuilder: 'buildCoderPlanSchema',
94
+ parser: 'validateCoderPlanPayload',
95
+ providerSurface: 'neal_json_block_protocol',
96
+ },
97
+ baseInstructions: {
98
+ kind: 'builder',
99
+ modulePath: 'src/neal/prompts/planning.ts',
100
+ exportName: 'buildPlanningPrompt',
101
+ inputShape: context('BuildPlanningPromptArgs', [field('planDoc', 'prompt_argument', true, 'Path to the draft plan artifact.')]),
102
+ },
103
+ providerVariants: SHARED_PROVIDER_VARIANTS,
104
+ evaluationNotes: [
105
+ 'Render tests should assert the canonical Neal-executable execution-shape contract stays present.',
106
+ 'Fixture cases should cover single-scope vs multi-scope decisions and cleanup of planning-only scaffolding.',
107
+ ],
108
+ firstMigrationPriority: 1,
109
+ currentHome: 'src/neal/prompts',
110
+ ownershipNotes: [
111
+ 'Prompt spec owns plan-author instructions and required context only.',
112
+ 'Plan review loop mechanics stay outside the prompt-spec library so the later adjudicator can consume them cleanly.',
113
+ ],
114
+ variants: [
115
+ {
116
+ kind: 'primary',
117
+ status: 'migration_target',
118
+ description: 'Initial plan-author prompt used by runCoderPlanRound.',
119
+ currentRoundEntrypoints: ['runCoderPlanRound'],
120
+ baseInstructions: {
121
+ kind: 'builder',
122
+ modulePath: 'src/neal/prompts/planning.ts',
123
+ exportName: 'buildPlanningPrompt',
124
+ inputShape: context('BuildPlanningPromptArgs', [field('planDoc', 'prompt_argument', true, 'Path to the draft plan artifact.')]),
125
+ },
126
+ schemaTarget: {
127
+ kind: 'structured_json',
128
+ schemaBuilder: 'buildCoderPlanSchema',
129
+ parser: 'validateCoderPlanPayload',
130
+ providerSurface: 'neal_json_block_protocol',
131
+ },
132
+ },
133
+ {
134
+ kind: 'response',
135
+ status: 'migration_target',
136
+ description: 'Plan-author response round used after plan-review findings.',
137
+ currentRoundEntrypoints: ['runCoderPlanResponseRound(reviewMode=plan)', 'runCoderPlanResponseRound(reviewMode=derived-plan)'],
138
+ baseInstructions: {
139
+ kind: 'builder',
140
+ modulePath: 'src/neal/prompts/planning.ts',
141
+ exportName: 'buildCoderPlanResponsePrompt',
142
+ inputShape: context('BuildCoderPlanResponsePromptArgs', [
143
+ field('planDoc', 'prompt_argument', true, 'Path to the plan artifact being revised.'),
144
+ field('openFindings', 'review_history', true, 'Open plan-review findings to address.'),
145
+ field('reviewMode', 'orchestrator_state', false, 'Plan review mode for ordinary vs derived-plan response wording.'),
146
+ ]),
147
+ },
148
+ schemaTarget: {
149
+ kind: 'structured_json',
150
+ schemaBuilder: 'buildCoderPlanResponseSchema',
151
+ parser: 'validateCoderPlanResponsePayload',
152
+ providerSurface: 'neal_json_block_protocol',
153
+ },
154
+ },
155
+ ],
156
+ },
157
+ {
158
+ id: 'plan_reviewer',
159
+ role: 'reviewer',
160
+ purpose: 'Review Neal-executable plans for execution-shape correctness, verification concreteness, and resume safety.',
161
+ requiredContext: PLAN_REVIEWER_CONTEXT,
162
+ schemaTarget: {
163
+ kind: 'structured_json',
164
+ schemaBuilder: 'buildPlanReviewerSchema',
165
+ parser: 'PlanReviewerPayload',
166
+ providerSurface: 'neal_json_block_protocol',
167
+ },
168
+ baseInstructions: {
169
+ kind: 'builder',
170
+ modulePath: 'src/neal/prompts/planning.ts',
171
+ exportName: 'buildPlanReviewerPrompt',
172
+ inputShape: context('BuildPlanReviewerPromptArgs', [
173
+ field('planDoc', 'prompt_argument', true, 'Path to the plan artifact under review.'),
174
+ field('round', 'orchestrator_state', true, 'Plan-review round number.'),
175
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review history artifact path.'),
176
+ field('mode', 'orchestrator_state', false, 'Plan review mode for ordinary vs derived-plan review.'),
177
+ ]),
178
+ },
179
+ providerVariants: SHARED_PROVIDER_VARIANTS,
180
+ evaluationNotes: [
181
+ 'Render tests should assert the reviewer prompt requires executionShape confirmation.',
182
+ 'Render tests should assert shared adversarial plan-readiness posture and verification skepticism without adding implementation diff-review instructions.',
183
+ 'Fixture cases should cover ordinary plans and derived plans.',
184
+ ],
185
+ firstMigrationPriority: 1,
186
+ currentHome: 'src/neal/prompts',
187
+ ownershipNotes: [
188
+ 'Prompt spec owns plan-review instructions, not the loop convergence rules.',
189
+ 'Derived-plan review is a variant of plan review rather than a separate top-level prompt-spec identity.',
190
+ ],
191
+ variants: [
192
+ {
193
+ kind: 'primary',
194
+ status: 'migration_target',
195
+ description: 'Ordinary plan-review round.',
196
+ currentRoundEntrypoints: ['runPlanReviewerRound(mode=plan)'],
197
+ baseInstructions: {
198
+ kind: 'builder',
199
+ modulePath: 'src/neal/prompts/planning.ts',
200
+ exportName: 'buildPlanReviewerPrompt',
201
+ inputShape: context('BuildPlanReviewerPromptArgs', [
202
+ field('planDoc', 'prompt_argument', true, 'Path to the plan artifact under review.'),
203
+ field('round', 'orchestrator_state', true, 'Plan-review round number.'),
204
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review history artifact path.'),
205
+ field('inlineContext', 'repository_state', false, "Optional Neal-inlined plan/review-history context; only valid with the 'no-read' access mode, whose prompt contains no repository-access instructions."),
206
+ field('accessMode', 'orchestrator_state', false, "Optional explicit doctrine access mode ('tool-access', 'read-only', or 'no-read'); when absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
207
+ ]),
208
+ },
209
+ schemaTarget: {
210
+ kind: 'structured_json',
211
+ schemaBuilder: 'buildPlanReviewerSchema',
212
+ parser: 'PlanReviewerPayload',
213
+ providerSurface: 'neal_json_block_protocol',
214
+ },
215
+ },
216
+ {
217
+ kind: 'derived_plan',
218
+ status: 'migration_target',
219
+ description: 'Derived-plan review after split-plan recovery.',
220
+ currentRoundEntrypoints: ['runPlanReviewerRound(mode=derived-plan)'],
221
+ baseInstructions: {
222
+ kind: 'builder',
223
+ modulePath: 'src/neal/prompts/planning.ts',
224
+ exportName: 'buildPlanReviewerPrompt',
225
+ inputShape: context('BuildPlanReviewerPromptDerivedArgs', [
226
+ field('planDoc', 'prompt_argument', true, 'Path to the derived plan artifact under review.'),
227
+ field('parentPlanDoc', 'prompt_argument', false, 'Path to the parent plan artifact.'),
228
+ field('derivedFromScopeNumber', 'orchestrator_state', false, 'Parent scope number that the derived plan replaces.'),
229
+ field('inlineContext', 'repository_state', false, "Optional Neal-inlined derived-plan/parent-plan/review-history context; only valid with the 'no-read' access mode, whose prompt contains no repository-access instructions."),
230
+ field('accessMode', 'orchestrator_state', false, "Optional explicit doctrine access mode ('tool-access', 'read-only', or 'no-read'); when absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
231
+ ]),
232
+ },
233
+ schemaTarget: {
234
+ kind: 'structured_json',
235
+ schemaBuilder: 'buildPlanReviewerSchema',
236
+ parser: 'PlanReviewerPayload',
237
+ providerSurface: 'neal_json_block_protocol',
238
+ },
239
+ },
240
+ ],
241
+ },
242
+ {
243
+ id: 'scope_coder',
244
+ role: 'coder',
245
+ purpose: 'Execute exactly one bounded implementation scope and respond to in-scope review feedback without starting new scopes.',
246
+ requiredContext: SCOPE_CODER_CONTEXT,
247
+ schemaTarget: {
248
+ kind: 'structured_json',
249
+ schemaBuilder: 'buildCoderScopeSchema',
250
+ parser: 'validateCoderScopePayload',
251
+ providerSurface: 'neal_json_block_protocol',
252
+ },
253
+ baseInstructions: {
254
+ kind: 'builder',
255
+ modulePath: 'src/neal/prompts/execute.ts',
256
+ exportName: 'buildScopePrompt',
257
+ inputShape: context('BuildScopePromptArgs', [
258
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
259
+ field('progressText', 'run_artifact', true, 'Current Neal progress markdown.'),
260
+ ]),
261
+ },
262
+ providerVariants: SHARED_PROVIDER_VARIANTS,
263
+ evaluationNotes: [
264
+ 'Render tests should assert structured execution envelope, progress-justification field requirements, and manual-gate instructions.',
265
+ 'Future fixture cases should cover split-plan responses, manual-gate checks, and response-round schema invariants.',
266
+ ],
267
+ firstMigrationPriority: 2,
268
+ currentHome: 'mixed',
269
+ ownershipNotes: [
270
+ 'Prompt spec owns execute-scope instructions, not state transitions, commit adoption, or blocked-recovery routing.',
271
+ 'Blocked recovery stays as a capability variant rather than a separate top-level role id in v1.',
272
+ ],
273
+ variants: [
274
+ {
275
+ kind: 'primary',
276
+ status: 'migration_target',
277
+ description: 'Initial execute-scope coder round.',
278
+ currentRoundEntrypoints: ['runCoderScopeRound'],
279
+ baseInstructions: {
280
+ kind: 'builder',
281
+ modulePath: 'src/neal/prompts/execute.ts',
282
+ exportName: 'buildScopePrompt',
283
+ inputShape: context('BuildScopePromptArgs', [
284
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
285
+ field('progressText', 'run_artifact', true, 'Current Neal progress markdown.'),
286
+ ]),
287
+ },
288
+ schemaTarget: {
289
+ kind: 'structured_json',
290
+ schemaBuilder: 'buildCoderScopeSchema',
291
+ parser: 'validateCoderScopePayload',
292
+ providerSurface: 'neal_json_block_protocol',
293
+ },
294
+ },
295
+ {
296
+ kind: 'response',
297
+ status: 'migration_target',
298
+ description: 'Reviewer-response round inside the same execute scope.',
299
+ currentRoundEntrypoints: ['runCoderResponseRound'],
300
+ baseInstructions: {
301
+ kind: 'builder',
302
+ modulePath: 'src/neal/prompts/execute.ts',
303
+ exportName: 'buildCoderResponsePrompt',
304
+ inputShape: context('BuildCoderResponsePromptArgs', [
305
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
306
+ field('progressText', 'run_artifact', true, 'Current Neal progress markdown.'),
307
+ field('verificationHint', 'orchestrator_state', true, 'Wrapper-provided verification hint.'),
308
+ field('openFindings', 'review_history', true, 'Open execute-review findings to address.'),
309
+ ]),
310
+ },
311
+ schemaTarget: {
312
+ kind: 'structured_json',
313
+ schemaBuilder: 'buildCoderResponseSchema',
314
+ parser: 'validateCoderResponsePayload',
315
+ providerSurface: 'neal_json_block_protocol',
316
+ },
317
+ },
318
+ {
319
+ kind: 'response',
320
+ status: 'adjacent',
321
+ description: 'Interactive blocked-recovery response round.',
322
+ currentRoundEntrypoints: ['runBlockedRecoveryCoderRound'],
323
+ baseInstructions: {
324
+ kind: 'builder',
325
+ modulePath: 'src/neal/agents/prompts.ts',
326
+ exportName: 'buildBlockedRecoveryCoderPrompt',
327
+ inputShape: context('BuildBlockedRecoveryCoderPromptArgs', [
328
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
329
+ field('progressText', 'run_artifact', true, 'Current Neal progress markdown.'),
330
+ field('recoveryMarkdownPath', 'run_artifact', true, 'Interactive blocked-recovery history artifact path.'),
331
+ field('blockedReason', 'orchestrator_state', true, 'Current blocked reason.'),
332
+ field('operatorGuidance', 'operator_input', true, 'Latest operator guidance.'),
333
+ ]),
334
+ },
335
+ schemaTarget: {
336
+ kind: 'structured_json',
337
+ schemaBuilder: 'buildCoderBlockedRecoveryDispositionSchema',
338
+ parser: 'validateCoderBlockedRecoveryDispositionPayload',
339
+ providerSurface: 'neal_json_block_protocol',
340
+ },
341
+ },
342
+ ],
343
+ },
344
+ {
345
+ id: 'scope_reviewer',
346
+ role: 'reviewer',
347
+ purpose: 'Review execute-scope results for correctness, verification coverage, and meaningful progress toward the active parent objective.',
348
+ requiredContext: SCOPE_REVIEWER_CONTEXT,
349
+ schemaTarget: {
350
+ kind: 'structured_json',
351
+ schemaBuilder: 'buildReviewerSchema',
352
+ parser: 'ReviewerPayload',
353
+ providerSurface: 'neal_json_block_protocol',
354
+ },
355
+ baseInstructions: {
356
+ kind: 'builder',
357
+ modulePath: 'src/neal/prompts/execute.ts',
358
+ exportName: 'buildReviewerPrompt',
359
+ inputShape: context('BuildReviewerPromptArgs', [
360
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
361
+ field('baseCommit', 'orchestrator_state', true, 'Commit range base.'),
362
+ field('headCommit', 'orchestrator_state', true, 'Commit range head.'),
363
+ field('commits', 'orchestrator_state', true, 'Commits produced in the current scope.'),
364
+ field('round', 'orchestrator_state', true, 'Review round number.'),
365
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review history artifact path.'),
366
+ field('progressJustification', 'review_history', true, 'Coder progress-justification payload.'),
367
+ field('scratchDir', 'run_artifact', true, 'Run-local scratch directory for reviewer verification artifacts.'),
368
+ ]),
369
+ },
370
+ providerVariants: SHARED_PROVIDER_VARIANTS,
371
+ evaluationNotes: [
372
+ 'Render tests should assert reviewer prompts include shared adversarial falsification, verification skepticism, concrete finding-quality doctrine, meaningful-progress instructions, and parent-objective history.',
373
+ 'Future fixture cases should cover cases where local correctness differs from parent-objective convergence.',
374
+ ],
375
+ firstMigrationPriority: 2,
376
+ currentHome: 'src/neal/prompts',
377
+ ownershipNotes: [
378
+ 'Meaningful-progress remains a capability variant of scope review in v1 rather than its own top-level prompt spec.',
379
+ 'Reviewer loop sequencing and acceptance transitions stay outside the prompt-spec library.',
380
+ ],
381
+ variants: [
382
+ {
383
+ kind: 'primary',
384
+ status: 'migration_target',
385
+ description: 'Execute-scope review round.',
386
+ currentRoundEntrypoints: ['runReviewerRound'],
387
+ baseInstructions: {
388
+ kind: 'builder',
389
+ modulePath: 'src/neal/prompts/execute.ts',
390
+ exportName: 'buildReviewerPrompt',
391
+ inputShape: context('BuildReviewerPromptArgs', [
392
+ field('planDoc', 'prompt_argument', true, 'Path to the active execute-mode plan.'),
393
+ field('baseCommit', 'orchestrator_state', true, 'Commit range base.'),
394
+ field('headCommit', 'orchestrator_state', true, 'Commit range head.'),
395
+ field('commits', 'orchestrator_state', true, 'Commits produced in the current scope.'),
396
+ field('reviewMarkdownPath', 'run_artifact', true, 'Review history artifact path.'),
397
+ field('parentScopeLabel', 'orchestrator_state', true, 'Active parent objective label.'),
398
+ field('scratchDir', 'run_artifact', true, 'Run-local scratch directory for reviewer verification artifacts.'),
399
+ field('inlineContext', 'repository_state', false, "Optional Neal-inlined diff/plan/review-history context; only valid with the 'no-read' access mode, whose prompt contains no repository-access instructions."),
400
+ field('accessMode', 'orchestrator_state', false, "Optional explicit doctrine access mode ('tool-access', 'read-only', or 'no-read'); when absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
401
+ ]),
402
+ },
403
+ schemaTarget: {
404
+ kind: 'structured_json',
405
+ schemaBuilder: 'buildReviewerSchema',
406
+ parser: 'ReviewerPayload',
407
+ providerSurface: 'neal_json_block_protocol',
408
+ },
409
+ },
410
+ {
411
+ kind: 'meaningful_progress',
412
+ status: 'migration_target',
413
+ description: 'Meaningful-progress capability layered onto execute review, including ordinary accept, top-level already-satisfied accept, block_for_operator, replace_plan, and the empty derived-scope advance_parent action.',
414
+ currentRoundEntrypoints: ['runReviewerRound'],
415
+ baseInstructions: {
416
+ kind: 'builder',
417
+ modulePath: 'src/neal/prompts/execute.ts',
418
+ exportName: 'buildReviewerPrompt',
419
+ inputShape: context('BuildReviewerPromptMeaningfulProgressArgs', [
420
+ field('progressJustification', 'review_history', true, 'Coder progress-justification payload.'),
421
+ field('recentHistorySummary', 'review_history', true, 'Accepted scope history for the active parent objective.'),
422
+ ]),
423
+ },
424
+ schemaTarget: {
425
+ kind: 'structured_json',
426
+ schemaBuilder: 'buildReviewerSchema',
427
+ parser: 'ReviewerPayload',
428
+ providerSurface: 'neal_json_block_protocol',
429
+ },
430
+ },
431
+ ],
432
+ },
433
+ {
434
+ id: 'completion_coder',
435
+ role: 'coder',
436
+ purpose: 'Summarize whole-plan completion state in compact structured JSON.',
437
+ requiredContext: COMPLETION_CODER_CONTEXT,
438
+ schemaTarget: {
439
+ kind: 'structured_json',
440
+ schemaBuilder: 'buildFinalCompletionSummarySchema',
441
+ parser: 'parseFinalCompletionSummaryPayload',
442
+ providerSurface: 'neal_json_block_protocol',
443
+ },
444
+ baseInstructions: {
445
+ kind: 'builder',
446
+ modulePath: 'src/neal/prompts/specialized.ts',
447
+ exportName: 'buildFinalCompletionSummaryPrompt',
448
+ inputShape: context('BuildFinalCompletionSummaryPromptArgs', [
449
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan.'),
450
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet.'),
451
+ ]),
452
+ },
453
+ providerVariants: SHARED_PROVIDER_VARIANTS,
454
+ evaluationNotes: [
455
+ 'Render tests should assert the prompt requires JSON-only output and completion packet context.',
456
+ ],
457
+ firstMigrationPriority: 3,
458
+ currentHome: 'src/neal/prompts',
459
+ ownershipNotes: [
460
+ 'Whole-plan completion summary is prompt-local; completion transitions remain outside the prompt-spec library.',
461
+ ],
462
+ variants: [
463
+ {
464
+ kind: 'final_completion',
465
+ status: 'migration_target',
466
+ description: 'Whole-plan completion summary round.',
467
+ currentRoundEntrypoints: ['runCoderFinalCompletionSummaryRound'],
468
+ baseInstructions: {
469
+ kind: 'builder',
470
+ modulePath: 'src/neal/prompts/specialized.ts',
471
+ exportName: 'buildFinalCompletionSummaryPrompt',
472
+ inputShape: context('BuildFinalCompletionSummaryPromptArgs', [
473
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan.'),
474
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet.'),
475
+ ]),
476
+ },
477
+ schemaTarget: {
478
+ kind: 'structured_json',
479
+ schemaBuilder: 'buildFinalCompletionSummarySchema',
480
+ parser: 'parseFinalCompletionSummaryPayload',
481
+ providerSurface: 'neal_json_block_protocol',
482
+ },
483
+ },
484
+ ],
485
+ },
486
+ {
487
+ id: 'completion_reviewer',
488
+ role: 'reviewer',
489
+ purpose: 'Judge whole-plan completion and decide whether Neal should accept completion, continue execution, or block for operator input.',
490
+ requiredContext: COMPLETION_REVIEWER_CONTEXT,
491
+ schemaTarget: {
492
+ kind: 'structured_json',
493
+ schemaBuilder: 'buildFinalCompletionReviewerSchema',
494
+ parser: 'parseFinalCompletionReviewerPayload',
495
+ providerSurface: 'neal_json_block_protocol',
496
+ },
497
+ baseInstructions: {
498
+ kind: 'builder',
499
+ modulePath: 'src/neal/prompts/specialized.ts',
500
+ exportName: 'buildFinalCompletionReviewerPrompt',
501
+ inputShape: context('BuildFinalCompletionReviewerPromptArgs', [
502
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan.'),
503
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet.'),
504
+ field('summary', 'review_history', true, 'Coder-authored completion summary.'),
505
+ field('scratchDir', 'run_artifact', true, 'Run-local scratch directory for final-completion reviewer artifacts.'),
506
+ ]),
507
+ },
508
+ providerVariants: SHARED_PROVIDER_VARIANTS,
509
+ evaluationNotes: [
510
+ 'Render tests should assert the reviewer prompt requires shared adversarial doctrine, aggregate range context, and one of the three structured completion actions.',
511
+ ],
512
+ firstMigrationPriority: 3,
513
+ currentHome: 'src/neal/prompts',
514
+ ownershipNotes: [
515
+ 'Final completion review is plan-review-adjacent in the later adjudicator design, but prompt ownership remains separate from transition semantics.',
516
+ ],
517
+ variants: [
518
+ {
519
+ kind: 'final_completion',
520
+ status: 'migration_target',
521
+ description: 'Whole-plan final completion review round.',
522
+ currentRoundEntrypoints: ['runReviewerFinalCompletionRound'],
523
+ baseInstructions: {
524
+ kind: 'builder',
525
+ modulePath: 'src/neal/prompts/specialized.ts',
526
+ exportName: 'buildFinalCompletionReviewerPrompt',
527
+ inputShape: context('BuildFinalCompletionReviewerPromptArgs', [
528
+ field('planDoc', 'prompt_argument', true, 'Path to the execute-mode plan.'),
529
+ field('packet', 'orchestrator_state', true, 'Whole-plan completion packet.'),
530
+ field('summary', 'review_history', true, 'Coder-authored completion summary.'),
531
+ field('scratchDir', 'run_artifact', true, 'Run-local scratch directory for final-completion reviewer artifacts.'),
532
+ field('inlineContext', 'repository_state', false, "Optional Neal-inlined aggregate-diff/plan context; only valid with the 'no-read' access mode, whose prompt contains no repository-access instructions."),
533
+ field('accessMode', 'orchestrator_state', false, "Optional explicit doctrine access mode ('tool-access', 'read-only', or 'no-read'); when absent the builder derives 'no-read' from inline-context presence, else 'tool-access'."),
534
+ ]),
535
+ },
536
+ schemaTarget: {
537
+ kind: 'structured_json',
538
+ schemaBuilder: 'buildFinalCompletionReviewerSchema',
539
+ parser: 'parseFinalCompletionReviewerPayload',
540
+ providerSurface: 'neal_json_block_protocol',
541
+ },
542
+ },
543
+ ],
544
+ },
545
+ ];
546
+ function getContractFieldKeys(contract) {
547
+ return new Set(contract.fields.map((field) => field.key));
548
+ }
549
+ function validateBuilderInputShape(spec, builder, label) {
550
+ const allowedKeys = getContractFieldKeys(spec.requiredContext);
551
+ const extraKeys = builder.inputShape.fields.map((field) => field.key).filter((key) => !allowedKeys.has(key));
552
+ if (extraKeys.length > 0) {
553
+ throw new Error(`Prompt spec ${spec.id} ${label} references builder context keys missing from requiredContext: ${extraKeys.join(', ')}`);
554
+ }
555
+ }
556
+ function validatePromptSpecContracts(specs) {
557
+ for (const spec of specs) {
558
+ validateBuilderInputShape(spec, spec.baseInstructions, 'baseInstructions');
559
+ for (const variant of spec.variants) {
560
+ validateBuilderInputShape(spec, variant.baseInstructions, `variant ${variant.kind}/${variant.baseInstructions.exportName}`);
561
+ }
562
+ }
563
+ }
564
+ validatePromptSpecContracts(PROMPT_SPECS);
565
+ const PROMPT_SPEC_MAP = new Map(PROMPT_SPECS.map((spec) => [spec.id, spec]));
566
+ export function getPromptSpec(id) {
567
+ const spec = PROMPT_SPEC_MAP.get(id);
568
+ if (!spec) {
569
+ throw new Error(`Unknown prompt spec: ${id}`);
570
+ }
571
+ return spec;
572
+ }