@open-cr-agent/core 0.5.0 → 0.6.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/dist/agent/json.d.ts +2 -0
- package/dist/agent/json.js +12 -0
- package/dist/{pipeline → agent}/pool.js +2 -1
- package/dist/{pipeline/agents.d.ts → agent/settings.d.ts} +10 -5
- package/dist/{pipeline/agents.js → agent/settings.js} +15 -6
- package/dist/anchor/match.js +5 -4
- package/dist/anchor/relocate.d.ts +1 -2
- package/dist/anchor/relocate.js +2 -2
- package/dist/at.d.ts +2 -0
- package/dist/at.js +12 -0
- package/dist/bundle/bundle.d.ts +2 -1
- package/dist/bundle/bundle.js +3 -2
- package/dist/bundle/grouping.d.ts +0 -1
- package/dist/bundle/runtime-grouper.d.ts +5 -0
- package/dist/{pipeline/helpers.js → bundle/runtime-grouper.js} +5 -14
- package/dist/contracts.d.ts +6 -14
- package/dist/contracts.js +2 -1
- package/dist/diff/hunks.js +3 -2
- package/dist/diff/parse.js +5 -4
- package/dist/diff/quoted-path.js +16 -15
- package/dist/domain.d.ts +10 -2
- package/dist/domain.js +2 -2
- package/dist/errors.d.ts +3 -1
- package/dist/errors.js +12 -0
- package/dist/hash.d.ts +2 -0
- package/dist/hash.js +7 -0
- package/dist/index.d.ts +26 -12
- package/dist/index.js +16 -5
- package/dist/internal.d.ts +9 -12
- package/dist/internal.js +9 -12
- package/dist/judge/judge.d.ts +1 -2
- package/dist/judge/judge.js +9 -8
- package/dist/judge/verdict.d.ts +0 -1
- package/dist/judge/verdict.js +1 -1
- package/dist/memory/memory.js +2 -2
- package/dist/net/proxied-fetch.js +2 -1
- package/dist/pipeline/assemble-report.d.ts +22 -0
- package/dist/pipeline/assemble-report.js +99 -0
- package/dist/pipeline/check-stage.d.ts +13 -0
- package/dist/pipeline/check-stage.js +70 -0
- package/dist/pipeline/context.d.ts +2 -1
- package/dist/pipeline/coverage.d.ts +1 -1
- package/dist/pipeline/coverage.js +2 -1
- package/dist/pipeline/execute-stage.d.ts +26 -0
- package/dist/pipeline/execute-stage.js +104 -0
- package/dist/pipeline/execute.d.ts +2 -4
- package/dist/pipeline/execute.js +63 -56
- package/dist/pipeline/filter-stage.d.ts +16 -0
- package/dist/pipeline/filter-stage.js +46 -0
- package/dist/pipeline/findings.js +3 -2
- package/dist/pipeline/imports.d.ts +1 -1
- package/dist/pipeline/imports.js +1 -1
- package/dist/pipeline/matrix.d.ts +1 -8
- package/dist/pipeline/options.d.ts +65 -0
- package/dist/pipeline/options.js +9 -0
- package/dist/pipeline/plan-output.d.ts +90 -0
- package/dist/pipeline/plan-output.js +109 -0
- package/dist/pipeline/plan.d.ts +2 -3
- package/dist/pipeline/plan.js +4 -4
- package/dist/pipeline/preview.d.ts +23 -9
- package/dist/pipeline/preview.js +25 -4
- package/dist/pipeline/provenance.d.ts +4 -27
- package/dist/pipeline/provenance.js +2 -2
- package/dist/pipeline/run.d.ts +2 -48
- package/dist/pipeline/run.js +18 -273
- package/dist/pipeline/task.d.ts +1 -3
- package/dist/pipeline/task.js +4 -4
- package/dist/plugin/registry.d.ts +5 -4
- package/dist/plugin/registry.js +3 -3
- package/dist/plugin/types.d.ts +3 -5
- package/dist/{pipeline → report}/output-schema.d.ts +57 -63
- package/dist/{pipeline → report}/output-schema.js +55 -40
- package/dist/report/output.d.ts +8 -0
- package/dist/report/output.js +211 -0
- package/dist/report/provenance.d.ts +26 -0
- package/dist/report/provenance.js +2 -0
- package/dist/report/read.d.ts +3 -0
- package/dist/report/read.js +34 -0
- package/dist/{pipeline → report}/report.d.ts +1 -1
- package/dist/report/serialize.d.ts +3 -0
- package/dist/report/serialize.js +27 -0
- package/dist/rereview/presence.js +1 -1
- package/dist/rereview/quote.js +2 -2
- package/dist/rereview/reconcile.d.ts +1 -1
- package/dist/review/impact.d.ts +0 -2
- package/dist/review/impact.js +2 -2
- package/dist/review/plan-phase.d.ts +1 -2
- package/dist/review/plan-phase.js +2 -2
- package/dist/review/prompt-text.d.ts +1 -1
- package/dist/review/prompt-text.js +1 -1
- package/dist/review/prompt.d.ts +0 -3
- package/dist/review/prompt.js +3 -3
- package/dist/rules/builtin/index.d.ts +0 -4
- package/dist/rules/builtin/index.js +1 -2
- package/dist/rules/repo-rules.d.ts +0 -6
- package/dist/rules/repo-rules.js +3 -3
- package/dist/runtime/chain-runner.d.ts +19 -0
- package/dist/runtime/chain-runner.js +63 -0
- package/dist/runtime/effort-capability.d.ts +14 -0
- package/dist/runtime/effort-capability.js +70 -0
- package/dist/runtime/failback.d.ts +0 -9
- package/dist/runtime/failback.js +14 -4
- package/dist/runtime/models.d.ts +1 -2
- package/dist/runtime/tools.d.ts +0 -16
- package/dist/runtime/tools.js +3 -3
- package/dist/sarif/candidates.d.ts +2 -1
- package/dist/sarif/schema.d.ts +2 -2
- package/dist/sarif/schema.js +4 -4
- package/dist/session/jsonl.d.ts +2 -2
- package/dist/session/jsonl.js +5 -4
- package/dist/triage.d.ts +2 -2
- package/dist/triage.js +1 -1
- package/dist/vcs.d.ts +15 -0
- package/dist/vcs.js +2 -0
- package/dist/verify/prompt.d.ts +0 -6
- package/dist/verify/prompt.js +1 -1
- package/dist/verify/verify.d.ts +2 -3
- package/dist/verify/verify.js +4 -4
- package/package.json +1 -1
- package/dist/pipeline/helpers.d.ts +0 -7
- package/dist/pipeline/output.d.ts +0 -79
- package/dist/pipeline/output.js +0 -132
- /package/dist/{pipeline → agent}/budget.d.ts +0 -0
- /package/dist/{pipeline → agent}/budget.js +0 -0
- /package/dist/{pipeline → agent}/pool.d.ts +0 -0
- /package/dist/{pipeline → agent}/usage.d.ts +0 -0
- /package/dist/{pipeline → agent}/usage.js +0 -0
- /package/dist/{pipeline → report}/report.js +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// What ocra knows of current models, matched on the model id's last path
|
|
2
|
+
// segment, so "anthropic/claude-sonnet-4-5" and an OpenRouter
|
|
3
|
+
// "openrouter/anthropic/claude-sonnet-4.5" both match. It goes stale as
|
|
4
|
+
// models ship: a model it does not know, or a level it says a model does
|
|
5
|
+
// not take, is left out of the call with a warning, never refused. The first
|
|
6
|
+
// matching row wins, so a family's later versions come first.
|
|
7
|
+
const CAPABILITIES = [
|
|
8
|
+
{
|
|
9
|
+
pattern: /^gpt-5\.\d/,
|
|
10
|
+
parameter: "reasoningEffort",
|
|
11
|
+
levels: ["none", "low", "medium", "high"],
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
pattern: /^gpt-5(?:$|-)/,
|
|
15
|
+
parameter: "reasoningEffort",
|
|
16
|
+
levels: ["minimal", "low", "medium", "high"],
|
|
17
|
+
},
|
|
18
|
+
{ pattern: /^o[134](?:$|-)/, parameter: "reasoningEffort", levels: ["low", "medium", "high"] },
|
|
19
|
+
{
|
|
20
|
+
pattern: /^claude-(?:(?:opus|sonnet|haiku)-)?[4-9]/,
|
|
21
|
+
parameter: "thinkingBudget",
|
|
22
|
+
levels: ["none", "minimal", "low", "medium", "high"],
|
|
23
|
+
budget: { min: 1_024 },
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
pattern: /^gemini-2\.5-pro/,
|
|
27
|
+
parameter: "thinkingBudget",
|
|
28
|
+
levels: ["minimal", "low", "medium", "high"],
|
|
29
|
+
budget: { min: 128, max: 32_768 },
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
pattern: /^gemini-2\.5-flash/,
|
|
33
|
+
parameter: "thinkingBudget",
|
|
34
|
+
levels: ["none", "minimal", "low", "medium", "high"],
|
|
35
|
+
budget: { min: 512, max: 24_576 },
|
|
36
|
+
},
|
|
37
|
+
{ pattern: /^gemini-3/, parameter: "thinkingLevel", levels: ["low", "high"] },
|
|
38
|
+
];
|
|
39
|
+
export function effortCapability(model) {
|
|
40
|
+
const id = (model.split("/").at(-1) ?? model).toLowerCase();
|
|
41
|
+
const row = CAPABILITIES.find((r) => r.pattern.test(id));
|
|
42
|
+
if (!row)
|
|
43
|
+
return undefined;
|
|
44
|
+
const { pattern: _, ...capability } = row;
|
|
45
|
+
return capability;
|
|
46
|
+
}
|
|
47
|
+
// Share of the model's output limit each level may spend on thinking.
|
|
48
|
+
const BUDGET_SHARE = {
|
|
49
|
+
minimal: 1 / 32,
|
|
50
|
+
low: 1 / 16,
|
|
51
|
+
medium: 1 / 4,
|
|
52
|
+
high: 1 / 2,
|
|
53
|
+
};
|
|
54
|
+
// Claude Opus 4's output limit, the smallest among the models the table
|
|
55
|
+
// knows: a budget derived from it fits all of them.
|
|
56
|
+
export const FALLBACK_OUTPUT_LIMIT = 32_000;
|
|
57
|
+
// The thinking budget for a level, derived from the model's output limit
|
|
58
|
+
// (the fallback when the catalog gives none); 0 for "none". Undefined when
|
|
59
|
+
// no budget within the bounds fits below that limit.
|
|
60
|
+
export function thinkingBudget(capability, level, outputLimit) {
|
|
61
|
+
if (level === "none")
|
|
62
|
+
return 0;
|
|
63
|
+
const limit = outputLimit && outputLimit > 0 ? outputLimit : FALLBACK_OUTPUT_LIMIT;
|
|
64
|
+
const min = capability.budget?.min ?? 0;
|
|
65
|
+
const max = Math.min(capability.budget?.max ?? Number.POSITIVE_INFINITY, limit - 1);
|
|
66
|
+
if (min > max)
|
|
67
|
+
return undefined;
|
|
68
|
+
return Math.min(max, Math.max(min, Math.floor(limit * BUDGET_SHARE[level])));
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=effort-capability.js.map
|
|
@@ -11,15 +11,6 @@ export interface FailbackOptions {
|
|
|
11
11
|
attempt(model: string, onUsage: (spent: Usage) => void): Promise<AttemptOutcome>;
|
|
12
12
|
}
|
|
13
13
|
export declare function withFailback(options: FailbackOptions): AsyncGenerator<AgentEvent>;
|
|
14
|
-
export declare class LiveUsage {
|
|
15
|
-
private seen;
|
|
16
|
-
private given;
|
|
17
|
-
private wake;
|
|
18
|
-
observe(spent: Usage): void;
|
|
19
|
-
changed(): Promise<void>;
|
|
20
|
-
take(): Usage;
|
|
21
|
-
rest(total: Usage): Usage;
|
|
22
|
-
}
|
|
23
14
|
export interface CompleteOptions {
|
|
24
15
|
tier: ModelTier;
|
|
25
16
|
agent?: string;
|
package/dist/runtime/failback.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { addUsage, emptyUsage } from "../agent/usage.js";
|
|
1
2
|
import { CompletionError } from "../errors.js";
|
|
2
|
-
import { addUsage, emptyUsage } from "../pipeline/usage.js";
|
|
3
3
|
import { attemptSummary } from "./attempt.js";
|
|
4
4
|
import { sleep } from "./quota.js";
|
|
5
5
|
// Findings from a failed attempt are still emitted: the pipeline deduplicates
|
|
@@ -75,7 +75,7 @@ export async function* withFailback(options) {
|
|
|
75
75
|
// Hands out what an attempt has spent in increments, each what grew since the
|
|
76
76
|
// last one; `rest` settles the finished attempt's total, so the increments
|
|
77
77
|
// add up to it and nothing is counted twice.
|
|
78
|
-
|
|
78
|
+
class LiveUsage {
|
|
79
79
|
seen = emptyUsage();
|
|
80
80
|
given = emptyUsage();
|
|
81
81
|
wake;
|
|
@@ -113,11 +113,21 @@ const FIELDS = [
|
|
|
113
113
|
"cachedTokens",
|
|
114
114
|
"costUsd",
|
|
115
115
|
];
|
|
116
|
+
// Each field of a usage from the same field of two others.
|
|
117
|
+
function mapUsage(a, b, combine) {
|
|
118
|
+
return {
|
|
119
|
+
inputTokens: combine(a.inputTokens, b.inputTokens),
|
|
120
|
+
outputTokens: combine(a.outputTokens, b.outputTokens),
|
|
121
|
+
reasoningTokens: combine(a.reasoningTokens, b.reasoningTokens),
|
|
122
|
+
cachedTokens: combine(a.cachedTokens, b.cachedTokens),
|
|
123
|
+
costUsd: combine(a.costUsd, b.costUsd),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
116
126
|
function larger(a, b) {
|
|
117
|
-
return
|
|
127
|
+
return mapUsage(a, b, Math.max);
|
|
118
128
|
}
|
|
119
129
|
function beyond(a, b) {
|
|
120
|
-
return
|
|
130
|
+
return mapUsage(a, b, (x, y) => Math.max(0, x - y));
|
|
121
131
|
}
|
|
122
132
|
function ahead(a, b) {
|
|
123
133
|
return FIELDS.some((f) => a[f] > b[f]);
|
package/dist/runtime/models.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { ModelTier } from "../contracts.js";
|
|
2
|
-
import type { ModelChains } from "../plugin/types.js";
|
|
1
|
+
import type { ModelChains, ModelTier } from "../contracts.js";
|
|
3
2
|
import { type QuotaError } from "./quota.js";
|
|
4
3
|
export interface ModelRef {
|
|
5
4
|
providerID: string;
|
package/dist/runtime/tools.d.ts
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
1
|
import type { ToolDefinition } from "../plugin/types.js";
|
|
3
|
-
export declare const MAX_READ_LINES = 400;
|
|
4
|
-
export declare const MAX_SEARCH_RESULTS = 50;
|
|
5
2
|
export declare const MAX_LINE_CHARS = 2000;
|
|
6
3
|
export declare const MAX_RESULT_CHARS = 50000;
|
|
7
|
-
export declare const reportFindingInput: z.ZodObject<{
|
|
8
|
-
file: z.ZodString;
|
|
9
|
-
existingCode: z.ZodString;
|
|
10
|
-
severity: z.ZodEnum<{
|
|
11
|
-
critical: "critical";
|
|
12
|
-
suggestion: "suggestion";
|
|
13
|
-
warning: "warning";
|
|
14
|
-
}>;
|
|
15
|
-
title: z.ZodString;
|
|
16
|
-
body: z.ZodString;
|
|
17
|
-
suggestion: z.ZodOptional<z.ZodString>;
|
|
18
|
-
evidence: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
19
|
-
}, z.core.$strip>;
|
|
20
4
|
export declare const reviewTools: readonly ToolDefinition[];
|
|
21
5
|
//# sourceMappingURL=tools.d.ts.map
|
package/dist/runtime/tools.js
CHANGED
|
@@ -2,8 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
import { severitySchema } from "../domain.js";
|
|
3
3
|
import { data as promptData } from "../review/prompt-text.js";
|
|
4
4
|
import { REVIEW_TOOLS } from "../review/tools.js";
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
const MAX_READ_LINES = 400;
|
|
6
|
+
const MAX_SEARCH_RESULTS = 50;
|
|
7
7
|
// Lines and results are also capped in characters: one line of a minified
|
|
8
8
|
// bundle or a JSON fixture can be megabytes, and every step resends it.
|
|
9
9
|
export const MAX_LINE_CHARS = 2_000;
|
|
@@ -23,7 +23,7 @@ function fitting(lines) {
|
|
|
23
23
|
}
|
|
24
24
|
return kept;
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
const reportFindingInput = z.object({
|
|
27
27
|
file: z.string().min(1).describe("Path of a file in <ocra_review_files>"),
|
|
28
28
|
existingCode: z
|
|
29
29
|
.string()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LineRange, Severity } from "../domain.js";
|
|
2
2
|
import type { SarifRun } from "./schema.js";
|
|
3
|
-
|
|
3
|
+
interface SarifTool {
|
|
4
4
|
name: string;
|
|
5
5
|
slug: string;
|
|
6
6
|
version?: string;
|
|
@@ -24,4 +24,5 @@ export interface SarifCandidates {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
export declare function sarifCandidates(run: SarifRun): SarifCandidates;
|
|
27
|
+
export {};
|
|
27
28
|
//# sourceMappingURL=candidates.d.ts.map
|
package/dist/sarif/schema.d.ts
CHANGED
|
@@ -37,7 +37,7 @@ declare const result: z.ZodObject<{
|
|
|
37
37
|
}, z.core.$loose>>;
|
|
38
38
|
}, z.core.$loose>>>;
|
|
39
39
|
}, z.core.$loose>;
|
|
40
|
-
|
|
40
|
+
declare const sarifRunSchema: z.ZodObject<{
|
|
41
41
|
tool: z.ZodObject<{
|
|
42
42
|
driver: z.ZodObject<{
|
|
43
43
|
name: z.ZodString;
|
|
@@ -83,7 +83,7 @@ export declare const sarifRunSchema: z.ZodObject<{
|
|
|
83
83
|
}, z.core.$loose>>>;
|
|
84
84
|
}, z.core.$loose>>>;
|
|
85
85
|
}, z.core.$loose>;
|
|
86
|
-
|
|
86
|
+
declare const sarifLogSchema: z.ZodObject<{
|
|
87
87
|
version: z.ZodLiteral<"2.1.0">;
|
|
88
88
|
runs: z.ZodArray<z.ZodObject<{
|
|
89
89
|
tool: z.ZodObject<{
|
package/dist/sarif/schema.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { OcraError } from "../errors.js";
|
|
2
|
+
import { errorMessage, OcraError } from "../errors.js";
|
|
3
3
|
// The part of SARIF 2.1.0 an import reads. Objects are loose: a log carries
|
|
4
4
|
// far more than this, and none of it is trusted beyond what is checked here.
|
|
5
5
|
// https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html
|
|
@@ -34,7 +34,7 @@ const result = z.looseObject({
|
|
|
34
34
|
message,
|
|
35
35
|
locations: z.array(location).optional(),
|
|
36
36
|
});
|
|
37
|
-
|
|
37
|
+
const sarifRunSchema = z.looseObject({
|
|
38
38
|
tool: z.looseObject({
|
|
39
39
|
driver: z.looseObject({
|
|
40
40
|
name: z.string().min(1),
|
|
@@ -45,7 +45,7 @@ export const sarifRunSchema = z.looseObject({
|
|
|
45
45
|
}),
|
|
46
46
|
results: z.array(result).optional(),
|
|
47
47
|
});
|
|
48
|
-
|
|
48
|
+
const sarifLogSchema = z.looseObject({
|
|
49
49
|
version: z.literal("2.1.0"),
|
|
50
50
|
runs: z.array(sarifRunSchema),
|
|
51
51
|
});
|
|
@@ -61,7 +61,7 @@ export function parseSarifLog(text) {
|
|
|
61
61
|
data = JSON.parse(text);
|
|
62
62
|
}
|
|
63
63
|
catch (error) {
|
|
64
|
-
throw new SarifError(`not valid JSON: ${error
|
|
64
|
+
throw new SarifError(`not valid JSON: ${errorMessage(error)}`);
|
|
65
65
|
}
|
|
66
66
|
const parsed = sarifLogSchema.safeParse(data);
|
|
67
67
|
if (!parsed.success)
|
package/dist/session/jsonl.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ReviewEvent } from "../
|
|
1
|
+
import type { ReviewEvent } from "../report/report.js";
|
|
2
2
|
export declare const EVENTS_FILE = "events.jsonl";
|
|
3
3
|
export declare const REPORT_FILE = "report.json";
|
|
4
4
|
export declare class JsonlSessionWriter {
|
|
5
|
-
readonly id: string;
|
|
6
5
|
readonly dir: string;
|
|
6
|
+
readonly id: string;
|
|
7
7
|
constructor(sessionsDir: string, id?: string);
|
|
8
8
|
write(event: ReviewEvent): void;
|
|
9
9
|
}
|
package/dist/session/jsonl.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { appendFileSync, closeSync, constants, lstatSync, mkdirSync, openSync, writeFileSync, writeSync, } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
-
import { OcraError } from "../errors.js";
|
|
4
|
-
import { serializeOutput, toReportOutput } from "../pipeline/output.js";
|
|
3
|
+
import { isNotFound, OcraError } from "../errors.js";
|
|
5
4
|
import { newRunId } from "../pipeline/run-id.js";
|
|
5
|
+
import { toReportOutput } from "../report/output.js";
|
|
6
|
+
import { serializeOutput } from "../report/serialize.js";
|
|
6
7
|
export const EVENTS_FILE = "events.jsonl";
|
|
7
8
|
export const REPORT_FILE = "report.json";
|
|
8
9
|
// Events are appended synchronously, one JSON object per line, so the log
|
|
9
10
|
// stays valid and ordered even if the process dies mid-run.
|
|
10
11
|
export class JsonlSessionWriter {
|
|
11
|
-
id;
|
|
12
12
|
dir;
|
|
13
|
+
id;
|
|
13
14
|
constructor(sessionsDir, id = newRunId()) {
|
|
14
15
|
this.id = id;
|
|
15
16
|
// The sessions directory lives in the reviewed tree, which may carry
|
|
@@ -44,7 +45,7 @@ function refuseSymlink(path) {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
catch (error) {
|
|
47
|
-
if (error
|
|
48
|
+
if (!isNotFound(error))
|
|
48
49
|
throw error;
|
|
49
50
|
}
|
|
50
51
|
}
|
package/dist/triage.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { FileDiff, RiskTier } from "./domain.js";
|
|
2
|
-
|
|
2
|
+
interface TriagePolicy {
|
|
3
3
|
trivialMaxLines: number;
|
|
4
4
|
liteMaxLines: number;
|
|
5
5
|
maxFilesBeforeFull: number;
|
|
6
6
|
sensitivePathPatterns: RegExp[];
|
|
7
7
|
sensitivePathWords: ReadonlySet<string>;
|
|
8
8
|
}
|
|
9
|
-
export declare const defaultTriagePolicy: TriagePolicy;
|
|
10
9
|
export declare function triage(diffs: readonly FileDiff[], policy?: TriagePolicy): RiskTier;
|
|
10
|
+
export {};
|
|
11
11
|
//# sourceMappingURL=triage.d.ts.map
|
package/dist/triage.js
CHANGED
package/dist/vcs.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CodeMatch } from "./contracts.js";
|
|
2
|
+
import type { ChangeRequest, FileDiff, PriorReview } from "./domain.js";
|
|
3
|
+
import type { ReviewReport } from "./report/report.js";
|
|
4
|
+
export interface VcsAdapter {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
getChangeRequest(): Promise<ChangeRequest>;
|
|
7
|
+
getDiff(): Promise<FileDiff[]>;
|
|
8
|
+
readFile(path: string): Promise<string | undefined>;
|
|
9
|
+
searchCode(literal: string): Promise<CodeMatch[]>;
|
|
10
|
+
getPriorReview(): Promise<PriorReview | undefined>;
|
|
11
|
+
publish(report: ReviewReport): Promise<{
|
|
12
|
+
warnings: string[];
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=vcs.d.ts.map
|
package/dist/vcs.js
ADDED
package/dist/verify/prompt.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import type { Finding } from "../domain.js";
|
|
3
|
-
export declare const verificationVerdictSchema: z.ZodEnum<{
|
|
4
|
-
confirmed: "confirmed";
|
|
5
|
-
refuted: "refuted";
|
|
6
|
-
uncertain: "uncertain";
|
|
7
|
-
}>;
|
|
8
|
-
export type VerificationVerdict = z.infer<typeof verificationVerdictSchema>;
|
|
9
3
|
export declare const verificationResponseSchema: z.ZodArray<z.ZodObject<{
|
|
10
4
|
index: z.ZodNumber;
|
|
11
5
|
verdict: z.ZodEnum<{
|
package/dist/verify/prompt.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { data, join, labelled, oneLine, section } from "../review/prompt-text.js";
|
|
3
|
-
|
|
3
|
+
const verificationVerdictSchema = z.enum(["confirmed", "refuted", "uncertain"]);
|
|
4
4
|
export const verificationResponseSchema = z.array(z.object({
|
|
5
5
|
index: z.number().int(),
|
|
6
6
|
verdict: verificationVerdictSchema,
|
package/dist/verify/verify.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import type { SpendTracker } from "../agent/budget.js";
|
|
2
|
+
import { type AgentCallSettings } from "../agent/settings.js";
|
|
1
3
|
import type { AgentRuntime, ReviewContext, Usage } from "../contracts.js";
|
|
2
4
|
import type { FileDiff, Finding } from "../domain.js";
|
|
3
|
-
import { type AgentCallSettings } from "../pipeline/agents.js";
|
|
4
|
-
import type { SpendTracker } from "../pipeline/budget.js";
|
|
5
|
-
export declare const VERIFY_TIMEOUT_MS = 120000;
|
|
6
5
|
export interface RefutedFinding {
|
|
7
6
|
fingerprint: string;
|
|
8
7
|
file: string;
|
package/dist/verify/verify.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import { parseJsonAnswer } from "../agent/json.js";
|
|
2
|
+
import { mapWithConcurrency } from "../agent/pool.js";
|
|
3
|
+
import { agentCall } from "../agent/settings.js";
|
|
1
4
|
import { errorMessage, OcraError, usageSpent } from "../errors.js";
|
|
2
|
-
import { agentCall } from "../pipeline/agents.js";
|
|
3
|
-
import { parseJsonAnswer } from "../pipeline/helpers.js";
|
|
4
|
-
import { mapWithConcurrency } from "../pipeline/pool.js";
|
|
5
5
|
import { buildVerificationPrompt, fileExcerpt, verificationResponseSchema } from "./prompt.js";
|
|
6
|
-
|
|
6
|
+
const VERIFY_TIMEOUT_MS = 120_000;
|
|
7
7
|
// Precision without losing recall to doubt: a finding is dropped only when
|
|
8
8
|
// the verifier says the code shown proves it wrong. Any failure keeps it.
|
|
9
9
|
export async function verifyFindings(findings, options) {
|
package/package.json
CHANGED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { FileGrouper } from "../bundle/grouping.js";
|
|
2
|
-
import type { AgentRuntime, Usage } from "../contracts.js";
|
|
3
|
-
import { type AgentCallSettings } from "./agents.js";
|
|
4
|
-
export declare const HELPER_TIMEOUT_MS = 60000;
|
|
5
|
-
export declare function runtimeGrouper(runtime: AgentRuntime, signal: AbortSignal, onUsage: (usage: Usage) => void, call?: AgentCallSettings): FileGrouper | undefined;
|
|
6
|
-
export declare function parseJsonAnswer(text: string): unknown;
|
|
7
|
-
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Usage } from "../contracts.js";
|
|
2
|
-
import type { ChangeRequest, RiskTier, Severity, Verdict, Verification } from "../domain.js";
|
|
3
|
-
import type { JudgeDecisions } from "../judge/judge.js";
|
|
4
|
-
import type { MemoryEntry, MemorySource } from "../memory/memory.js";
|
|
5
|
-
import type { RefutedFinding } from "../verify/verify.js";
|
|
6
|
-
import type { SkippedCell } from "./matrix.js";
|
|
7
|
-
import type { ReviewPreview } from "./preview.js";
|
|
8
|
-
import type { RunProvenance } from "./provenance.js";
|
|
9
|
-
import type { AnchoringSummary, CoverageEntry, ReviewReport, TaskOutcome } from "./report.js";
|
|
10
|
-
export declare const REPORT_VERSION = 1;
|
|
11
|
-
export interface OutputFinding {
|
|
12
|
-
fingerprint: string;
|
|
13
|
-
reviewer: string;
|
|
14
|
-
category: string;
|
|
15
|
-
severity: Severity;
|
|
16
|
-
verification: Verification;
|
|
17
|
-
file: string;
|
|
18
|
-
lines?: {
|
|
19
|
-
start: number;
|
|
20
|
-
end: number;
|
|
21
|
-
};
|
|
22
|
-
inDiff: boolean;
|
|
23
|
-
status: "new" | "unfixed";
|
|
24
|
-
title: string;
|
|
25
|
-
body: string;
|
|
26
|
-
suggestion?: string;
|
|
27
|
-
evidence: string[];
|
|
28
|
-
code: string;
|
|
29
|
-
lowConfidence?: true;
|
|
30
|
-
provenance?: {
|
|
31
|
-
task: string;
|
|
32
|
-
model?: string;
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
export interface OutputPriorFinding {
|
|
36
|
-
fingerprint: string;
|
|
37
|
-
title: string;
|
|
38
|
-
file: string;
|
|
39
|
-
severity: Severity;
|
|
40
|
-
verification: Verification;
|
|
41
|
-
}
|
|
42
|
-
export interface ReportOutput {
|
|
43
|
-
version: typeof REPORT_VERSION;
|
|
44
|
-
runId?: string;
|
|
45
|
-
changeRequest: ChangeRequest;
|
|
46
|
-
tier: RiskTier;
|
|
47
|
-
verdict: Verdict;
|
|
48
|
-
summary: string;
|
|
49
|
-
scope?: ReviewReport["scope"];
|
|
50
|
-
coverage: CoverageEntry[];
|
|
51
|
-
findings: OutputFinding[];
|
|
52
|
-
unverifiedCriticals: number;
|
|
53
|
-
refuted: RefutedFinding[];
|
|
54
|
-
remembered: (MemoryEntry & {
|
|
55
|
-
source?: MemorySource;
|
|
56
|
-
})[];
|
|
57
|
-
judgement?: JudgeDecisions;
|
|
58
|
-
rereview?: Record<"fixed" | "notReproduced" | "notRechecked" | "unchanged" | "dismissed", OutputPriorFinding[]>;
|
|
59
|
-
tasks: TaskOutcome[];
|
|
60
|
-
skipped: SkippedCell[];
|
|
61
|
-
bundles: {
|
|
62
|
-
label: string;
|
|
63
|
-
files: string[];
|
|
64
|
-
}[];
|
|
65
|
-
anchoring?: AnchoringSummary;
|
|
66
|
-
spendLimit?: ReviewReport["spendLimit"];
|
|
67
|
-
provenance?: RunProvenance;
|
|
68
|
-
usage: Usage;
|
|
69
|
-
warnings: string[];
|
|
70
|
-
}
|
|
71
|
-
export declare function toReportOutput(report: ReviewReport): ReportOutput;
|
|
72
|
-
export declare const PLAN_VERSION = 1;
|
|
73
|
-
export type PlanOutput = {
|
|
74
|
-
version: typeof PLAN_VERSION;
|
|
75
|
-
} & ReviewPreview;
|
|
76
|
-
export declare function toPlanOutput(preview: ReviewPreview): PlanOutput;
|
|
77
|
-
export declare function isUnsafeCodePoint(code: number): boolean;
|
|
78
|
-
export declare function serializeOutput(value: unknown, indent?: number): string;
|
|
79
|
-
//# sourceMappingURL=output.d.ts.map
|
package/dist/pipeline/output.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// The published shape of a review: `--format json` and a session's
|
|
2
|
-
// report.json. It is a contract with scripts and CI, so it carries a version
|
|
3
|
-
// and only what a reader can rely on; internal fields (per-run ids, how each
|
|
4
|
-
// finding was anchored, code signatures, platform state) stay out, though the
|
|
5
|
-
// anchoring counts of the whole run are in. Change it
|
|
6
|
-
// only by adding optional fields, or by a new version.
|
|
7
|
-
export const REPORT_VERSION = 1;
|
|
8
|
-
export function toReportOutput(report) {
|
|
9
|
-
const output = {
|
|
10
|
-
version: REPORT_VERSION,
|
|
11
|
-
runId: report.runId,
|
|
12
|
-
changeRequest: report.changeRequest,
|
|
13
|
-
tier: report.tier,
|
|
14
|
-
verdict: report.verdict,
|
|
15
|
-
summary: report.summary,
|
|
16
|
-
coverage: report.coverage,
|
|
17
|
-
findings: report.findings.map(outputFinding),
|
|
18
|
-
unverifiedCriticals: report.unverifiedCriticals,
|
|
19
|
-
refuted: report.refuted,
|
|
20
|
-
remembered: report.remembered,
|
|
21
|
-
tasks: report.tasks,
|
|
22
|
-
skipped: report.skipped,
|
|
23
|
-
bundles: report.bundles,
|
|
24
|
-
usage: report.usage,
|
|
25
|
-
warnings: report.warnings,
|
|
26
|
-
};
|
|
27
|
-
if (report.scope)
|
|
28
|
-
output.scope = report.scope;
|
|
29
|
-
if (report.judgement)
|
|
30
|
-
output.judgement = report.judgement;
|
|
31
|
-
if (report.anchoring)
|
|
32
|
-
output.anchoring = report.anchoring;
|
|
33
|
-
if (report.spendLimit)
|
|
34
|
-
output.spendLimit = report.spendLimit;
|
|
35
|
-
if (report.provenance)
|
|
36
|
-
output.provenance = report.provenance;
|
|
37
|
-
if (report.rereview) {
|
|
38
|
-
const r = report.rereview;
|
|
39
|
-
output.rereview = {
|
|
40
|
-
fixed: r.fixed.map(outputPrior),
|
|
41
|
-
notReproduced: r.notReproduced.map(outputPrior),
|
|
42
|
-
notRechecked: r.notRechecked.map(outputPrior),
|
|
43
|
-
unchanged: r.unchanged.map(outputPrior),
|
|
44
|
-
dismissed: r.dismissed.map(outputPrior),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return output;
|
|
48
|
-
}
|
|
49
|
-
function outputFinding(f) {
|
|
50
|
-
const output = {
|
|
51
|
-
fingerprint: f.fingerprint,
|
|
52
|
-
reviewer: f.reviewer,
|
|
53
|
-
category: f.category,
|
|
54
|
-
severity: f.severity,
|
|
55
|
-
verification: f.verification ?? "unchecked",
|
|
56
|
-
file: f.file,
|
|
57
|
-
inDiff: f.anchor.inDiff,
|
|
58
|
-
status: f.status === "unfixed" ? "unfixed" : "new",
|
|
59
|
-
title: f.title,
|
|
60
|
-
body: f.body,
|
|
61
|
-
evidence: f.evidence,
|
|
62
|
-
code: f.existingCode,
|
|
63
|
-
};
|
|
64
|
-
if (f.lineRange)
|
|
65
|
-
output.lines = { start: f.lineRange.start, end: f.lineRange.end };
|
|
66
|
-
if (f.suggestion !== undefined)
|
|
67
|
-
output.suggestion = f.suggestion;
|
|
68
|
-
if (f.lowConfidence)
|
|
69
|
-
output.lowConfidence = true;
|
|
70
|
-
output.provenance =
|
|
71
|
-
f.provenance.model === undefined
|
|
72
|
-
? { task: f.provenance.task }
|
|
73
|
-
: { task: f.provenance.task, model: f.provenance.model };
|
|
74
|
-
return output;
|
|
75
|
-
}
|
|
76
|
-
function outputPrior(f) {
|
|
77
|
-
return {
|
|
78
|
-
fingerprint: f.fingerprint,
|
|
79
|
-
title: f.title,
|
|
80
|
-
file: f.file,
|
|
81
|
-
severity: f.severity,
|
|
82
|
-
verification: f.verification ?? "unchecked",
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
// The published shape of `ocra review --plan --format json`, versioned like
|
|
86
|
-
// the report. The preview is already free of internal fields; the version
|
|
87
|
-
// makes the contract explicit.
|
|
88
|
-
export const PLAN_VERSION = 1;
|
|
89
|
-
export function toPlanOutput(preview) {
|
|
90
|
-
return {
|
|
91
|
-
version: PLAN_VERSION,
|
|
92
|
-
changeRequest: preview.changeRequest,
|
|
93
|
-
tier: preview.tier,
|
|
94
|
-
selected: preview.selected,
|
|
95
|
-
excluded: preview.excluded,
|
|
96
|
-
bundles: preview.bundles,
|
|
97
|
-
groupingSkipped: preview.groupingSkipped,
|
|
98
|
-
tasks: preview.tasks,
|
|
99
|
-
skipped: preview.skipped,
|
|
100
|
-
promptTokens: preview.promptTokens,
|
|
101
|
-
// Added in version 1 without a bump: a new field older readers ignore.
|
|
102
|
-
planCalls: preview.planCalls,
|
|
103
|
-
warnings: preview.warnings,
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
// Characters a terminal or an editor acts on: C0 controls but tab and
|
|
107
|
-
// newline, DEL and C1 controls (ANSI and OSC escapes), line and paragraph
|
|
108
|
-
// separators, and bidirectional marks and overrides ("Trojan Source"). One
|
|
109
|
-
// definition for every output: terminal text replaces them, JSON escapes them.
|
|
110
|
-
export function isUnsafeCodePoint(code) {
|
|
111
|
-
return ((code <= 0x1f && code !== 0x09 && code !== 0x0a) ||
|
|
112
|
-
(code >= 0x7f && code <= 0x9f) ||
|
|
113
|
-
code === 0x061c ||
|
|
114
|
-
code === 0x200e ||
|
|
115
|
-
code === 0x200f ||
|
|
116
|
-
code === 0x2028 ||
|
|
117
|
-
code === 0x2029 ||
|
|
118
|
-
(code >= 0x202a && code <= 0x202e) ||
|
|
119
|
-
(code >= 0x2066 && code <= 0x2069));
|
|
120
|
-
}
|
|
121
|
-
// JSON for files and stdout. JSON.stringify escapes C0 controls but not the
|
|
122
|
-
// rest; model and pull request text reaches these files.
|
|
123
|
-
export function serializeOutput(value, indent = 2) {
|
|
124
|
-
let out = "";
|
|
125
|
-
for (const char of JSON.stringify(value, null, indent)) {
|
|
126
|
-
const code = char.codePointAt(0) ?? 0;
|
|
127
|
-
out +=
|
|
128
|
-
code > 0x1f && isUnsafeCodePoint(code) ? `\\u${code.toString(16).padStart(4, "0")}` : char;
|
|
129
|
-
}
|
|
130
|
-
return out;
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=output.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|