@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,9 @@
1
+ {
2
+ "name": "@navels/neal-example-issue-triage-js",
3
+ "private": true,
4
+ "type": "module",
5
+ "packageManager": "pnpm@11.5.0",
6
+ "scripts": {
7
+ "test": "node --test"
8
+ }
9
+ }
@@ -0,0 +1,87 @@
1
+ const ISSUE_LINE_PATTERN = /^- \[(P\d+)\] ([^:]+): (.+)$/;
2
+
3
+ function incrementCounter(counter, key) {
4
+ counter[key] = (counter[key] ?? 0) + 1;
5
+ }
6
+
7
+ function formatCounts(title, counts) {
8
+ const lines = [`## ${title}`];
9
+
10
+ for (const [key, count] of Object.entries(counts)) {
11
+ lines.push(`- ${key}: ${count}`);
12
+ }
13
+
14
+ return lines.join('\n');
15
+ }
16
+
17
+ export function parseIssueLine(line) {
18
+ const match = line.match(ISSUE_LINE_PATTERN);
19
+
20
+ if (match === null) {
21
+ throw new Error(`Invalid issue line: ${line}`);
22
+ }
23
+
24
+ const [, priority, area, details] = match;
25
+ const tokens = details.split(' ');
26
+ const ownerToken = tokens.find((token) => token.startsWith('@'));
27
+ const tags = tokens
28
+ .filter((token) => token.startsWith('#'))
29
+ .map((token) => token.slice(1));
30
+ const title = tokens
31
+ .filter((token) => !token.startsWith('@') && !token.startsWith('#'))
32
+ .join(' ');
33
+
34
+ return {
35
+ priority,
36
+ area,
37
+ title,
38
+ owner: ownerToken?.slice(1) ?? null,
39
+ tags,
40
+ };
41
+ }
42
+
43
+ export function parseIssues(markdown) {
44
+ return markdown
45
+ .split(/\r?\n/u)
46
+ .map((line) => line.trimEnd())
47
+ .filter((line) => line.length > 0 && !line.startsWith('//'))
48
+ .map((line) => parseIssueLine(line));
49
+ }
50
+
51
+ export function summarizeIssues(issues) {
52
+ const summary = {
53
+ total: issues.length,
54
+ byPriority: {},
55
+ byArea: {},
56
+ byOwner: {},
57
+ byTag: {},
58
+ };
59
+
60
+ for (const issue of issues) {
61
+ incrementCounter(summary.byPriority, issue.priority);
62
+ incrementCounter(summary.byArea, issue.area);
63
+ incrementCounter(summary.byOwner, issue.owner);
64
+
65
+ for (const tag of issue.tags) {
66
+ incrementCounter(summary.byTag, tag);
67
+ }
68
+ }
69
+
70
+ return summary;
71
+ }
72
+
73
+ export function formatSummary(summary) {
74
+ return [
75
+ '# Issue Summary',
76
+ '',
77
+ `Total: ${summary.total}`,
78
+ '',
79
+ formatCounts('Priorities', summary.byPriority),
80
+ '',
81
+ formatCounts('Areas', summary.byArea),
82
+ '',
83
+ formatCounts('Owners', summary.byOwner),
84
+ '',
85
+ formatCounts('Tags', summary.byTag),
86
+ ].join('\n');
87
+ }
@@ -0,0 +1,107 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+
4
+ import {
5
+ formatSummary,
6
+ parseIssueLine,
7
+ parseIssues,
8
+ summarizeIssues,
9
+ } from '../src/issue-triage.js';
10
+
11
+ describe('issue triage example', () => {
12
+ it('parses a basic issue line', () => {
13
+ assert.deepEqual(
14
+ parseIssueLine('- [P1] auth: Login fails @web #bug #customer'),
15
+ {
16
+ priority: 'P1',
17
+ area: 'auth',
18
+ title: 'Login fails',
19
+ owner: 'web',
20
+ tags: ['bug', 'customer'],
21
+ },
22
+ );
23
+ });
24
+
25
+ it('parses multiple issue lines while ignoring blanks and comments', () => {
26
+ assert.deepEqual(
27
+ parseIssues(`
28
+ - [P1] auth: Login fails @web #bug #customer
29
+
30
+ // keep this scenario in the sample input but out of the parsed issues
31
+ - [P2] billing: Invoice total is wrong @api #bug
32
+ `),
33
+ [
34
+ {
35
+ priority: 'P1',
36
+ area: 'auth',
37
+ title: 'Login fails',
38
+ owner: 'web',
39
+ tags: ['bug', 'customer'],
40
+ },
41
+ {
42
+ priority: 'P2',
43
+ area: 'billing',
44
+ title: 'Invoice total is wrong',
45
+ owner: 'api',
46
+ tags: ['bug'],
47
+ },
48
+ ],
49
+ );
50
+ });
51
+
52
+ it('summarizes counts by priority, area, owner, and tag', () => {
53
+ const summary = summarizeIssues([
54
+ parseIssueLine('- [P1] auth: Login fails @web #bug #customer'),
55
+ parseIssueLine('- [P1] auth: Session expires early @web #bug'),
56
+ parseIssueLine('- [P2] billing: Invoice total is wrong @api #bug'),
57
+ ]);
58
+
59
+ assert.deepEqual(summary, {
60
+ total: 3,
61
+ byPriority: {
62
+ P1: 2,
63
+ P2: 1,
64
+ },
65
+ byArea: {
66
+ auth: 2,
67
+ billing: 1,
68
+ },
69
+ byOwner: {
70
+ web: 2,
71
+ api: 1,
72
+ },
73
+ byTag: {
74
+ bug: 3,
75
+ customer: 1,
76
+ },
77
+ });
78
+ });
79
+
80
+ it('formats a minimal markdown summary', () => {
81
+ const summary = summarizeIssues([
82
+ parseIssueLine('- [P1] auth: Login fails @web #bug #customer'),
83
+ ]);
84
+
85
+ assert.equal(
86
+ formatSummary(summary),
87
+ [
88
+ '# Issue Summary',
89
+ '',
90
+ 'Total: 1',
91
+ '',
92
+ '## Priorities',
93
+ '- P1: 1',
94
+ '',
95
+ '## Areas',
96
+ '- auth: 1',
97
+ '',
98
+ '## Owners',
99
+ '- web: 1',
100
+ '',
101
+ '## Tags',
102
+ '- bug: 1',
103
+ '- customer: 1',
104
+ ].join('\n'),
105
+ );
106
+ });
107
+ });
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "@navels/neal",
3
+ "version": "0.1.0",
4
+ "description": "A source-first multi-agent CLI for planning, executing, reviewing, and resuming scoped code changes.",
5
+ "license": "MIT",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "author": "Lee Nave",
10
+ "type": "module",
11
+ "packageManager": "pnpm@11.12.0",
12
+ "homepage": "https://github.com/navels/neal#readme",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/navels/neal.git"
16
+ },
17
+ "bugs": {
18
+ "url": "https://github.com/navels/neal/issues"
19
+ },
20
+ "keywords": [
21
+ "agent",
22
+ "cli",
23
+ "codex",
24
+ "claude",
25
+ "code-review",
26
+ "multi-agent",
27
+ "planning",
28
+ "refactoring"
29
+ ],
30
+ "bin": {
31
+ "neal": "dist/neal/index.js"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "README.md",
36
+ "SECURITY.md",
37
+ "LICENSE",
38
+ "config.yml",
39
+ "docs",
40
+ "examples"
41
+ ],
42
+ "engines": {
43
+ "node": ">=22.13",
44
+ "pnpm": ">=11"
45
+ },
46
+ "scripts": {
47
+ "build": "rm -rf dist && tsc -p tsconfig.json && chmod +x dist/neal/index.js",
48
+ "pack:local": "pnpm build && pnpm pack",
49
+ "verify:package": "pnpm build && node scripts/verify-package.mjs",
50
+ "validate:release": "node scripts/validate-release.mjs",
51
+ "dev:link": "pnpm build && npm link",
52
+ "start": "tsx src/neal/index.ts",
53
+ "test": "NEAL_NOTIFY_BIN= node --import tsx --test test/*.test.ts",
54
+ "typecheck": "tsc --noEmit -p tsconfig.json && tsc -p tsconfig.test.json"
55
+ },
56
+ "dependencies": {
57
+ "@ai-sdk/openai-compatible": "2.0.49",
58
+ "@anthropic-ai/claude-agent-sdk": "0.3.163",
59
+ "@openai/codex-sdk": "0.137.0",
60
+ "ai": "6.0.202",
61
+ "dotenv": "^17.4.2",
62
+ "yaml": "^2.8.3",
63
+ "zod": "4.4.3"
64
+ },
65
+ "devDependencies": {
66
+ "@types/node": "^22.19.19",
67
+ "tsx": "^4.21.0",
68
+ "typescript": "^6.0.3"
69
+ }
70
+ }