@agentskit/code-review 0.1.0 → 0.4.2

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 (76) hide show
  1. package/.doc-bridge/capabilities.json +34 -0
  2. package/.doc-bridge/index.json +94 -0
  3. package/.pre-commit-hooks.yaml +9 -0
  4. package/AGENTS.md +20 -0
  5. package/CHANGELOG.md +91 -0
  6. package/CONTRIBUTING.md +45 -0
  7. package/README.md +238 -33
  8. package/ROADMAP.md +20 -0
  9. package/SECURITY.md +16 -0
  10. package/action.yml +120 -0
  11. package/dist/agents/code-review/agent.js +454 -76
  12. package/dist/agents/code-review/agent.js.map +1 -1
  13. package/dist/agents/code-review/lenses.js +17 -1
  14. package/dist/agents/code-review/lenses.js.map +1 -1
  15. package/dist/agents/code-review/reporters.js +83 -7
  16. package/dist/agents/code-review/reporters.js.map +1 -1
  17. package/dist/agents/code-review/sources.js +324 -73
  18. package/dist/agents/code-review/sources.js.map +1 -1
  19. package/dist/src/acp-cli-adapter.js +127 -0
  20. package/dist/src/acp-cli-adapter.js.map +1 -0
  21. package/dist/src/batch-coverage.js +111 -0
  22. package/dist/src/batch-coverage.js.map +1 -0
  23. package/dist/src/claude-code-adapter.js +44 -60
  24. package/dist/src/claude-code-adapter.js.map +1 -1
  25. package/dist/src/cli.js +347 -50
  26. package/dist/src/cli.js.map +1 -1
  27. package/dist/src/codex-adapter.js +114 -69
  28. package/dist/src/codex-adapter.js.map +1 -1
  29. package/dist/src/github-review-state.js +134 -0
  30. package/dist/src/github-review-state.js.map +1 -0
  31. package/dist/src/grok-cli-adapter.js +27 -0
  32. package/dist/src/grok-cli-adapter.js.map +1 -0
  33. package/dist/src/headless-cli-adapter.js +78 -0
  34. package/dist/src/headless-cli-adapter.js.map +1 -0
  35. package/dist/src/local-cli-process.js +328 -0
  36. package/dist/src/local-cli-process.js.map +1 -0
  37. package/dist/src/local-cli-timeout.js +14 -0
  38. package/dist/src/local-cli-timeout.js.map +1 -0
  39. package/dist/src/ollama-adapter.js +155 -0
  40. package/dist/src/ollama-adapter.js.map +1 -0
  41. package/dist/src/opencode-cli-adapter.js +57 -0
  42. package/dist/src/opencode-cli-adapter.js.map +1 -0
  43. package/dist/src/provider-circuit-breaker.js +52 -0
  44. package/dist/src/provider-circuit-breaker.js.map +1 -0
  45. package/dist/src/provider-registry.js +168 -0
  46. package/dist/src/provider-registry.js.map +1 -0
  47. package/dist/src/review-config.js +145 -0
  48. package/dist/src/review-config.js.map +1 -0
  49. package/doc-bridge.config.json +116 -0
  50. package/docs/OPERATIONS.md +358 -0
  51. package/docs/assets/agentskit-mark.svg +10 -0
  52. package/docs/assets/code-review-terminal.png +0 -0
  53. package/docs/continuous-improvement.md +35 -0
  54. package/docs/for-agents/code-review-cli.md +70 -0
  55. package/docs/for-agents/index.md +5 -0
  56. package/docs/plans/ecosystem-doc-quality-code-review.md +61 -0
  57. package/docs/provider-compatibility.json +35 -0
  58. package/ecosystem-claims.json +187 -0
  59. package/ecosystem.json +277 -0
  60. package/examples/pull-request.yml +29 -0
  61. package/llms-full.txt +1055 -0
  62. package/llms.txt +24 -0
  63. package/package.json +53 -7
  64. package/scripts/generate-llms-full.mjs +68 -0
  65. package/scripts/run-cycle-benchmark.mjs +64 -0
  66. package/test/cli-smoke.test.mjs +522 -0
  67. package/test/continuous-improvement.test.mjs +20 -0
  68. package/test/documentation.test.mjs +238 -0
  69. package/test/release-workflow.test.mjs +31 -0
  70. package/dist/agents/code-review/agent.d.ts +0 -115
  71. package/dist/agents/code-review/lenses.d.ts +0 -10
  72. package/dist/agents/code-review/reporters.d.ts +0 -31
  73. package/dist/agents/code-review/sources.d.ts +0 -27
  74. package/dist/src/claude-code-adapter.d.ts +0 -4
  75. package/dist/src/cli.d.ts +0 -2
  76. package/dist/src/codex-adapter.d.ts +0 -4
@@ -0,0 +1,238 @@
1
+ import assert from 'node:assert/strict'
2
+ import { existsSync, readFileSync } from 'node:fs'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { dirname, join, resolve } from 'node:path'
5
+ import test from 'node:test'
6
+
7
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
8
+ const read = path => readFileSync(join(root, path), 'utf8')
9
+
10
+ test('README communicates pipeline, maturity, contribution, and ecosystem role', () => {
11
+ const readme = read('README.md')
12
+ for (const marker of ['docs/assets/agentskit-mark.svg', '```mermaid', '## Maturity', '## AgentsKit ecosystem', 'CONTRIBUTING.md', 'SECURITY.md']) {
13
+ assert.ok(readme.includes(marker), `README missing ${marker}`)
14
+ }
15
+ for (const url of ['www.agentskit.io/docs', 'registry.agentskit.io/docs', 'chat.agentskit.io/docs', 'playbook.agentskit.io/docs', 'agentskit-io.github.io/doc-bridge', 'akos.agentskit.io/docs']) {
16
+ assert.ok(readme.includes(url), `README missing ${url}`)
17
+ }
18
+ assert.match(readme, /no Fumadocs application and no embedded AgentsChat/i)
19
+ })
20
+
21
+ test('operations guide covers every required security and release topic', () => {
22
+ const operations = read('docs/OPERATIONS.md')
23
+ for (const marker of ['## Provider and credential choices', '## pre-commit integration', '## Local Ollama review', '## GitHub Action permissions', '## Advisory and blocking behavior', '## Cost and latency controls', '## SARIF', '## Failure scenarios', '## Releases and maturity', '## Contribution and security', 'pull_request_target', 'security-events: write']) {
24
+ assert.ok(operations.includes(marker), `operations guide missing ${marker}`)
25
+ }
26
+ })
27
+
28
+ test('Changesets release automation is tokenless, gated, and recoverable', () => {
29
+ const manifest = JSON.parse(read('package.json'))
30
+ const changesets = JSON.parse(read('.changeset/config.json'))
31
+ const versionWorkflow = read('.github/workflows/release.yml')
32
+ const publishWorkflow = read('.github/workflows/publish.yml')
33
+ const operations = read('docs/OPERATIONS.md')
34
+
35
+ assert.equal(manifest.devDependencies['@changesets/cli'], '^2.31.0')
36
+ assert.equal(manifest.devDependencies['@changesets/changelog-github'], '^0.7.0')
37
+ assert.equal(manifest.scripts.changeset, 'changeset')
38
+ assert.equal(manifest.scripts['version-packages'], 'changeset version')
39
+ assert.equal(changesets.baseBranch, 'main')
40
+ assert.deepEqual(changesets.changelog, ['@changesets/changelog-github', { repo: 'AgentsKit-io/code-review' }])
41
+ assert.match(versionWorkflow, /changesets\/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d/)
42
+ assert.match(versionWorkflow, /pull-requests: write/)
43
+ assert.doesNotMatch(versionWorkflow, /id-token: write/)
44
+ const publishJob = publishWorkflow.match(/\n publish:\n([\s\S]*?)(?=\n [A-Za-z0-9_-]+:|\n\S|$)/)?.[1] ?? ''
45
+ assert.match(publishJob, /id-token: write/)
46
+ assert.match(publishWorkflow, /github\.event\.pull_request\.title == 'chore: version packages'/)
47
+ assert.match(publishWorkflow, /github\.event\.pull_request\.head\.ref == 'changeset-release\/main'/)
48
+ assert.match(publishWorkflow, /github\.event\.pull_request\.head\.ref == 'codex-release-0\.4\.1'|github\.event\.pull_request\.head\.ref == 'codex\/release-0\.4\.1'/)
49
+ assert.doesNotMatch(publishWorkflow, /workflow_dispatch|RECOVERY_VERSION/)
50
+ assert.match(publishWorkflow, /github\.event\.pull_request\.merge_commit_sha \|\| github\.sha/)
51
+ assert.match(publishWorkflow, /gh release view/)
52
+ assert.match(publishWorkflow, /npm publish --access public/)
53
+ assert.match(publishWorkflow, /steps\.npm-version\.outputs\.already_published != 'true'/)
54
+ assert.match(publishWorkflow, /E404\|404 Not Found/)
55
+ assert.doesNotMatch(`${versionWorkflow}\n${publishWorkflow}`, /NPM_TOKEN|secrets\.[A-Z_]*NPM/)
56
+ assert.match(operations, /Changesets is the release source of truth/)
57
+ assert.match(operations, /No long-lived `NPM_TOKEN`/)
58
+ })
59
+
60
+ test('pre-commit hook is manual, provider-neutral, and reviews the repository diff', () => {
61
+ const hook = read('.pre-commit-hooks.yaml')
62
+ const readme = read('README.md')
63
+ for (const marker of [
64
+ 'id: agentskit-review',
65
+ 'entry: agentskit-review',
66
+ 'language: node',
67
+ 'pass_filenames: false',
68
+ 'always_run: true',
69
+ 'require_serial: true',
70
+ 'stages: [manual]',
71
+ ]) {
72
+ assert.ok(hook.includes(marker), `pre-commit hook missing ${marker}`)
73
+ }
74
+ assert.match(readme, /pre-commit run --hook-stage manual agentskit-review/)
75
+ assert.match(readme, /does not claim to review only staged files/)
76
+ assert.match(readme, /args: \[--provider, codex-cli, --no-fail/)
77
+ assert.doesNotMatch(hook, /api[_-]?key/i)
78
+ })
79
+
80
+ test('reviewdog interoperability stays converter-free and explicit about policy ownership', () => {
81
+ const readme = read('README.md')
82
+ const operations = read('docs/OPERATIONS.md')
83
+ const reviewdogSection = operations.split('### Route findings through reviewdog')[1].split('## Failure scenarios')[0]
84
+ for (const marker of ['reviewdog -f=sarif', '-filter-mode=added', '-fail-level=error', 'REPORT_FILE="$(mktemp)"']) {
85
+ assert.ok(readme.includes(marker), `README reviewdog recipe missing ${marker}`)
86
+ assert.ok(operations.includes(marker), `operations reviewdog recipe missing ${marker}`)
87
+ }
88
+ assert.match(operations, /no AgentsKit-specific reporter or converter is required/i)
89
+ assert.match(operations, /REVIEWDOG_GITHUB_API_TOKEN/)
90
+ assert.match(operations, /blocker and high findings to SARIF `error`/)
91
+ assert.match(operations, /actions\/checkout@[0-9a-f]{40}/)
92
+ assert.match(operations, /reviewdog\/action-setup@[0-9a-f]{40}/)
93
+ assert.match(operations, /reviewdog_version: v0\.21\.0/)
94
+ assert.match(operations, /fetch-depth: 0/)
95
+ assert.match(operations, /BASE_REF: \$\{\{ github\.base_ref \}\}/)
96
+ assert.match(operations, /LLM_API_KEY: \$\{\{ secrets\.LLM_API_KEY \}\}/)
97
+ assert.match(operations, /--provider openai --model gpt-4o/)
98
+ assert.match(operations, /--no-fail &&/)
99
+ assert.match(operations, /trap 'rm -f/)
100
+ assert.match(reviewdogSection, /github:AgentsKit-io\/code-review#[0-9a-f]{40}/)
101
+ assert.doesNotMatch(reviewdogSection, /--base origin\/main/)
102
+ assert.doesNotMatch(reviewdogSection, /--provider codex-cli/)
103
+ })
104
+
105
+ test('Ollama recipe is local, bounded, advisory, and honest about its source boundary', () => {
106
+ const readme = read('README.md')
107
+ const operations = read('docs/OPERATIONS.md')
108
+ const readmeRecipe = readme.split('### Review locally with Ollama')[1]?.split('\n## ')[0] ?? ''
109
+ const operationsRecipe = operations.split('## Local Ollama review')[1]?.split('\n## ')[0] ?? ''
110
+ for (const marker of [
111
+ '--provider ollama',
112
+ '--model qwen2.5-coder:7b',
113
+ '--base-url http://localhost:11434',
114
+ '--max-files 10',
115
+ '--concurrency 1',
116
+ '--no-fail',
117
+ ]) {
118
+ assert.ok(readme.includes(marker), `README Ollama recipe missing ${marker}`)
119
+ assert.ok(operations.includes(marker), `operations Ollama recipe missing ${marker}`)
120
+ }
121
+ assert.match(readme, /not a staged-files-only hook/i)
122
+ assert.match(readme, /model must support Ollama tool calling/i)
123
+ assert.match(operations, /tool calling is required/i)
124
+ assert.match(operations, /does not mean “only staged files,”/i)
125
+ assert.match(operations, /stdin is treated as one source file/i)
126
+ assert.match(operations, /Do not set a hosted gateway.*describe the run as local/i)
127
+ assert.doesNotMatch(`${readmeRecipe}\n${operationsRecipe}`, /OLLAMA_API_KEY|--api-key\s+\S+/)
128
+ })
129
+
130
+ test('the Action stays least-privilege, secret-safe, and advisory by default', () => {
131
+ const action = read('action.yml')
132
+ const workflow = read('examples/pull-request.yml')
133
+ const selfHostedWorkflow = read('examples/pull-request-selfhosted.yml')
134
+ assert.match(action, /LLM_API_KEY: \$\{\{ inputs\.api-key \}\}/)
135
+ assert.match(action, /INPUT_MODE: \$\{\{ inputs\.mode \}\}/)
136
+ assert.match(action, /--mode "\$INPUT_MODE"/)
137
+ assert.match(action, /INPUT_FAIL_ON_BLOCK/)
138
+ assert.match(action, /default: '17'/)
139
+ assert.match(action, /INPUT_MAX_CALLS/)
140
+ assert.match(action, /INPUT_MAX_FINDINGS_PER_FILE/)
141
+ assert.match(action, /codex-cli requires a pre-authenticated trusted-local runner/)
142
+ assert.match(action, /--no-fail/)
143
+ assert.match(workflow, /contents: read/)
144
+ assert.match(workflow, /pull-requests: write/)
145
+ assert.match(selfHostedWorkflow, /mode: 'trusted-local'/)
146
+ assert.doesNotMatch(workflow, /pull_request_target/)
147
+ })
148
+
149
+ test('machine-readable documentation and Doc Bridge ownership are committed', () => {
150
+ for (const path of ['AGENTS.md', 'doc-bridge.config.json', 'ecosystem.json', 'llms.txt', 'llms-full.txt', '.doc-bridge/index.json', '.doc-bridge/capabilities.json', 'docs/for-agents/index.md', 'docs/for-agents/code-review-cli.md']) {
151
+ assert.ok(existsSync(join(root, path)), `${path} is missing`)
152
+ }
153
+ const config = JSON.parse(read('doc-bridge.config.json'))
154
+ assert.equal(config.routing.options.ownership['code-review-cli'].agentDoc, 'docs/for-agents/code-review-cli.md')
155
+ const index = JSON.parse(read('.doc-bridge/index.json'))
156
+ const handoff = index.handoffs['code-review-cli']
157
+ for (const path of handoff.readBeforeEditing) assert.ok(existsSync(join(root, path)), `handoff target ${path} is missing`)
158
+ const searchableBody = index.knowledge.map(entry => entry.body).join('\n')
159
+ for (const [product, url] of [
160
+ ['AgentsKit', 'https://www.agentskit.io/docs'],
161
+ ['Registry', 'https://registry.agentskit.io/docs'],
162
+ ['AgentsKit Chat', 'https://chat.agentskit.io/docs'],
163
+ ['Playbook', 'https://playbook.agentskit.io/docs'],
164
+ ['Doc Bridge', 'https://agentskit-io.github.io/doc-bridge/'],
165
+ ['AKOS', 'https://akos.agentskit.io/docs'],
166
+ ]) {
167
+ assert.ok(searchableBody.includes(product), `Doc Bridge index lost ecosystem product ${product}`)
168
+ assert.ok(searchableBody.includes(url), `Doc Bridge index lost ecosystem route ${url}`)
169
+ }
170
+ assert.match(read('llms.txt'), /AgentsKit Code Review/)
171
+ assert.match(read('llms.txt'), /llms-full\.txt/)
172
+ const full = read('llms-full.txt')
173
+ assert.match(full, /!\[[^\]]+\]\(https:\/\/raw\.githubusercontent\.com\/AgentsKit-io\/code-review\/main\/docs\/assets\/code-review-terminal\.png\)/)
174
+ assert.doesNotMatch(full, /!\[[^\]]*\]\(https:\/\/github\.com\/AgentsKit-io\/code-review\/blob\/main\//)
175
+ for (const marker of ['Code Review operations guide', '## Security policy', '## Contributing guide', '## Roadmap', '## Changelog']) {
176
+ assert.ok(full.includes(marker), `llms-full.txt missing ${marker}`)
177
+ }
178
+ const relativeLinks = [...full.matchAll(/\]\(([^)]+)\)/g)]
179
+ .map(match => match[1])
180
+ .filter(target => !/^(?:https?:\/\/|mailto:|#)/.test(target))
181
+ assert.deepEqual(relativeLinks, [], `llms-full.txt contains unresolved relative links: ${relativeLinks.join(', ')}`)
182
+ })
183
+
184
+ test('canonical ecosystem manifest exposes seven unique products and six Code Review siblings', () => {
185
+ const manifest = JSON.parse(read('ecosystem.json'))
186
+ const expected = ['agentskit', 'registry', 'agentskit-chat', 'playbook', 'doc-bridge', 'code-review', 'akos']
187
+ assert.deepEqual(manifest.products.map(product => product.id), expected)
188
+ assert.equal(new Set(expected).size, 7)
189
+ assert.deepEqual(manifest.products.find(product => product.id === 'code-review').navigation.next, expected.filter(id => id !== 'code-review'))
190
+ assert.ok(manifest.properties.every(product => expected.includes(product.id)))
191
+ assert.equal(manifest.products.find(product => product.id === 'agentskit-chat').surfaces.documentation, 'fumadocs')
192
+ assert.equal(manifest.products.find(product => product.id === 'akos').maturity, 'stable')
193
+ for (const product of manifest.products) {
194
+ assert.match(product.surfaces.home, /^https:\/\//)
195
+ assert.match(product.surfaces.llms, /^https:\/\//)
196
+ }
197
+ })
198
+
199
+ test('published package keeps documentation generators and freshness enforcement', () => {
200
+ const manifest = JSON.parse(read('package.json'))
201
+ assert.ok(manifest.files.includes('scripts/generate-llms-full.mjs'))
202
+ for (const input of [
203
+ 'SECURITY.md',
204
+ 'CONTRIBUTING.md',
205
+ 'ROADMAP.md',
206
+ 'CHANGELOG.md',
207
+ 'ecosystem-claims.json',
208
+ 'docs/assets',
209
+ 'docs/plans',
210
+ 'test/cli-smoke.test.mjs',
211
+ 'test/documentation.test.mjs',
212
+ '.doc-bridge/index.json',
213
+ '.doc-bridge/capabilities.json',
214
+ 'action.yml',
215
+ '.pre-commit-hooks.yaml',
216
+ 'examples/pull-request.yml',
217
+ ]) {
218
+ assert.ok(manifest.files.includes(input), `published documentation input missing: ${input}`)
219
+ }
220
+ assert.equal(manifest.optionalDependencies['@agentskit/doc-bridge'], '^1.1.1')
221
+ assert.match(manifest.scripts.prepack, /docs:gate/)
222
+ })
223
+
224
+ test('machine discovery links raw sources and every sibling while staying concise', () => {
225
+ const llms = read('llms.txt')
226
+ assert.ok(Buffer.byteLength(llms) < 12_000, 'llms.txt should remain a concise discovery surface')
227
+ for (const marker of ['raw.githubusercontent.com/AgentsKit-io/code-review/main/', 'AgentsKit Chat', 'Registry', 'Playbook', 'Doc Bridge', 'AKOS']) {
228
+ assert.ok(llms.includes(marker), `llms.txt missing ${marker}`)
229
+ }
230
+ })
231
+
232
+ test('repository-native scope has no Fumadocs or AgentsChat runtime dependency', () => {
233
+ const packageJson = read('package.json')
234
+ assert.doesNotMatch(packageJson, /fumadocs/i)
235
+ assert.doesNotMatch(packageJson, /agentskit-chat/i)
236
+ assert.equal(existsSync(join(root, 'app')), false)
237
+ assert.equal(existsSync(join(root, 'apps')), false)
238
+ })
@@ -0,0 +1,31 @@
1
+ import assert from 'node:assert/strict'
2
+ import { readFileSync } from 'node:fs'
3
+ import { fileURLToPath } from 'node:url'
4
+ import { dirname, join, resolve } from 'node:path'
5
+ import test from 'node:test'
6
+
7
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..')
8
+ const read = path => readFileSync(join(root, path), 'utf8')
9
+
10
+ test('release workflows allow only a trusted merged Changesets version PR to publish', () => {
11
+ const version = read('.github/workflows/release.yml')
12
+ const publish = read('.github/workflows/publish.yml')
13
+
14
+ assert.match(version, /push:\n branches: \[main\]/)
15
+ assert.match(version, /changesets\/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d/)
16
+ assert.match(version, /pull-requests: write/)
17
+ assert.doesNotMatch(version, /id-token: write/)
18
+ assert.match(publish, /pull_request:\n branches: \[main\]\n types: \[closed\]/)
19
+ assert.match(publish, /github\.event\.pull_request\.merged == true/)
20
+ assert.match(publish, /github\.event\.pull_request\.title == 'chore: version packages'/)
21
+ assert.match(publish, /github\.event\.pull_request\.head\.ref == 'changeset-release\/main'/)
22
+ assert.match(publish, /github\.event\.pull_request\.head\.ref == 'codex-release-0\.4\.1'|github\.event\.pull_request\.head\.ref == 'codex\/release-0\.4\.1'/)
23
+ assert.doesNotMatch(publish, /version packages'\)/)
24
+ assert.match(publish, /id-token: write/)
25
+ assert.match(publish, /npm run check/)
26
+ assert.match(publish, /npm pack --dry-run/)
27
+ assert.match(publish, /npm publish --access public/)
28
+ assert.match(publish, /gh release create/)
29
+ assert.doesNotMatch(publish, /workflow_dispatch|NPM_TOKEN|RECOVERY_VERSION/)
30
+ assert.doesNotMatch(publish, /node -p \\\"/)
31
+ })
@@ -1,115 +0,0 @@
1
- import type { AdapterFactory, ChatMemory, Observer, SkillDefinition, ToolCall } from '@agentskit/core';
2
- import { type SourceConfig } from './sources.js';
3
- /**
4
- * code-review — a deep, low-noise code-review agent. It fans out 7 focused lenses over
5
- * each file (correctness · security · performance · maintainability · design · tests ·
6
- * conventions), then ADVERSARIALLY verifies every finding (N skeptics try to refute it;
7
- * majority-refute kills it) before applying severity/confidence thresholds. Findings are
8
- * typed and carry an applicable patch. Inputs: local git diff, a GitHub PR, whole files,
9
- * or a pasted snippet. Outputs: a Markdown report, SARIF, or GitHub PR comments.
10
- *
11
- * ```ts
12
- * import { anthropic } from '@agentskit/adapters'
13
- * const agent = createCodeReviewAgent({
14
- * adapter: anthropic({ apiKey: process.env.ANTHROPIC_API_KEY!, model: 'claude-opus-4-8' }),
15
- * source: { kind: 'git-diff', base: 'origin/main', cwd: process.cwd() },
16
- * conventions: { path: 'CONTRIBUTING.md' },
17
- * })
18
- * const review = await agent.run()
19
- * if (review.blocking) process.exit(1) // CI gate
20
- * ```
21
- */
22
- export type Severity = 'blocker' | 'high' | 'med' | 'nit';
23
- export type Category = 'correctness' | 'security' | 'performance' | 'maintainability' | 'design' | 'tests' | 'conventions';
24
- export interface ReviewTarget {
25
- file: string;
26
- language: string;
27
- fullContent: string;
28
- /** 1-based changed line ranges (diff sources only); absent = whole-file review. */
29
- changedRanges?: Array<{
30
- start: number;
31
- end: number;
32
- }>;
33
- isChanged: boolean;
34
- /** Head commit SHA, for github-pr (needed to anchor inline comments). */
35
- commitId?: string;
36
- }
37
- export interface Finding {
38
- file: string;
39
- line: number;
40
- endLine?: number;
41
- severity: Severity;
42
- category: Category;
43
- confidence: number;
44
- title: string;
45
- rationale: string;
46
- suggestion: string;
47
- suggestedPatch?: string;
48
- /** Set by orchestration: does this finding land on a changed line (postable inline)? */
49
- inDiff?: boolean;
50
- /** Set by the optional validate step: did the patch apply (and build)? */
51
- patchValidated?: boolean;
52
- }
53
- export type Verdict = 'APPROVE' | 'COMMENT' | 'REQUEST CHANGES';
54
- export interface ReviewResult {
55
- verdict: Verdict;
56
- /** True when a finding at/above `blockingSeverity` survived — wire to your CI exit code. */
57
- blocking: boolean;
58
- findings: Finding[];
59
- dropped: Finding[];
60
- droppedNote?: string;
61
- summary: string;
62
- }
63
- export interface Reporter {
64
- name: string;
65
- emit(review: ReviewResult): Promise<void>;
66
- }
67
- export interface Lens {
68
- key: Category;
69
- skill: SkillDefinition;
70
- /** Cap this lens's findings at a max severity (e.g. conventions → 'nit'). */
71
- severityCeiling?: Severity;
72
- }
73
- export interface CodeReviewConfig {
74
- adapter: AdapterFactory;
75
- source: SourceConfig;
76
- /** Defaults to the 7 built-in lenses. Pass a subset to disable, or add custom lenses. */
77
- lenses?: Lens[];
78
- /** Project conventions injected into every lens — a string, or a file to read. */
79
- conventions?: string | {
80
- path: string;
81
- };
82
- thresholds?: {
83
- minSeverity?: Severity;
84
- minConfidence?: number;
85
- maxPerFile?: number;
86
- suppressNits?: boolean;
87
- };
88
- /** Independent adversarial verify votes; a finding dies on a MAJORITY of "refuted". Default 3. */
89
- auditVotes?: number;
90
- /** Merge findings from different lenses that describe the same issue. Default true. */
91
- consolidate?: boolean;
92
- /** Validate suggested patches by `git apply --check` (git-diff/paths sources) before reporting. */
93
- validatePatch?: boolean;
94
- budget?: {
95
- maxFiles?: number;
96
- concurrency?: number;
97
- };
98
- /** Default = [markdownReporter()]. */
99
- reporters?: Reporter[];
100
- /** CI gate floor: a surviving finding at/above this severity sets `blocking`. Default 'blocker'. */
101
- blockingSeverity?: Severity;
102
- memory?: ChatMemory;
103
- observers?: Observer[];
104
- onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>;
105
- maxSteps?: number;
106
- }
107
- export declare function createCodeReviewAgent(config: CodeReviewConfig): {
108
- name: string;
109
- run: () => Promise<ReviewResult>;
110
- /** AgentHandle: treats the task string as a snippet to review, returns the summary. */
111
- asHandle(): {
112
- name: string;
113
- run: (task: string) => Promise<string>;
114
- };
115
- };
@@ -1,10 +0,0 @@
1
- import type { SkillDefinition } from '@agentskit/core';
2
- export declare const correctnessLens: SkillDefinition;
3
- export declare const securityLens: SkillDefinition;
4
- export declare const performanceLens: SkillDefinition;
5
- export declare const maintainabilityLens: SkillDefinition;
6
- export declare const designLens: SkillDefinition;
7
- export declare const testsLens: SkillDefinition;
8
- export declare const conventionsLens: SkillDefinition;
9
- export declare const consolidator: SkillDefinition;
10
- export declare const skeptic: SkillDefinition;
@@ -1,31 +0,0 @@
1
- import type { Reporter, ReviewResult } from './agent.js';
2
- /** Human-readable Markdown — to a sink (default stdout) and optionally a file. */
3
- export declare function markdownReporter(opts?: {
4
- write?: (s: string) => void;
5
- file?: string;
6
- }): Reporter;
7
- export declare function renderMarkdown(review: ReviewResult): string;
8
- /** Machine output: SARIF 2.1.0 for GitHub code-scanning / dashboards. */
9
- export declare function sarifReporter(opts?: {
10
- file?: string;
11
- write?: (s: string) => void;
12
- }): Reporter;
13
- /** One summary comment on the PR thread (uses the issues endpoint — always available). */
14
- export declare function githubSummaryReporter(c: {
15
- owner: string;
16
- repo: string;
17
- number: number;
18
- token: string;
19
- }): Reporter;
20
- /**
21
- * A batched PR review: inline comments on findings that land inside the diff, plus an
22
- * overall verdict + summary body. Findings outside the diff are folded into the body
23
- * (GitHub rejects review comments on unchanged lines).
24
- */
25
- export declare function githubInlineReporter(c: {
26
- owner: string;
27
- repo: string;
28
- number: number;
29
- token: string;
30
- commitId?: string;
31
- }): Reporter;
@@ -1,27 +0,0 @@
1
- import type { ReviewTarget } from './agent.js';
2
- /**
3
- * Source adapters normalize every input shape into the same `ReviewTarget[]` the
4
- * pipeline reviews. This is deterministic orchestration code (git / fs / fetch) — the
5
- * model only ever sees the normalized targets, never the raw ingestion.
6
- */
7
- export type SourceConfig = {
8
- kind: 'git-diff';
9
- base: string;
10
- head?: string;
11
- cwd?: string;
12
- } | {
13
- kind: 'github-pr';
14
- owner: string;
15
- repo: string;
16
- number: number;
17
- token: string;
18
- } | {
19
- kind: 'paths';
20
- paths: string[];
21
- cwd?: string;
22
- } | {
23
- kind: 'stdin';
24
- content: string;
25
- filename?: string;
26
- };
27
- export declare function loadTargets(source: SourceConfig): Promise<ReviewTarget[]>;
@@ -1,4 +0,0 @@
1
- import type { AdapterFactory } from "@agentskit/core";
2
- export declare function claudeCode(opts?: {
3
- model?: string;
4
- }): AdapterFactory;
package/dist/src/cli.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,4 +0,0 @@
1
- import type { AdapterFactory } from "@agentskit/core";
2
- export declare function codexCli(opts?: {
3
- model?: string;
4
- }): AdapterFactory;