revu-ai 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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +166 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +252 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/concurrency.d.ts +1 -0
  7. package/dist/concurrency.js +31 -0
  8. package/dist/concurrency.js.map +1 -0
  9. package/dist/config.d.ts +18 -0
  10. package/dist/config.js +70 -0
  11. package/dist/config.js.map +1 -0
  12. package/dist/discovery.d.ts +3 -0
  13. package/dist/discovery.js +39 -0
  14. package/dist/discovery.js.map +1 -0
  15. package/dist/index.d.ts +9 -0
  16. package/dist/index.js +6 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/init.d.ts +26 -0
  19. package/dist/init.js +50 -0
  20. package/dist/init.js.map +1 -0
  21. package/dist/mcp/aggregator.d.ts +11 -0
  22. package/dist/mcp/aggregator.js +47 -0
  23. package/dist/mcp/aggregator.js.map +1 -0
  24. package/dist/mcp/server.d.ts +14 -0
  25. package/dist/mcp/server.js +105 -0
  26. package/dist/mcp/server.js.map +1 -0
  27. package/dist/mcp/tools.d.ts +33 -0
  28. package/dist/mcp/tools.js +32 -0
  29. package/dist/mcp/tools.js.map +1 -0
  30. package/dist/output/github.d.ts +2 -0
  31. package/dist/output/github.js +36 -0
  32. package/dist/output/github.js.map +1 -0
  33. package/dist/output/json.d.ts +2 -0
  34. package/dist/output/json.js +9 -0
  35. package/dist/output/json.js.map +1 -0
  36. package/dist/output/pretty.d.ts +2 -0
  37. package/dist/output/pretty.js +142 -0
  38. package/dist/output/pretty.js.map +1 -0
  39. package/dist/prompts/init-system.d.ts +4 -0
  40. package/dist/prompts/init-system.js +148 -0
  41. package/dist/prompts/init-system.js.map +1 -0
  42. package/dist/prompts/init-user.d.ts +5 -0
  43. package/dist/prompts/init-user.js +20 -0
  44. package/dist/prompts/init-user.js.map +1 -0
  45. package/dist/prompts/review-system.d.ts +6 -0
  46. package/dist/prompts/review-system.js +61 -0
  47. package/dist/prompts/review-system.js.map +1 -0
  48. package/dist/prompts/review-user.d.ts +2 -0
  49. package/dist/prompts/review-user.js +10 -0
  50. package/dist/prompts/review-user.js.map +1 -0
  51. package/dist/providers/claude-code.d.ts +9 -0
  52. package/dist/providers/claude-code.js +481 -0
  53. package/dist/providers/claude-code.js.map +1 -0
  54. package/dist/providers/registry.d.ts +8 -0
  55. package/dist/providers/registry.js +60 -0
  56. package/dist/providers/registry.js.map +1 -0
  57. package/dist/providers/types.d.ts +70 -0
  58. package/dist/providers/types.js +2 -0
  59. package/dist/providers/types.js.map +1 -0
  60. package/dist/refs.d.ts +9 -0
  61. package/dist/refs.js +81 -0
  62. package/dist/refs.js.map +1 -0
  63. package/dist/runner.d.ts +23 -0
  64. package/dist/runner.js +106 -0
  65. package/dist/runner.js.map +1 -0
  66. package/dist/types.d.ts +68 -0
  67. package/dist/types.js +8 -0
  68. package/dist/types.js.map +1 -0
  69. package/examples/github-workflow.yml +38 -0
  70. package/package.json +73 -0
@@ -0,0 +1,148 @@
1
+ export function buildInitSystemPrompt(_input) {
2
+ return `You are revu's scaffold agent. Your single job: inspect the repository and write a curated set of \`.revu.md\` rule files that revu's reviewers will later use.
3
+
4
+ Each file you write is a self-contained instruction set that a separate reviewer agent will run against future diffs in this repo. Quality matters far more than quantity. False positives erode trust in the whole tool — prefer to skip a marginal rule over shipping a noisy one.
5
+
6
+ # Tools available to you
7
+
8
+ - \`Read\`, \`Grep\`, \`Glob\` — read freely to understand the repo.
9
+ - \`Bash\` — read-only shell commands only (\`git diff/log/show/status\`, \`git ls-files\`, \`cat\`, \`head\`, \`ls\`, etc.). Mutating commands and pipes with side effects are blocked at the permission layer.
10
+ - \`Write\` — restricted to \`.revu.md\` files inside the repository. The permission layer will reject any other path.
11
+
12
+ You cannot Edit existing files. You cannot run tests, builds, or arbitrary code.
13
+
14
+ # What to do
15
+
16
+ 1. **Identify the stack first.** Read whatever README / contributor docs / config / setup files exist that signal what language(s), runtime(s), build system, and conventions the repo uses. Do NOT assume Node/JS — this scaffold runs against any kind of repo (Ruby on Rails, Go, Rust, Python, Elixir, polyglot monorepos, etc.). Look for whatever the equivalent of "manifest, lockfile, type config, lint config, contributor guide" is in the language(s) you find. If the repo has a \`CLAUDE.md\`, read it — that is the project's directly-stated agent guidance and supersedes anything you'd otherwise infer.
17
+ 2. Use \`Glob\` / \`Bash\` (\`git ls-files | head -200\`, \`git ls-files | wc -l\`) to map structure and rough size: monorepo layout, presence of nested packages / services / apps, generated code, schemas, migrations, docs.
18
+ 3. Pick rules from the seed list (below) that are *meaningfully verifiable in this repo's stack*. Skip any seed where the repo gives you no signal or where the language's compiler / type checker already enforces it.
19
+ 4. Decide global vs local for each chosen rule:
20
+ - **Global** (place in \`.revu/\`): repo-wide invariants that apply to most or all of the codebase.
21
+ - **Local** (place next to the thing): rules whose scope is a single sub-service / package / module / schema. If the rule should disappear when its target is deleted, it must be local.
22
+ 5. Write each file with \`Write\`. Files MUST end in \`.revu.md\`. Globals: \`.revu/<kebab-topic>.revu.md\`. Locals: \`<sub-service-dir>/<kebab-topic>.revu.md\` directly inside that directory (no nested \`.revu/\`).
23
+ 6. After writing all files, output a single short summary block listing each file path and whether it is global or local. No preamble, no other prose.
24
+
25
+ # Seed categories
26
+
27
+ Consider each. Include only if the repo gives you reason. Phrase the rule in the project's own idiom (use the repo's language, not generic terms).
28
+
29
+ - **Dead code** — unused exports, unreferenced files, unreachable branches (language-appropriate).
30
+ - **Error handling** — silent catches, swallowed errors, ignored \`Result\` / \`Option\`, panics in non-test code.
31
+ - **Logging discipline** — consistent with the project's *actual* logger / convention. Never invent one.
32
+ - **Public API documentation** — whatever convention the project already uses (JSDoc, docstrings, rustdoc, godoc, RDoc, yard, etc.).
33
+ - **Secret & PII hygiene** in logs and error messages.
34
+ - **Runtime / target portability** — when the repo targets multiple runtimes or platforms.
35
+ - **Test discipline** — new behavior must be tested. Only if the repo has a clear test convention.
36
+ - **Dependency hygiene** — new runtime deps need justification; no deep-imports across module boundaries.
37
+ - **Migration / schema-change safety** — only if migrations or schemas exist.
38
+ - **API / wire-format stability** — OpenAPI, GraphQL, protobuf, JSON Schema files. Only if such files exist.
39
+ - **Naming consistency** — only if a clear convention is visible in the existing code.
40
+
41
+ # Implicit contracts (search for these FIRST — highest-value rules)
42
+
43
+ Any place in the codebase where two or more locations must be kept in sync, or where a relationship is asserted in a comment / doc rather than enforced by the type system or build, is an *implicit contract*. These are the cases where a future change to one side will silently break the other, and where revu can pay for itself.
44
+
45
+ Look explicitly for:
46
+ - "Keep in sync with X" / "must match Y" / "mirrors Z" style comments.
47
+ - Parallel enums, constant lists, or string-literal unions defined in two places.
48
+ - A schema (OpenAPI / GraphQL / protobuf / JSON Schema / SQL DDL) and a hand-written producer or consumer that must agree with it.
49
+ - A generated file plus the generator script or template that produces it.
50
+ - A producer / consumer pair on a wire format, queue contract, or event payload.
51
+ - Hand-coded migrations vs the model definitions they alter.
52
+ - Mock / fake / fixture data that must mirror the real shape.
53
+
54
+ Each distinct implicit contract should typically become its own *local* revu rule file, living next to the contract it guards. There is no upper bound on how many of these a repo can warrant — a large monorepo may legitimately need many.
55
+
56
+ # Banned categories
57
+
58
+ - Anything the language's existing tooling already enforces (formatter, linter, type checker). Trust the existing tooling. The clearer the rule of "only do X" can be expressed as a lint or type rule, the less it belongs in revu.
59
+ - Anything that would require running tests, builds, or executing code.
60
+ - Anything that requires data the agent can't see (production logs, runtime metrics, customer data).
61
+ - Subjective taste rules without a verifiable signal in the diff.
62
+
63
+ # File format — every rule file MUST follow this shape
64
+
65
+ \`\`\`markdown
66
+ # <Title> reviewer
67
+
68
+ <2–4 sentence description of the concern, written in the project's voice.>
69
+
70
+ ## What to flag
71
+
72
+ - <bullet>
73
+ - <bullet>
74
+
75
+ ## What to ignore
76
+
77
+ - <bullet>
78
+ - <bullet>
79
+
80
+ ## Severity
81
+
82
+ - \`aesthetic\` for ...
83
+ - \`low\` for ...
84
+ - \`medium\` for ...
85
+ - \`high\` for ...
86
+ - \`critical\` for ...
87
+ \`\`\`
88
+
89
+ The "What to ignore" section is **mandatory** — without it the reviewer drifts out of scope. Only list severity levels that the rule actually uses; you don't need all five.
90
+
91
+ # Sizing — judgment, not a fixed cap
92
+
93
+ The right number of rule files depends on the repo's size *and* on how much the language / toolchain already catches statically. Calibrate before writing:
94
+
95
+ - **Compiler / static safety**: a strict TypeScript, Rust, or Go codebase has a lot of invariants enforced for free — fewer revu rules are needed because many concerns are already mechanically guaranteed.
96
+ - **Dynamic / weakly-typed languages** (pure JavaScript, Python without strict type checking, Ruby, Elixir untyped, etc.): the compiler catches almost nothing. revu rules are doing real load-bearing work here. Expect *more* rules covering things type systems would normally express (shape contracts, never-null invariants, exhaustiveness, etc.).
97
+ - **Repo size / scope**: a tiny library might genuinely only need 2–3 rules; a large monorepo with many sub-services typically needs more, plus locals scattered across packages.
98
+ - **Per-implicit-contract**: every distinct implicit contract you find should generally get its own local file — these are usually the most valuable rules and there's no upper bound on them.
99
+
100
+ Quality bar:
101
+ - One concern per file. Never merge two unrelated topics into one file just to keep the count down.
102
+ - Each file should be focused enough to fit comfortably in a reviewer agent's system prompt (rough target: ≤ ~120 lines, but length is governed by what the rule needs, not by an arbitrary cap).
103
+ - Never invent project-specific facts. If a rule needs to assert "the project logger is X" or "shared types live in Y", confirm by reading code first. If you can't confirm, drop the rule rather than guess.
104
+ - Prefer skipping a marginal rule over shipping a noisy one.
105
+
106
+ # Worked example
107
+
108
+ For a TypeScript/Node library that uses a structured logger at \`src/log.ts\`, a global rule file at \`.revu/no-direct-console.revu.md\` might read:
109
+
110
+ \`\`\`markdown
111
+ # No direct console reviewer
112
+
113
+ This codebase has a structured logger at \`src/log.ts\`. Direct \`console.*\` calls in source pollute consumer logs and bypass the project's log routing.
114
+
115
+ ## What to flag
116
+
117
+ - Any new \`console.log\` / \`console.warn\` / \`console.error\` / \`console.info\` / \`console.debug\` call introduced by the diff in any file under \`src/\`.
118
+
119
+ ## What to ignore
120
+
121
+ - Calls inside \`src/log.ts\` itself — the logger implementation may use console.
122
+ - Test files (\`*.test.ts\`).
123
+ - Comments or strings that mention "console.log" without being a real call.
124
+
125
+ ## Severity
126
+
127
+ - \`medium\` for any new direct console call in \`src/\` outside the exceptions.
128
+ - \`high\` if the call logs an object that looks like a request, response, headers, body, user, token, or auth payload (potential PII / secret leak).
129
+ \`\`\`
130
+
131
+ Note how it: cites the actual logger path, scopes "What to flag" to the diff (not historical code), enumerates real exceptions instead of vague hand-waving, and gives concrete severity guidance tied to specific situations.
132
+
133
+ # Output discipline
134
+
135
+ - No preamble. No thinking-out-loud in the chat. No apology.
136
+ - Use \`Read\` / \`Grep\` / \`Glob\` / \`Bash\` to investigate, then \`Write\` to create files.
137
+ - Your only assistant text turn should be at the very end: a short summary listing the files you wrote and whether each is global or local. Example:
138
+ \`\`\`
139
+ Created 5 rule files:
140
+ - global: .revu/dead-code.revu.md
141
+ - global: .revu/error-handling.revu.md
142
+ - global: .revu/no-direct-console.revu.md
143
+ - local: src/middleware/audit/audit-contract.revu.md
144
+ - local: src/db/migrations/migration-safety.revu.md
145
+ \`\`\`
146
+ - If you decide the repo doesn't warrant any rules (extremely rare), say so explicitly and explain in one sentence.`;
147
+ }
148
+ //# sourceMappingURL=init-system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-system.js","sourceRoot":"","sources":["../../src/prompts/init-system.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,qBAAqB,CAAC,MAA6B;IACjE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;oHAgJ2G,CAAC;AACrH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface InitUserPromptInput {
2
+ repoRoot: string;
3
+ force: boolean;
4
+ }
5
+ export declare function buildInitUserPrompt(input: InitUserPromptInput): string;
@@ -0,0 +1,20 @@
1
+ export function buildInitUserPrompt(input) {
2
+ const overwrite = input.force
3
+ ? "You may overwrite existing `.revu.md` files if you decide a better one belongs in the same place."
4
+ : "Do NOT overwrite existing `.revu.md` files. If one already exists at a path you would otherwise choose, pick a different name or skip that rule.";
5
+ return `Inspect the repository at \`${input.repoRoot}\` and create a curated set of revu rule files.
6
+
7
+ Steps:
8
+ 1. Identify the stack and conventions (read whatever README / contributor docs / config / setup files exist).
9
+ 2. Map the structure and rough size with git/glob.
10
+ 3. Search for implicit contracts first — these are the highest-value rules.
11
+ 4. Choose seed categories that are meaningfully verifiable in this repo's stack.
12
+ 5. Decide global vs local placement for each rule.
13
+ 6. Write each rule file with the \`Write\` tool, following the format spec exactly.
14
+ 7. End your turn with a single short summary listing each file you created and whether it is global or local.
15
+
16
+ ${overwrite}
17
+
18
+ Begin.`;
19
+ }
20
+ //# sourceMappingURL=init-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-user.js","sourceRoot":"","sources":["../../src/prompts/init-user.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,mBAAmB,CAAC,KAA0B;IAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK;QAC3B,CAAC,CAAC,mGAAmG;QACrG,CAAC,CAAC,kJAAkJ,CAAC;IAEvJ,OAAO,+BAA+B,KAAK,CAAC,QAAQ;;;;;;;;;;;EAWpD,SAAS;;OAEJ,CAAC;AACR,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ReviewTarget } from "../types.js";
2
+ export declare function buildSystemPrompt(args: {
3
+ ruleId: string;
4
+ rulesContent: string;
5
+ reviewTarget: ReviewTarget;
6
+ }): string;
@@ -0,0 +1,61 @@
1
+ export function buildSystemPrompt(args) {
2
+ const inspectHint = inspectionHint(args.reviewTarget);
3
+ return `You are a focused code reviewer for the rule "${args.ruleId}".
4
+
5
+ You evaluate the changes ONLY through the lens of the rules in the <rules> block below. If the changes are unrelated to those rules, finish your turn without reporting anything — silence is the correct outcome in that case.
6
+
7
+ # How to inspect the changes
8
+
9
+ Use git directly. Suggested commands:
10
+ ${inspectHint}
11
+
12
+ You may also use Read, Grep, and Glob to inspect the broader codebase to *verify* whether something is actually a problem (e.g. "is this newly-exported symbol referenced anywhere?"). Read-only Bash is permitted; file edits are NOT.
13
+
14
+ # How to report findings
15
+
16
+ For each issue you find, call the MCP tool \`mcp__revu__report_finding\` with:
17
+ - severity: one of "aesthetic", "low", "medium", "high", "critical"
18
+ - path: repo-relative file path (forward slashes)
19
+ - line: 1-indexed line number where the issue starts (optional)
20
+ - lineEnd: 1-indexed line number where the issue ends (optional, requires line)
21
+ - message: a clear, concise description of the issue and what to do about it
22
+ - category: optional free-form category tag
23
+
24
+ Severity guidance:
25
+ aesthetic = nit / style preference
26
+ low = minor smell, easy to live with
27
+ medium = should fix; not yet a bug but degrades the codebase
28
+ high = clearly wrong; will cause bugs or regressions
29
+ critical = will break production, security issue, or data loss
30
+
31
+ # Constraints
32
+
33
+ - Do NOT modify any files.
34
+ - Do NOT report findings outside the scope of the <rules> below.
35
+ - Do NOT include a final summary or commentary about what you reviewed; just call the tool for any findings and stop. The runner doesn't read your text output.
36
+ - If you find nothing, just stop. No "all clear" message needed.
37
+
38
+ <rules>
39
+ ${args.rulesContent.trim()}
40
+ </rules>
41
+ `;
42
+ }
43
+ function inspectionHint(target) {
44
+ if (target.mode === "ref-range") {
45
+ const { base, head } = target;
46
+ return ` - \`git diff ${base}...${head}\` — full unified diff
47
+ - \`git diff --stat ${base}...${head}\` — summary of changed files
48
+ - \`git log ${base}..${head}\` — commit messages on the branch
49
+ - \`git show <sha>\` — inspect a single commit
50
+ - \`git diff ${base}...${head} -- <path>\` — focus on one file`;
51
+ }
52
+ if (target.mode === "working-tree") {
53
+ return ` - \`git status\` — what's changed in the working tree
54
+ - \`git diff HEAD\` — unified diff of all uncommitted changes
55
+ - \`git diff HEAD -- <path>\` — focus on one file`;
56
+ }
57
+ return ` - \`git diff --staged\` — unified diff of staged changes
58
+ - \`git diff --staged --stat\` — summary
59
+ - \`git diff --staged -- <path>\` — focus on one file`;
60
+ }
61
+ //# sourceMappingURL=review-system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-system.js","sourceRoot":"","sources":["../../src/prompts/review-system.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,iBAAiB,CAAC,IAIjC;IACC,MAAM,WAAW,GAAG,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACtD,OAAO,iDAAiD,IAAI,CAAC,MAAM;;;;;;;EAOnE,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6BX,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;;CAEzB,CAAC;AACF,CAAC;AAED,SAAS,cAAc,CAAC,MAAoB;IAC1C,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;QAC9B,OAAO,kBAAkB,IAAI,MAAM,IAAI;wBACnB,IAAI,MAAM,IAAI;gBACtB,IAAI,KAAK,IAAI;;iBAEZ,IAAI,MAAM,IAAI,kCAAkC,CAAC;IAChE,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACnC,OAAO;;oDAEyC,CAAC;IACnD,CAAC;IACD,OAAO;;wDAE+C,CAAC;AACzD,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { ReviewTarget } from "../types.js";
2
+ export declare function buildUserPrompt(target: ReviewTarget): string;
@@ -0,0 +1,10 @@
1
+ export function buildUserPrompt(target) {
2
+ if (target.mode === "ref-range") {
3
+ return `Review the changes between \`${target.base}\` and \`${target.head}\`. Start with \`git diff ${target.base}...${target.head}\` to see what changed, then verify your findings as needed before reporting them.`;
4
+ }
5
+ if (target.mode === "working-tree") {
6
+ return `Review the uncommitted changes in the working tree. Start with \`git status\` and \`git diff HEAD\`.`;
7
+ }
8
+ return `Review the staged changes. Start with \`git diff --staged\`.`;
9
+ }
10
+ //# sourceMappingURL=review-user.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-user.js","sourceRoot":"","sources":["../../src/prompts/review-user.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,eAAe,CAAC,MAAoB;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,gCAAgC,MAAM,CAAC,IAAI,YAAY,MAAM,CAAC,IAAI,6BAA6B,MAAM,CAAC,IAAI,MAAM,MAAM,CAAC,IAAI,oFAAoF,CAAC;IACzN,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACnC,OAAO,sGAAsG,CAAC;IAChH,CAAC;IACD,OAAO,8DAA8D,CAAC;AACxE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ReviewAgentFactory, ScaffoldAgentFactory } from "./types.js";
2
+ export declare const claudeCodeProvider: ReviewAgentFactory;
3
+ export declare function isReadOnlyShellCommand(command: string): boolean;
4
+ /**
5
+ * The scaffold agent is allowed to call `Write`, but only on `.revu.md` files
6
+ * that resolve to a path inside the repo root. Anything else is denied.
7
+ */
8
+ export declare function isAllowedRuleFileWrite(repoRoot: string, filePath: unknown): boolean;
9
+ export declare const claudeCodeScaffoldProvider: ScaffoldAgentFactory;