@amrishkhan05/frankly 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.
- package/.claude-plugin/marketplace.json +27 -0
- package/.claude-plugin/plugin.json +11 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
- package/.github/ISSUE_TEMPLATE/documentation.md +15 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +20 -0
- package/.github/copilot-instructions.md +12 -0
- package/.github/plugin/marketplace.json +20 -0
- package/.github/plugin/plugin.json +16 -0
- package/.mcp.json +10 -0
- package/LICENSE +21 -0
- package/README.md +394 -0
- package/commands/frankly-help.toml +2 -0
- package/commands/frankly-plan.toml +2 -0
- package/commands/frankly-review.toml +2 -0
- package/commands/frankly-verify.toml +2 -0
- package/commands/frankly.toml +2 -0
- package/dist/analysis/change-classifier.d.ts +65 -0
- package/dist/analysis/change-classifier.d.ts.map +1 -0
- package/dist/analysis/change-classifier.js +241 -0
- package/dist/analysis/change-classifier.js.map +1 -0
- package/dist/analysis/repository-intelligence.d.ts +15 -0
- package/dist/analysis/repository-intelligence.d.ts.map +1 -0
- package/dist/analysis/repository-intelligence.js +179 -0
- package/dist/analysis/repository-intelligence.js.map +1 -0
- package/dist/core/config.d.ts +393 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +130 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/engine.d.ts +20 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +117 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/errors.d.ts +27 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +48 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +8 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +8 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/models.d.ts +155 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +6 -0
- package/dist/core/models.js.map +1 -0
- package/dist/git/index.d.ts +7 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/index.js +6 -0
- package/dist/git/index.js.map +1 -0
- package/dist/git/repository.d.ts +44 -0
- package/dist/git/repository.d.ts.map +1 -0
- package/dist/git/repository.js +198 -0
- package/dist/git/repository.js.map +1 -0
- package/dist/graph/symbols.d.ts +45 -0
- package/dist/graph/symbols.d.ts.map +1 -0
- package/dist/graph/symbols.js +204 -0
- package/dist/graph/symbols.js.map +1 -0
- package/dist/integrations/claude/checkpoint.d.ts +2 -0
- package/dist/integrations/claude/checkpoint.d.ts.map +1 -0
- package/dist/integrations/claude/checkpoint.js +33 -0
- package/dist/integrations/claude/checkpoint.js.map +1 -0
- package/dist/integrations/cli/demo.d.ts +3 -0
- package/dist/integrations/cli/demo.d.ts.map +1 -0
- package/dist/integrations/cli/demo.js +31 -0
- package/dist/integrations/cli/demo.js.map +1 -0
- package/dist/integrations/cli/index.d.ts +7 -0
- package/dist/integrations/cli/index.d.ts.map +1 -0
- package/dist/integrations/cli/index.js +181 -0
- package/dist/integrations/cli/index.js.map +1 -0
- package/dist/integrations/mcp/index.d.ts +3 -0
- package/dist/integrations/mcp/index.d.ts.map +1 -0
- package/dist/integrations/mcp/index.js +7 -0
- package/dist/integrations/mcp/index.js.map +1 -0
- package/dist/integrations/mcp/server.d.ts +14 -0
- package/dist/integrations/mcp/server.d.ts.map +1 -0
- package/dist/integrations/mcp/server.js +232 -0
- package/dist/integrations/mcp/server.js.map +1 -0
- package/dist/project/detector.d.ts +70 -0
- package/dist/project/detector.d.ts.map +1 -0
- package/dist/project/detector.js +214 -0
- package/dist/project/detector.js.map +1 -0
- package/dist/report/json.d.ts +26 -0
- package/dist/report/json.d.ts.map +1 -0
- package/dist/report/json.js +148 -0
- package/dist/report/json.js.map +1 -0
- package/dist/review/red-ink-review.d.ts +26 -0
- package/dist/review/red-ink-review.d.ts.map +1 -0
- package/dist/review/red-ink-review.js +103 -0
- package/dist/review/red-ink-review.js.map +1 -0
- package/fixtures/retry-429/README.md +8 -0
- package/fixtures/retry-429/baseline/package.json +4 -0
- package/fixtures/retry-429/baseline/src/client.test.ts +8 -0
- package/fixtures/retry-429/baseline/src/client.ts +3 -0
- package/fixtures/retry-429/baseline/src/retry-policy.ts +1 -0
- package/fixtures/retry-429/baseline/tsconfig.json +7 -0
- package/fixtures/retry-429/candidate/src/client.ts +5 -0
- package/fixtures/retry-429/candidate/src/retry-strategy.ts +9 -0
- package/fixtures/retry-429/candidate/src/unrelated-format.ts +1 -0
- package/hooks/copilot-activate.js +9 -0
- package/hooks/copilot-hooks.json +13 -0
- package/hooks/hooks.json +13 -0
- package/package.json +70 -0
- package/scripts/run.cjs +32 -0
- package/skills/frankly/SKILL.md +12 -0
- package/src/analysis/change-classifier.ts +285 -0
- package/src/analysis/repository-intelligence.ts +236 -0
- package/src/core/config.ts +149 -0
- package/src/core/engine.ts +143 -0
- package/src/core/errors.ts +56 -0
- package/src/core/index.ts +8 -0
- package/src/core/models.ts +280 -0
- package/src/git/index.ts +7 -0
- package/src/git/repository.ts +207 -0
- package/src/graph/symbols.ts +254 -0
- package/src/integrations/claude/checkpoint.ts +40 -0
- package/src/integrations/cli/demo.ts +34 -0
- package/src/integrations/cli/index.ts +211 -0
- package/src/integrations/mcp/index.ts +7 -0
- package/src/integrations/mcp/server.ts +257 -0
- package/src/project/detector.ts +242 -0
- package/src/report/json.ts +175 -0
- package/src/review/red-ink-review.ts +125 -0
- package/src/tests/phase1.test.ts +57 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project detection and analysis
|
|
3
|
+
* Identifies TypeScript/JavaScript projects, workspaces, and configuration
|
|
4
|
+
*/
|
|
5
|
+
import * as fs from "fs";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { ProjectError } from "../core/errors.js";
|
|
8
|
+
export class ProjectDetector {
|
|
9
|
+
constructor(rootPath) {
|
|
10
|
+
this.cache = new Map();
|
|
11
|
+
this.rootPath = rootPath;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Detect project configuration
|
|
15
|
+
*/
|
|
16
|
+
async detectProject() {
|
|
17
|
+
const cacheKey = "project";
|
|
18
|
+
if (this.cache.has(cacheKey)) {
|
|
19
|
+
return this.cache.get(cacheKey);
|
|
20
|
+
}
|
|
21
|
+
const packageJson = this.readPackageJson(this.rootPath);
|
|
22
|
+
if (!packageJson) {
|
|
23
|
+
throw new ProjectError("No package.json found", { path: this.rootPath });
|
|
24
|
+
}
|
|
25
|
+
const project = {
|
|
26
|
+
root: this.rootPath,
|
|
27
|
+
type: this.detectLanguageType(),
|
|
28
|
+
packageManager: this.detectPackageManager(),
|
|
29
|
+
isWorkspace: this.isWorkspace(packageJson),
|
|
30
|
+
hasTsConfig: this.hasTsConfig(this.rootPath),
|
|
31
|
+
testRunner: this.detectTestRunner(packageJson),
|
|
32
|
+
};
|
|
33
|
+
if (project.isWorkspace) {
|
|
34
|
+
project.workspaceRoot = this.rootPath;
|
|
35
|
+
project.packages = this.detectWorkspacePackages(packageJson);
|
|
36
|
+
}
|
|
37
|
+
this.cache.set(cacheKey, project);
|
|
38
|
+
return project;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Detect language type from tsconfig or file extensions
|
|
42
|
+
*/
|
|
43
|
+
detectLanguageType() {
|
|
44
|
+
if (this.hasTsConfig(this.rootPath)) {
|
|
45
|
+
return "typescript";
|
|
46
|
+
}
|
|
47
|
+
// Check for .ts files
|
|
48
|
+
return this.hasTypeScriptFiles(this.rootPath) ? "typescript" : "javascript";
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if tsconfig.json exists
|
|
52
|
+
*/
|
|
53
|
+
hasTsConfig(dir) {
|
|
54
|
+
return fs.existsSync(path.join(dir, "tsconfig.json"));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check for TypeScript files
|
|
58
|
+
*/
|
|
59
|
+
hasTypeScriptFiles(dir, depth = 2) {
|
|
60
|
+
if (depth <= 0)
|
|
61
|
+
return false;
|
|
62
|
+
try {
|
|
63
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules")
|
|
66
|
+
continue;
|
|
67
|
+
if (entry.isFile() && entry.name.endsWith(".ts"))
|
|
68
|
+
return true;
|
|
69
|
+
if (entry.isDirectory() && this.hasTypeScriptFiles(path.join(dir, entry.name), depth - 1)) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Ignore errors
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Detect package manager from lock files
|
|
81
|
+
*/
|
|
82
|
+
detectPackageManager() {
|
|
83
|
+
if (fs.existsSync(path.join(this.rootPath, "pnpm-lock.yaml")))
|
|
84
|
+
return "pnpm";
|
|
85
|
+
if (fs.existsSync(path.join(this.rootPath, "yarn.lock")))
|
|
86
|
+
return "yarn";
|
|
87
|
+
return "npm";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if project is a workspace
|
|
91
|
+
*/
|
|
92
|
+
isWorkspace(packageJson) {
|
|
93
|
+
return (Array.isArray(packageJson.workspaces) || typeof packageJson.workspaces === "object");
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Detect workspace packages
|
|
97
|
+
*/
|
|
98
|
+
detectWorkspacePackages(packageJson) {
|
|
99
|
+
const workspaces = packageJson.workspaces;
|
|
100
|
+
if (!workspaces)
|
|
101
|
+
return [];
|
|
102
|
+
let patterns = [];
|
|
103
|
+
if (Array.isArray(workspaces)) {
|
|
104
|
+
patterns = workspaces;
|
|
105
|
+
}
|
|
106
|
+
else if (typeof workspaces === "object" && workspaces !== null) {
|
|
107
|
+
const w = workspaces;
|
|
108
|
+
if (Array.isArray(w.packages)) {
|
|
109
|
+
patterns = w.packages;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Resolve glob patterns to actual packages
|
|
113
|
+
const packages = [];
|
|
114
|
+
for (const pattern of patterns) {
|
|
115
|
+
const resolved = this.resolveGlobPattern(pattern);
|
|
116
|
+
packages.push(...resolved);
|
|
117
|
+
}
|
|
118
|
+
return packages;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Resolve glob pattern to actual directories
|
|
122
|
+
*/
|
|
123
|
+
resolveGlobPattern(pattern) {
|
|
124
|
+
const result = [];
|
|
125
|
+
if (!pattern.includes("*")) {
|
|
126
|
+
const fullPath = path.join(this.rootPath, pattern);
|
|
127
|
+
if (fs.existsSync(fullPath)) {
|
|
128
|
+
result.push(pattern);
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
}
|
|
132
|
+
// Simple glob resolution
|
|
133
|
+
const parts = pattern.split("/");
|
|
134
|
+
const basePart = parts[0];
|
|
135
|
+
if (basePart.includes("*")) {
|
|
136
|
+
const basePattern = basePart.replace("*", "");
|
|
137
|
+
try {
|
|
138
|
+
const entries = fs.readdirSync(this.rootPath);
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
if (entry.startsWith(basePattern)) {
|
|
141
|
+
const fullPath = path.join(this.rootPath, entry);
|
|
142
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
143
|
+
result.push(entry);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Ignore errors
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Detect test runner from package.json
|
|
156
|
+
*/
|
|
157
|
+
detectTestRunner(packageJson) {
|
|
158
|
+
const deps = {
|
|
159
|
+
...(packageJson.dependencies || {}),
|
|
160
|
+
...(packageJson.devDependencies || {}),
|
|
161
|
+
};
|
|
162
|
+
if ("nx" in deps)
|
|
163
|
+
return "nx";
|
|
164
|
+
if ("vitest" in deps)
|
|
165
|
+
return "vitest";
|
|
166
|
+
if ("jest" in deps)
|
|
167
|
+
return "jest";
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Read package.json from directory
|
|
172
|
+
*/
|
|
173
|
+
readPackageJson(dir) {
|
|
174
|
+
const packageJsonPath = path.join(dir, "package.json");
|
|
175
|
+
try {
|
|
176
|
+
const content = fs.readFileSync(packageJsonPath, "utf-8");
|
|
177
|
+
return JSON.parse(content);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Find package.json for a given file path
|
|
185
|
+
*/
|
|
186
|
+
findPackageJsonForFile(filePath) {
|
|
187
|
+
let dir = path.dirname(filePath);
|
|
188
|
+
while (dir !== path.dirname(dir)) {
|
|
189
|
+
const packageJsonPath = path.join(dir, "package.json");
|
|
190
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
191
|
+
return packageJsonPath;
|
|
192
|
+
}
|
|
193
|
+
dir = path.dirname(dir);
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Read tsconfig.json
|
|
199
|
+
*/
|
|
200
|
+
readTsConfig(dir = this.rootPath) {
|
|
201
|
+
const tsConfigPath = path.join(dir, "tsconfig.json");
|
|
202
|
+
try {
|
|
203
|
+
const content = fs.readFileSync(tsConfigPath, "utf-8");
|
|
204
|
+
return JSON.parse(content);
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
export async function createProjectDetector(rootPath) {
|
|
212
|
+
return new ProjectDetector(rootPath);
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/project/detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report formatting
|
|
3
|
+
* Outputs analysis results in various formats
|
|
4
|
+
*/
|
|
5
|
+
import type { AnalysisResult } from "../core/models.js";
|
|
6
|
+
export declare class ReportFormatter {
|
|
7
|
+
/**
|
|
8
|
+
* Format as JSON
|
|
9
|
+
*/
|
|
10
|
+
formatAsJson(result: AnalysisResult): string;
|
|
11
|
+
/**
|
|
12
|
+
* Format as compact terminal output
|
|
13
|
+
*/
|
|
14
|
+
formatAsTerminal(result: AnalysisResult): string;
|
|
15
|
+
/**
|
|
16
|
+
* Format as markdown
|
|
17
|
+
*/
|
|
18
|
+
formatAsMarkdown(result: AnalysisResult): string;
|
|
19
|
+
/**
|
|
20
|
+
* Format as summary
|
|
21
|
+
*/
|
|
22
|
+
formatAsSummary(result: AnalysisResult): string;
|
|
23
|
+
formatAsCi(result: AnalysisResult): string;
|
|
24
|
+
}
|
|
25
|
+
export declare function createReportFormatter(): ReportFormatter;
|
|
26
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/report/json.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAyB,MAAM,mBAAmB,CAAC;AAE/E,qBAAa,eAAe;IACxB;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAI5C;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAiEhD;;OAEG;IACH,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAqDhD;;OAEG;IACL,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAgB/C,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;CAY3C;AAED,wBAAgB,qBAAqB,IAAI,eAAe,CAEvD"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Report formatting
|
|
3
|
+
* Outputs analysis results in various formats
|
|
4
|
+
*/
|
|
5
|
+
export class ReportFormatter {
|
|
6
|
+
/**
|
|
7
|
+
* Format as JSON
|
|
8
|
+
*/
|
|
9
|
+
formatAsJson(result) {
|
|
10
|
+
return JSON.stringify(result, null, 2);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Format as compact terminal output
|
|
14
|
+
*/
|
|
15
|
+
formatAsTerminal(result) {
|
|
16
|
+
const lines = [];
|
|
17
|
+
lines.push("FRANKLY · RED INK REVIEW\n");
|
|
18
|
+
// Task
|
|
19
|
+
lines.push(`Task\n${result.task}\n`);
|
|
20
|
+
// Verdict
|
|
21
|
+
const review = result.review;
|
|
22
|
+
lines.push(`CHANGE VERDICT\n${review.verdict}\n`);
|
|
23
|
+
// Metrics
|
|
24
|
+
lines.push(`TASK ALIGNMENT\n${review.taskAlignment}\n`);
|
|
25
|
+
lines.push(`CHANGE NECESSITY\n${review.changeNecessity}/100\n`);
|
|
26
|
+
lines.push(`CHANGE SURFACE\n${review.changeSurface}\n`);
|
|
27
|
+
lines.push(`SCOPE DRIFT\n${Math.round(review.scopeDrift * 100)}%\n`);
|
|
28
|
+
lines.push(`MINIMUM PATCH\n${result.files.length} file(s), ${result.symbols.length} changed symbol(s)\n`);
|
|
29
|
+
// Red marks
|
|
30
|
+
if (review.findings.length > 0) {
|
|
31
|
+
lines.push("RED MARKS\n");
|
|
32
|
+
for (const finding of review.findings) {
|
|
33
|
+
const icon = finding.severity === "error" ? "✗" : "⚠";
|
|
34
|
+
lines.push(`${icon} ${finding.title}`);
|
|
35
|
+
}
|
|
36
|
+
lines.push("");
|
|
37
|
+
}
|
|
38
|
+
// Blast radius
|
|
39
|
+
lines.push("BLAST RADIUS\n");
|
|
40
|
+
lines.push(`Direct callers ${review.blastRadius.directCallers}`);
|
|
41
|
+
lines.push(`Transitive callers ${review.blastRadius.transitiveCallers}`);
|
|
42
|
+
lines.push(`Packages ${review.blastRadius.affectedPackages}\n`);
|
|
43
|
+
// Test impact
|
|
44
|
+
lines.push("TEST IMPACT\n");
|
|
45
|
+
lines.push(`Likely affected ${review.testImpact.likelyAffected}`);
|
|
46
|
+
lines.push(`Possibly affected ${review.testImpact.possiblyAffected}`);
|
|
47
|
+
lines.push(`Executed ${review.testImpact.executed}`);
|
|
48
|
+
lines.push(`Passed ${review.testImpact.passed}\n`);
|
|
49
|
+
for (const test of review.testImpact.predicted.slice(0, 10)) {
|
|
50
|
+
lines.push(` ${test.status.padEnd(19)} ${test.path}`);
|
|
51
|
+
}
|
|
52
|
+
if (review.testImpact.predicted.length)
|
|
53
|
+
lines.push("");
|
|
54
|
+
if (review.contractChanges.length) {
|
|
55
|
+
lines.push("CONTRACT CHANGES\n");
|
|
56
|
+
for (const contract of review.contractChanges.slice(0, 10))
|
|
57
|
+
lines.push(`⚠ ${contract.type} ${contract.location}`);
|
|
58
|
+
lines.push("");
|
|
59
|
+
}
|
|
60
|
+
// Recommendation
|
|
61
|
+
lines.push("RECOMMENDATION\n");
|
|
62
|
+
lines.push(review.recommendation);
|
|
63
|
+
if (review.correction)
|
|
64
|
+
lines.push(`\nCORRECTION PASS (1/1)\n${review.correction.instruction}`);
|
|
65
|
+
if (review.personality) {
|
|
66
|
+
lines.push(`\nFrank: "${review.personality}"`);
|
|
67
|
+
}
|
|
68
|
+
return lines.join("\n");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format as markdown
|
|
72
|
+
*/
|
|
73
|
+
formatAsMarkdown(result) {
|
|
74
|
+
const lines = [];
|
|
75
|
+
lines.push("# Frankly · Red Ink Review\n");
|
|
76
|
+
// Task
|
|
77
|
+
lines.push(`## Task\n${result.task}\n`);
|
|
78
|
+
// Verdict
|
|
79
|
+
const review = result.review;
|
|
80
|
+
lines.push(`## Change Verdict\n**${review.verdict}**\n`);
|
|
81
|
+
// Metrics
|
|
82
|
+
lines.push("## Analysis\n");
|
|
83
|
+
lines.push(`- **Task Alignment**: ${review.taskAlignment}`);
|
|
84
|
+
lines.push(`- **Change Necessity**: ${review.changeNecessity}/100`);
|
|
85
|
+
lines.push(`- **Change Surface**: ${review.changeSurface}`);
|
|
86
|
+
lines.push(`- **Scope Drift**: ${Math.round(review.scopeDrift * 100)}%\n`);
|
|
87
|
+
lines.push(`- **Behavioral Changes**: ${review.behavioralChanges.join(", ") || "none detected"}`);
|
|
88
|
+
// Findings
|
|
89
|
+
if (review.findings.length > 0) {
|
|
90
|
+
lines.push("## Findings\n");
|
|
91
|
+
for (const finding of review.findings) {
|
|
92
|
+
lines.push(`- **${finding.title}** (${finding.severity})\n ${finding.description}`);
|
|
93
|
+
}
|
|
94
|
+
lines.push("");
|
|
95
|
+
}
|
|
96
|
+
// Impact
|
|
97
|
+
lines.push("## Impact\n");
|
|
98
|
+
lines.push("### Blast Radius");
|
|
99
|
+
lines.push(`- Direct callers: ${review.blastRadius.directCallers}`);
|
|
100
|
+
lines.push(`- Transitive callers: ${review.blastRadius.transitiveCallers}`);
|
|
101
|
+
lines.push(`- Affected packages: ${review.blastRadius.affectedPackages}\n`);
|
|
102
|
+
lines.push("### Test Impact");
|
|
103
|
+
lines.push(`- Likely affected: ${review.testImpact.likelyAffected}`);
|
|
104
|
+
lines.push(`- Possibly affected: ${review.testImpact.possiblyAffected}`);
|
|
105
|
+
lines.push(`- Executed: ${review.testImpact.executed}`);
|
|
106
|
+
lines.push(`- Passed: ${review.testImpact.passed}\n`);
|
|
107
|
+
// Recommendation
|
|
108
|
+
lines.push("## Recommendation\n");
|
|
109
|
+
lines.push(review.recommendation);
|
|
110
|
+
if (review.correction)
|
|
111
|
+
lines.push(`\n## Correction Pass\n\n${review.correction.instruction}`);
|
|
112
|
+
return lines.join("\n");
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Format as summary
|
|
116
|
+
*/
|
|
117
|
+
formatAsSummary(result) {
|
|
118
|
+
const review = result.review;
|
|
119
|
+
return `
|
|
120
|
+
FRANKLY ANALYSIS
|
|
121
|
+
|
|
122
|
+
Verdict: ${review.verdict}
|
|
123
|
+
Files changed: ${result.files.length}
|
|
124
|
+
Symbols changed: ${result.symbols.length}
|
|
125
|
+
Findings: ${review.findings.length}
|
|
126
|
+
Task alignment: ${review.taskAlignment}
|
|
127
|
+
Change necessity: ${review.changeNecessity}/100
|
|
128
|
+
|
|
129
|
+
${review.recommendation}
|
|
130
|
+
`.trim();
|
|
131
|
+
}
|
|
132
|
+
formatAsCi(result) {
|
|
133
|
+
return JSON.stringify({
|
|
134
|
+
schemaVersion: result.schemaVersion,
|
|
135
|
+
verdict: result.review.verdict,
|
|
136
|
+
necessityScore: result.review.changeNecessity,
|
|
137
|
+
scopeDrift: result.review.scopeDrift,
|
|
138
|
+
findings: result.review.findings.map(({ id, severity, confidence, title, affectedSymbols }) => ({ id, severity, confidence, title, affectedSymbols })),
|
|
139
|
+
predictedTests: result.review.testImpact.predicted,
|
|
140
|
+
executedTests: result.review.testImpact.executedResults,
|
|
141
|
+
contracts: result.review.contractChanges,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export function createReportFormatter() {
|
|
146
|
+
return new ReportFormatter();
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/report/json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ChangedFile, ExecutedTest, RedInkReview } from "../core/models.js";
|
|
2
|
+
import type { ClassifiedChange } from "../analysis/change-classifier.js";
|
|
3
|
+
import type { RepositoryIntelligence } from "../analysis/repository-intelligence.js";
|
|
4
|
+
import type { FranklyAction, FranklyIntensity, FranklyPersonality } from "../core/config.js";
|
|
5
|
+
export interface ReviewInput {
|
|
6
|
+
task: string;
|
|
7
|
+
files: ChangedFile[];
|
|
8
|
+
classifications: ClassifiedChange[];
|
|
9
|
+
scopeDrift: number;
|
|
10
|
+
fileCount: number;
|
|
11
|
+
symbolCount: number;
|
|
12
|
+
intelligence: RepositoryIntelligence;
|
|
13
|
+
executedTests: ExecutedTest[];
|
|
14
|
+
personality: FranklyPersonality;
|
|
15
|
+
action: FranklyAction;
|
|
16
|
+
intensity: FranklyIntensity;
|
|
17
|
+
disabled: boolean;
|
|
18
|
+
maxCorrectionPasses: number;
|
|
19
|
+
}
|
|
20
|
+
export declare class RedInkReviewBuilder {
|
|
21
|
+
build(input: ReviewInput): RedInkReview;
|
|
22
|
+
private classificationFindings;
|
|
23
|
+
private verdict;
|
|
24
|
+
}
|
|
25
|
+
export declare function createRedInkReviewBuilder(): RedInkReviewBuilder;
|
|
26
|
+
//# sourceMappingURL=red-ink-review.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"red-ink-review.d.ts","sourceRoot":"","sources":["../../src/review/red-ink-review.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAEZ,YAAY,EAEb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wCAAwC,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE7F,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,eAAe,EAAE,gBAAgB,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,sBAAsB,CAAC;IACrC,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,WAAW,EAAE,kBAAkB,CAAC;IAChC,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,gBAAgB,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,mBAAmB;IAC9B,KAAK,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY;IA6CvC,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,OAAO;CAOhB;AAwBD,wBAAgB,yBAAyB,IAAI,mBAAmB,CAE/D"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
export class RedInkReviewBuilder {
|
|
2
|
+
build(input) {
|
|
3
|
+
const confidence = input.intensity === "lite" ? ["high"] : input.intensity === "ultra" ? ["high", "medium", "low"] : ["high", "medium"];
|
|
4
|
+
const findings = input.disabled ? [] : [...this.classificationFindings(input.classifications), ...input.intelligence.findings].filter((item) => confidence.includes(item.confidence));
|
|
5
|
+
const hasUntestedImpact = !input.disabled && input.intelligence.predictedTests.length > 0 && input.executedTests.length === 0;
|
|
6
|
+
const baseVerdict = this.verdict(findings, input.disabled ? 0 : input.scopeDrift, hasUntestedImpact);
|
|
7
|
+
const verdict = input.action === "enforce" && baseVerdict !== "CLEAN" ? "BLOCK" : baseVerdict;
|
|
8
|
+
const justified = input.classifications.filter((item) => ["REQUIRED", "SUPPORTING", "TEST", "GENERATED"].includes(item.classification)).length;
|
|
9
|
+
const necessity = input.disabled ? 100 : input.classifications.length
|
|
10
|
+
? Math.max(0, Math.round((justified / input.classifications.length) * 100 - findings.filter((item) => item.confidence !== "low").length * 5))
|
|
11
|
+
: 100;
|
|
12
|
+
const passed = input.executedTests.filter((test) => test.status === "PASSED").length;
|
|
13
|
+
const correction = input.action === "correct" && input.maxCorrectionPasses > 0 && verdict !== "CLEAN" ? input.intelligence.correction : undefined;
|
|
14
|
+
return {
|
|
15
|
+
task: input.task,
|
|
16
|
+
verdict,
|
|
17
|
+
taskAlignment: necessity >= 80 ? "high" : necessity >= 50 ? "medium" : "low",
|
|
18
|
+
changeNecessity: necessity,
|
|
19
|
+
changeSurface: surface(input.files, input.symbolCount, input.intelligence),
|
|
20
|
+
scopeDrift: input.disabled ? 0 : input.scopeDrift,
|
|
21
|
+
findings,
|
|
22
|
+
blastRadius: {
|
|
23
|
+
directCallers: input.intelligence.directCallers.length,
|
|
24
|
+
transitiveCallers: input.intelligence.transitiveCallers.length,
|
|
25
|
+
affectedPackages: input.intelligence.packages.length,
|
|
26
|
+
callers: [...input.intelligence.directCallers, ...input.intelligence.transitiveCallers],
|
|
27
|
+
packages: input.intelligence.packages,
|
|
28
|
+
},
|
|
29
|
+
testImpact: {
|
|
30
|
+
likelyAffected: input.intelligence.predictedTests.filter((test) => test.status === "LIKELY_AFFECTED").length,
|
|
31
|
+
possiblyAffected: input.intelligence.predictedTests.filter((test) => test.status === "POSSIBLY_AFFECTED").length,
|
|
32
|
+
executed: input.executedTests.length,
|
|
33
|
+
passed,
|
|
34
|
+
predicted: input.intelligence.predictedTests,
|
|
35
|
+
executedResults: input.executedTests,
|
|
36
|
+
},
|
|
37
|
+
contractChanges: input.intelligence.contracts,
|
|
38
|
+
behavioralChanges: input.intelligence.behavioralChanges,
|
|
39
|
+
reuseCandidates: input.intelligence.reuseCandidates,
|
|
40
|
+
correction,
|
|
41
|
+
recommendation: recommendation(verdict, findings, Boolean(correction)),
|
|
42
|
+
personality: personalityLine(input.personality, verdict),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
classificationFindings(classifications) {
|
|
46
|
+
return classifications.flatMap((item, index) => {
|
|
47
|
+
if (!["SUSPICIOUS", "UNEXPLAINED", "REFACTOR", "INCIDENTAL"].includes(item.classification))
|
|
48
|
+
return [];
|
|
49
|
+
const target = "path" in item.symbol ? item.symbol.path : item.symbol.id;
|
|
50
|
+
return [{
|
|
51
|
+
id: `classification-${index + 1}`,
|
|
52
|
+
severity: item.classification === "UNEXPLAINED" ? "error" : "warning",
|
|
53
|
+
confidence: item.confidence,
|
|
54
|
+
title: item.classification === "REFACTOR" ? "Refactor contamination" : `${item.classification[0]}${item.classification.slice(1).toLowerCase()} change`,
|
|
55
|
+
description: item.justification,
|
|
56
|
+
affectedSymbols: [target],
|
|
57
|
+
evidence: item.evidence,
|
|
58
|
+
recommendation: "Remove the change or provide repository evidence that the task requires it.",
|
|
59
|
+
autoCorrectible: true,
|
|
60
|
+
}];
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
verdict(findings, drift, untested) {
|
|
64
|
+
if (findings.some((item) => item.title === "Refactor contamination"))
|
|
65
|
+
return "SPLIT";
|
|
66
|
+
if (findings.some((item) => item.severity === "error") || drift > 0.3 || findings.length > 3)
|
|
67
|
+
return "SIMPLIFY";
|
|
68
|
+
if (untested || findings.some((item) => item.title === "Missing regression coverage"))
|
|
69
|
+
return "VERIFY";
|
|
70
|
+
if (findings.length)
|
|
71
|
+
return "REVIEW";
|
|
72
|
+
return "CLEAN";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function surface(files, symbols, intelligence) {
|
|
76
|
+
const score = files.filter((file) => !/(?:-lock\.json|pnpm-lock\.yaml|yarn\.lock)$/.test(file.path)).length
|
|
77
|
+
+ Math.ceil(symbols / 3)
|
|
78
|
+
+ intelligence.contracts.length * 2
|
|
79
|
+
+ Math.max(0, intelligence.packages.length - 1) * 3;
|
|
80
|
+
return score <= 4 ? "LOW" : score <= 12 ? "MEDIUM" : "HIGH";
|
|
81
|
+
}
|
|
82
|
+
function recommendation(verdict, findings, correction) {
|
|
83
|
+
if (verdict === "CLEAN")
|
|
84
|
+
return "Patch appears appropriately scoped; no red marks found.";
|
|
85
|
+
if (correction)
|
|
86
|
+
return "Give the coding agent the single correction pass below, then run verify_change.";
|
|
87
|
+
if (verdict === "VERIFY")
|
|
88
|
+
return "Run the predicted related tests and record their actual results.";
|
|
89
|
+
if (verdict === "SPLIT")
|
|
90
|
+
return "Move unrelated refactoring into a separate patch.";
|
|
91
|
+
return `Review ${findings.length} evidence-backed finding(s) before approval.`;
|
|
92
|
+
}
|
|
93
|
+
function personalityLine(personality, verdict) {
|
|
94
|
+
if (personality === "conservative")
|
|
95
|
+
return verdict === "CLEAN" ? "The patch appears proportionate." : "These changes may be broader than required.";
|
|
96
|
+
if (personality === "witty")
|
|
97
|
+
return verdict === "CLEAN" ? "Nothing to circle in red." : "The diff brought guests the task did not invite.";
|
|
98
|
+
return verdict === "CLEAN" ? "Every changed line has a plausible reason." : "This task does not yet justify this patch.";
|
|
99
|
+
}
|
|
100
|
+
export function createRedInkReviewBuilder() {
|
|
101
|
+
return new RedInkReviewBuilder();
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=red-ink-review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"red-ink-review.js","sourceRoot":"","sources":["../../src/review/red-ink-review.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Retry HTTP 429 fixture
|
|
2
|
+
|
|
3
|
+
This fixture represents an overly broad AI-generated candidate patch for the task
|
|
4
|
+
"Retry HTTP 429 responses." The baseline already has a retry policy; the candidate
|
|
5
|
+
replaces it with a single-use abstraction and adds an unrelated file.
|
|
6
|
+
|
|
7
|
+
`npm run demo` copies `baseline/` into a temporary Git repository, commits it, then
|
|
8
|
+
overlays `candidate/` before running Frankly's analysis.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const shouldRetry = (status: number) => status >= 500;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const unchangedBehavior = true;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** @format */
|
|
3
|
+
|
|
4
|
+
process.stdout.write(
|
|
5
|
+
JSON.stringify({
|
|
6
|
+
additionalContext:
|
|
7
|
+
"Frankly is active. Use plan_change before uncertain work; use analyze_change at completion; apply at most one minimize_change correction; then use verify_change with actual test results.",
|
|
8
|
+
}),
|
|
9
|
+
);
|