@open-cr-agent/core 0.4.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.
Files changed (131) hide show
  1. package/dist/agent/json.d.ts +2 -0
  2. package/dist/agent/json.js +12 -0
  3. package/dist/{pipeline → agent}/pool.js +2 -1
  4. package/dist/{pipeline/agents.d.ts → agent/settings.d.ts} +21 -7
  5. package/dist/agent/settings.js +86 -0
  6. package/dist/anchor/match.js +5 -4
  7. package/dist/anchor/relocate.d.ts +3 -3
  8. package/dist/anchor/relocate.js +4 -4
  9. package/dist/at.d.ts +2 -0
  10. package/dist/at.js +12 -0
  11. package/dist/bundle/bundle.d.ts +2 -1
  12. package/dist/bundle/bundle.js +3 -2
  13. package/dist/bundle/grouping.d.ts +0 -1
  14. package/dist/bundle/runtime-grouper.d.ts +5 -0
  15. package/dist/{pipeline/helpers.js → bundle/runtime-grouper.js} +7 -16
  16. package/dist/contracts.d.ts +8 -14
  17. package/dist/contracts.js +2 -1
  18. package/dist/diff/hunks.js +3 -2
  19. package/dist/diff/parse.js +5 -4
  20. package/dist/diff/quoted-path.js +16 -15
  21. package/dist/domain.d.ts +10 -2
  22. package/dist/domain.js +2 -2
  23. package/dist/errors.d.ts +3 -1
  24. package/dist/errors.js +12 -0
  25. package/dist/hash.d.ts +2 -0
  26. package/dist/hash.js +7 -0
  27. package/dist/index.d.ts +28 -14
  28. package/dist/index.js +16 -5
  29. package/dist/internal.d.ts +10 -13
  30. package/dist/internal.js +10 -13
  31. package/dist/judge/judge.d.ts +3 -3
  32. package/dist/judge/judge.js +10 -9
  33. package/dist/judge/verdict.d.ts +0 -1
  34. package/dist/judge/verdict.js +1 -1
  35. package/dist/memory/memory.d.ts +7 -2
  36. package/dist/memory/memory.js +14 -2
  37. package/dist/net/proxied-fetch.js +2 -1
  38. package/dist/pipeline/assemble-report.d.ts +22 -0
  39. package/dist/pipeline/assemble-report.js +99 -0
  40. package/dist/pipeline/check-stage.d.ts +13 -0
  41. package/dist/pipeline/check-stage.js +70 -0
  42. package/dist/pipeline/context.d.ts +2 -1
  43. package/dist/pipeline/coverage.d.ts +1 -1
  44. package/dist/pipeline/coverage.js +2 -1
  45. package/dist/pipeline/execute-stage.d.ts +26 -0
  46. package/dist/pipeline/execute-stage.js +104 -0
  47. package/dist/pipeline/execute.d.ts +2 -4
  48. package/dist/pipeline/execute.js +65 -58
  49. package/dist/pipeline/filter-stage.d.ts +16 -0
  50. package/dist/pipeline/filter-stage.js +46 -0
  51. package/dist/pipeline/findings.js +3 -2
  52. package/dist/pipeline/imports.d.ts +1 -1
  53. package/dist/pipeline/imports.js +1 -1
  54. package/dist/pipeline/matrix.d.ts +1 -7
  55. package/dist/pipeline/options.d.ts +65 -0
  56. package/dist/pipeline/options.js +9 -0
  57. package/dist/pipeline/plan-output.d.ts +90 -0
  58. package/dist/pipeline/plan-output.js +109 -0
  59. package/dist/pipeline/plan.d.ts +7 -8
  60. package/dist/pipeline/plan.js +12 -9
  61. package/dist/pipeline/preview.d.ts +24 -7
  62. package/dist/pipeline/preview.js +31 -7
  63. package/dist/pipeline/provenance.d.ts +8 -17
  64. package/dist/pipeline/provenance.js +20 -8
  65. package/dist/pipeline/run.d.ts +2 -44
  66. package/dist/pipeline/run.js +18 -273
  67. package/dist/pipeline/task.d.ts +1 -3
  68. package/dist/pipeline/task.js +4 -4
  69. package/dist/plugin/registry.d.ts +5 -4
  70. package/dist/plugin/registry.js +3 -3
  71. package/dist/plugin/types.d.ts +4 -5
  72. package/dist/{pipeline → report}/output-schema.d.ts +70 -58
  73. package/dist/{pipeline → report}/output-schema.js +60 -36
  74. package/dist/report/output.d.ts +8 -0
  75. package/dist/report/output.js +211 -0
  76. package/dist/report/provenance.d.ts +26 -0
  77. package/dist/report/provenance.js +2 -0
  78. package/dist/report/read.d.ts +3 -0
  79. package/dist/report/read.js +34 -0
  80. package/dist/{pipeline → report}/report.d.ts +3 -3
  81. package/dist/report/serialize.d.ts +3 -0
  82. package/dist/report/serialize.js +27 -0
  83. package/dist/rereview/presence.js +1 -1
  84. package/dist/rereview/quote.js +2 -2
  85. package/dist/rereview/reconcile.d.ts +1 -1
  86. package/dist/review/impact.d.ts +0 -2
  87. package/dist/review/impact.js +2 -2
  88. package/dist/review/plan-phase.d.ts +3 -3
  89. package/dist/review/plan-phase.js +4 -4
  90. package/dist/review/prompt-text.d.ts +1 -1
  91. package/dist/review/prompt-text.js +1 -1
  92. package/dist/review/prompt.d.ts +0 -3
  93. package/dist/review/prompt.js +3 -3
  94. package/dist/rules/builtin/index.d.ts +0 -4
  95. package/dist/rules/builtin/index.js +1 -2
  96. package/dist/rules/repo-rules.d.ts +4 -6
  97. package/dist/rules/repo-rules.js +3 -3
  98. package/dist/runtime/chain-runner.d.ts +19 -0
  99. package/dist/runtime/chain-runner.js +63 -0
  100. package/dist/runtime/effort-capability.d.ts +14 -0
  101. package/dist/runtime/effort-capability.js +70 -0
  102. package/dist/runtime/failback.d.ts +2 -9
  103. package/dist/runtime/failback.js +23 -8
  104. package/dist/runtime/models.d.ts +2 -0
  105. package/dist/runtime/models.js +6 -0
  106. package/dist/runtime/tools.d.ts +0 -16
  107. package/dist/runtime/tools.js +3 -3
  108. package/dist/sarif/candidates.d.ts +2 -1
  109. package/dist/sarif/schema.d.ts +2 -2
  110. package/dist/sarif/schema.js +4 -4
  111. package/dist/session/jsonl.d.ts +2 -2
  112. package/dist/session/jsonl.js +5 -4
  113. package/dist/triage.d.ts +2 -2
  114. package/dist/triage.js +1 -1
  115. package/dist/vcs.d.ts +15 -0
  116. package/dist/vcs.js +2 -0
  117. package/dist/verify/prompt.d.ts +0 -6
  118. package/dist/verify/prompt.js +1 -1
  119. package/dist/verify/verify.d.ts +4 -4
  120. package/dist/verify/verify.js +5 -5
  121. package/package.json +1 -1
  122. package/dist/pipeline/agents.js +0 -55
  123. package/dist/pipeline/helpers.d.ts +0 -6
  124. package/dist/pipeline/output.d.ts +0 -77
  125. package/dist/pipeline/output.js +0 -132
  126. /package/dist/{pipeline → agent}/budget.d.ts +0 -0
  127. /package/dist/{pipeline → agent}/budget.js +0 -0
  128. /package/dist/{pipeline → agent}/pool.d.ts +0 -0
  129. /package/dist/{pipeline → agent}/usage.d.ts +0 -0
  130. /package/dist/{pipeline → agent}/usage.js +0 -0
  131. /package/dist/{pipeline → report}/report.js +0 -0
@@ -0,0 +1,109 @@
1
+ import { z } from "zod";
2
+ import { EFFORT_LEVELS } from "../agent/settings.js";
3
+ import { riskTierSchema } from "../domain.js";
4
+ import { changeRequestSchema, skippedCellSchema } from "../report/output-schema.js";
5
+ import { exclusionReasonSchema } from "../select/select.js";
6
+ // The published shape of `ocra review --plan --format json` without what
7
+ // the CLI adds (where each setting came from), versioned like the report: a
8
+ // version only gains optional fields. The type is derived from the schema,
9
+ // and the CLI publishes the JSON Schema of the whole output.
10
+ export const PLAN_VERSION = 1;
11
+ const inputCostSchema = z.discriminatedUnion("status", [
12
+ z.strictObject({ model: z.string(), status: z.literal("priced"), usd: z.number() }),
13
+ z.strictObject({ model: z.string(), status: z.literal("unpriced") }),
14
+ z.strictObject({ model: z.string(), status: z.literal("unknown") }),
15
+ ]);
16
+ const planTaskSchema = z.strictObject({
17
+ taskId: z.string(),
18
+ reviewer: z.string(),
19
+ bundle: z.string(),
20
+ files: z.array(z.string()),
21
+ promptTokens: z.int().nonnegative(),
22
+ effort: z.enum(EFFORT_LEVELS).exactOptional(),
23
+ models: z.array(z.string()).exactOptional(),
24
+ planPromptTokens: z.int().nonnegative().exactOptional(),
25
+ inputCost: inputCostSchema.exactOptional(),
26
+ });
27
+ export const planOutputSchema = z.strictObject({
28
+ version: z.literal(PLAN_VERSION),
29
+ changeRequest: changeRequestSchema,
30
+ tier: riskTierSchema,
31
+ selected: z.array(z.string()),
32
+ excluded: z.array(z.strictObject({ path: z.string(), reason: exclusionReasonSchema })),
33
+ bundles: z.array(z.strictObject({ label: z.string(), files: z.array(z.string()) })),
34
+ groupingSkipped: z.boolean(),
35
+ tasks: z.array(planTaskSchema),
36
+ skipped: z.array(skippedCellSchema),
37
+ promptTokens: z.int().nonnegative(),
38
+ // Added in version 1 without a bump: a new field older readers ignore.
39
+ planCalls: z.int().nonnegative(),
40
+ // Added in version 1 without a bump, like planCalls.
41
+ inputCost: z
42
+ .strictObject({
43
+ usd: z.number(),
44
+ priced: z.int().nonnegative(),
45
+ unpriced: z.int().nonnegative(),
46
+ unknown: z.int().nonnegative(),
47
+ })
48
+ .exactOptional(),
49
+ warnings: z.array(z.string()),
50
+ });
51
+ export function toPlanOutput(preview) {
52
+ const { changeRequest: c, inputCost } = preview;
53
+ return {
54
+ version: PLAN_VERSION,
55
+ changeRequest: {
56
+ id: c.id,
57
+ title: c.title,
58
+ description: c.description,
59
+ baseSha: c.baseSha,
60
+ headSha: c.headSha,
61
+ ...(c.override ? { override: { by: c.override.by, reason: c.override.reason } } : {}),
62
+ },
63
+ tier: preview.tier,
64
+ selected: [...preview.selected],
65
+ excluded: preview.excluded.map((e) => ({ path: e.path, reason: e.reason })),
66
+ bundles: preview.bundles.map((b) => ({ label: b.label, files: [...b.files] })),
67
+ groupingSkipped: preview.groupingSkipped,
68
+ tasks: preview.tasks.map(planTask),
69
+ skipped: preview.skipped.map((s) => ({
70
+ reviewer: s.reviewer,
71
+ bundle: s.bundle,
72
+ reason: s.reason,
73
+ })),
74
+ promptTokens: preview.promptTokens,
75
+ planCalls: preview.planCalls,
76
+ ...(inputCost
77
+ ? {
78
+ inputCost: {
79
+ usd: inputCost.usd,
80
+ priced: inputCost.priced,
81
+ unpriced: inputCost.unpriced,
82
+ unknown: inputCost.unknown,
83
+ },
84
+ }
85
+ : {}),
86
+ warnings: [...preview.warnings],
87
+ };
88
+ }
89
+ function planTask(t) {
90
+ const cost = t.inputCost;
91
+ return {
92
+ taskId: t.taskId,
93
+ reviewer: t.reviewer,
94
+ bundle: t.bundle,
95
+ files: [...t.files],
96
+ promptTokens: t.promptTokens,
97
+ ...(t.effort === undefined ? {} : { effort: t.effort }),
98
+ ...(t.models ? { models: [...t.models] } : {}),
99
+ ...(t.planPromptTokens === undefined ? {} : { planPromptTokens: t.planPromptTokens }),
100
+ ...(cost
101
+ ? {
102
+ inputCost: cost.status === "priced"
103
+ ? { model: cost.model, status: cost.status, usd: cost.usd }
104
+ : { model: cost.model, status: cost.status },
105
+ }
106
+ : {}),
107
+ };
108
+ }
109
+ //# sourceMappingURL=plan-output.js.map
@@ -1,12 +1,11 @@
1
1
  import { type Bundle } from "../bundle/bundle.js";
2
2
  import type { AgentRuntime, ReviewContext, Usage } from "../contracts.js";
3
3
  import type { ChangeRequest, FileDiff, RiskTier } from "../domain.js";
4
- import { type MemoryEntry } from "../memory/memory.js";
5
- import { type RepoRule } from "../rules/repo-rules.js";
4
+ import { type RememberedEntry } from "../memory/memory.js";
5
+ import type { ReviewEvent } from "../report/report.js";
6
+ import { type SourcedRule } from "../rules/repo-rules.js";
6
7
  import { type FileDecision } from "../select/select.js";
7
- import type { ReviewEvent } from "./report.js";
8
- import type { ReviewHooks, ReviewOptions } from "./run.js";
9
- export declare const GUIDELINES_PATH = "AGENTS.md";
8
+ import type { ReviewHooks, ReviewOptions } from "./options.js";
10
9
  export interface ReviewPlan {
11
10
  changeRequest: ChangeRequest;
12
11
  decisions: FileDecision[];
@@ -20,12 +19,12 @@ export interface ReviewPlan {
20
19
  };
21
20
  context: ReviewContext;
22
21
  guidelines: string | undefined;
23
- repoRules: RepoRule[];
24
- memory: MemoryEntry[];
22
+ repoRules: SourcedRule[];
23
+ memory: RememberedEntry[];
25
24
  usage: Usage[];
26
25
  warnings: string[];
27
26
  }
28
- export type PlanOptions = Pick<ReviewOptions & ReviewHooks, "vcs" | "rules" | "readTrusted" | "selection" | "bundling" | "grouper" | "effort" | "roles"> & {
27
+ export type PlanOptions = Pick<ReviewOptions & ReviewHooks, "vcs" | "rules" | "readTrusted" | "accountMemory" | "selection" | "bundling" | "grouper" | "effort" | "roles"> & {
29
28
  runId?: string;
30
29
  runtime?: AgentRuntime;
31
30
  reviewOnly?: ReadonlySet<string>;
@@ -1,21 +1,21 @@
1
+ import { roleCall } from "../agent/settings.js";
1
2
  import { bundleFiles, defaultBundlePolicy } from "../bundle/bundle.js";
2
- import { MEMORY_PATH, parseMemory } from "../memory/memory.js";
3
- import { parseRepoRules, REPO_RULES_PATH } from "../rules/repo-rules.js";
3
+ import { runtimeGrouper } from "../bundle/runtime-grouper.js";
4
+ import { MEMORY_PATH, mergeMemory, parseMemory } from "../memory/memory.js";
5
+ import { parseRepoRules, REPO_RULES_PATH, } from "../rules/repo-rules.js";
4
6
  import { defaultSelectionPolicy, selectFiles } from "../select/select.js";
5
7
  import { triage } from "../triage.js";
6
- import { roleEffort } from "./agents.js";
7
8
  import { reviewContext } from "./context.js";
8
- import { runtimeGrouper } from "./helpers.js";
9
9
  import { rank } from "./matrix.js";
10
10
  import { newRunId } from "./run-id.js";
11
- export const GUIDELINES_PATH = "AGENTS.md";
11
+ const GUIDELINES_PATH = "AGENTS.md";
12
12
  export async function planReview(options, emit, signal) {
13
13
  const { vcs } = options;
14
14
  const readTrusted = options.readTrusted ?? ((path) => vcs.readFile(path));
15
15
  const changeRequest = await vcs.getChangeRequest();
16
16
  emit({ type: "run_started", runId: options.runId ?? newRunId(), changeRequest });
17
17
  const diffs = await vcs.getDiff();
18
- const decisions = selectFiles(diffs, options.selection ?? defaultSelectionPolicy);
18
+ const decisions = selectFiles(diffs, { ...defaultSelectionPolicy, ...options.selection });
19
19
  const selected = decisions.filter((d) => d.selected).map((d) => d.diff);
20
20
  const tier = triage(selected);
21
21
  emit({
@@ -32,7 +32,7 @@ export async function planReview(options, emit, signal) {
32
32
  const usage = [];
33
33
  const grouper = options.grouper ??
34
34
  (options.runtime
35
- ? runtimeGrouper(options.runtime, signal, (u) => usage.push(u), roleEffort("helper", options))
35
+ ? runtimeGrouper(options.runtime, signal, (u) => usage.push(u), roleCall("helper", options))
36
36
  : undefined);
37
37
  const widened = options.reviewOnly && options.priorTier && rank(tier) > rank(options.priorTier)
38
38
  ? { from: options.priorTier, to: tier }
@@ -59,8 +59,11 @@ export async function planReview(options, emit, signal) {
59
59
  ...(widened ? { widened } : {}),
60
60
  context: reviewContext(vcs, diffs),
61
61
  guidelines,
62
- repoRules: [...(options.rules ?? []), ...fileRules],
63
- memory: memoryText === undefined ? [] : parseMemory(memoryText),
62
+ repoRules: [
63
+ ...(options.rules ?? []),
64
+ ...fileRules.map((rule) => ({ ...rule, source: "repository" })),
65
+ ],
66
+ memory: mergeMemory(memoryText === undefined ? [] : parseMemory(memoryText), options.accountMemory ?? []),
64
67
  usage,
65
68
  warnings: bundled.warnings,
66
69
  };
@@ -1,8 +1,8 @@
1
1
  import type { Effort } from "../contracts.js";
2
2
  import type { ChangeRequest, RiskTier } from "../domain.js";
3
- import type { ReviewerDefinition } from "../review/reviewer.js";
4
3
  import type { FileDecision } from "../select/select.js";
5
- import { type ReviewerOverrides, type SkippedCell } from "./matrix.js";
4
+ import { type SkippedCell } from "./matrix.js";
5
+ import type { ReviewOptions } from "./options.js";
6
6
  import { type PlanOptions } from "./plan.js";
7
7
  export interface PreviewTask {
8
8
  taskId: string;
@@ -12,7 +12,20 @@ export interface PreviewTask {
12
12
  promptTokens: number;
13
13
  planPromptTokens?: number;
14
14
  effort?: Effort;
15
+ models?: string[];
16
+ inputCost?: InputCost;
15
17
  }
18
+ type InputCost = {
19
+ model: string;
20
+ status: "priced";
21
+ usd: number;
22
+ } | {
23
+ model: string;
24
+ status: "unpriced";
25
+ } | {
26
+ model: string;
27
+ status: "unknown";
28
+ };
16
29
  export interface ReviewPreview {
17
30
  changeRequest: ChangeRequest;
18
31
  tier: RiskTier;
@@ -32,13 +45,17 @@ export interface ReviewPreview {
32
45
  skipped: SkippedCell[];
33
46
  promptTokens: number;
34
47
  planCalls: number;
48
+ inputCost?: {
49
+ usd: number;
50
+ priced: number;
51
+ unpriced: number;
52
+ unknown: number;
53
+ };
35
54
  warnings: string[];
36
55
  }
37
- export type PreviewOptions = Omit<PlanOptions, "runtime"> & {
38
- reviewers?: readonly ReviewerDefinition[];
39
- reviewerOverrides?: ReviewerOverrides;
40
- ultra?: boolean;
41
- maxTasks?: number;
56
+ export type PreviewOptions = Omit<PlanOptions, "runtime"> & Omit<ReviewOptions, "vcs" | "runtime"> & {
57
+ inputPrice?: (model: string) => number | undefined;
42
58
  };
43
59
  export declare function previewReview(options: PreviewOptions): Promise<ReviewPreview>;
60
+ export {};
44
61
  //# sourceMappingURL=preview.d.ts.map
@@ -1,9 +1,9 @@
1
+ import { reviewerCall } from "../agent/settings.js";
1
2
  import { defaultBundlePolicy } from "../bundle/bundle.js";
2
3
  import { memoryFor } from "../memory/memory.js";
3
4
  import { buildReviewPrompt } from "../review/prompt.js";
4
5
  import { correctnessReviewer } from "../review/reviewers/correctness.js";
5
6
  import { resolveRules } from "../rules/resolve.js";
6
- import { reviewerEffort } from "./agents.js";
7
7
  import { isLargeBundle } from "./execute.js";
8
8
  import { planTasks } from "./matrix.js";
9
9
  import { planReview } from "./plan.js";
@@ -13,8 +13,8 @@ export async function previewReview(options) {
13
13
  const plan = await planReview(options, () => { }, new AbortController().signal);
14
14
  const reviewers = options.reviewers ?? [correctnessReviewer];
15
15
  const planned = planTasks(plan.bundles, reviewers, plan.tier, options.reviewerOverrides, {
16
- ultra: options.ultra === true,
17
- ...(options.maxTasks !== undefined ? { maxTasks: options.maxTasks } : {}),
16
+ ultra: options.mode?.ultra === true,
17
+ ...(options.limits?.maxTasks !== undefined ? { maxTasks: options.limits?.maxTasks } : {}),
18
18
  hasGuidelines: Boolean(plan.guidelines?.trim()),
19
19
  });
20
20
  const { cells } = planned;
@@ -38,14 +38,21 @@ export async function previewReview(options) {
38
38
  files,
39
39
  promptTokens: tokens(prompt),
40
40
  };
41
- const effort = reviewerEffort(cell.reviewer, options);
42
- if (effort !== undefined)
43
- task.effort = effort;
41
+ const call = reviewerCall(cell.reviewer, options);
42
+ if (call.effort !== undefined)
43
+ task.effort = call.effort;
44
+ const models = call.models ?? options.models?.[cell.reviewer.modelTier];
45
+ if (models?.length)
46
+ task.models = [...models];
44
47
  const key = `${cell.reviewer.id}\0${cell.bundle.label}`;
45
- if ((options.ultra || isLargeBundle(cell.bundle.files)) && !plannedBundles.has(key)) {
48
+ if ((options.mode?.ultra || isLargeBundle(cell.bundle.files)) && !plannedBundles.has(key)) {
46
49
  plannedBundles.add(key);
47
50
  task.planPromptTokens = tokens(buildReviewPrompt({ ...input, forPlanning: true }));
48
51
  }
52
+ const first = task.models?.[0];
53
+ if (first !== undefined && options.inputPrice) {
54
+ task.inputCost = inputCost(first, options.inputPrice(first), task.promptTokens + (task.planPromptTokens ?? 0));
55
+ }
49
56
  return task;
50
57
  });
51
58
  const policy = options.bundling ?? defaultBundlePolicy;
@@ -60,6 +67,7 @@ export async function previewReview(options) {
60
67
  skipped: planned.skipped,
61
68
  promptTokens: tasks.reduce((sum, t) => sum + t.promptTokens + (t.planPromptTokens ?? 0), 0),
62
69
  planCalls: tasks.filter((t) => t.planPromptTokens !== undefined).length,
70
+ ...(tasks.some((t) => t.inputCost) ? { inputCost: totalInputCost(tasks) } : {}),
63
71
  warnings: [
64
72
  ...plan.warnings,
65
73
  ...(planned.limited?.length
@@ -70,6 +78,22 @@ export async function previewReview(options) {
70
78
  ],
71
79
  };
72
80
  }
81
+ function inputCost(model, price, promptTokens) {
82
+ if (price === undefined)
83
+ return { model, status: "unknown" };
84
+ if (price === 0)
85
+ return { model, status: "unpriced" };
86
+ return { model, status: "priced", usd: (promptTokens * price) / 1_000_000 };
87
+ }
88
+ function totalInputCost(tasks) {
89
+ const total = { usd: 0, priced: 0, unpriced: 0, unknown: 0 };
90
+ for (const { inputCost } of tasks) {
91
+ if (inputCost?.status === "priced")
92
+ total.usd += inputCost.usd;
93
+ total[inputCost?.status ?? "unknown"] += 1;
94
+ }
95
+ return total;
96
+ }
73
97
  // Four characters per token: an estimate, not a tokenizer.
74
98
  function tokens(prompt) {
75
99
  return Math.ceil((prompt.system.length + prompt.user.length) / 4);
@@ -1,24 +1,15 @@
1
- import type { AgentRuntime, AppliedSampling, Effort, ModelTier, Sampling } from "../contracts.js";
1
+ import type { ResolvedAgent, ReviewerOverrides } from "../agent/settings.js";
2
+ import type { AgentRuntime, AppliedSampling, Sampling } from "../contracts.js";
3
+ import type { AgentProvenance, RunProvenance } from "../report/provenance.js";
2
4
  import type { ReviewerDefinition } from "../review/reviewer.js";
3
- import type { ResolvedAgent } from "./agents.js";
4
- import type { ReviewerOverrides } from "./matrix.js";
5
- export interface RunProvenance {
6
- ocraVersion: string;
7
- promptHash: string;
8
- configHash: string;
9
- sampling: AppliedSampling;
10
- agents?: Record<string, AgentProvenance>;
11
- }
12
- export interface AgentProvenance {
13
- tier: ModelTier;
14
- effort?: Effort;
15
- applied?: boolean;
16
- notApplied?: (keyof Sampling)[];
17
- }
5
+ import type { SourcedRule } from "../rules/repo-rules.js";
18
6
  export interface ProvenanceInput {
19
7
  ocraVersion: string;
20
8
  configHash: string;
21
9
  sampling?: Sampling;
10
+ accountSettings?: {
11
+ version: string | null;
12
+ };
22
13
  }
23
14
  export declare function stableHash(value: unknown): string;
24
15
  export declare function promptHash(reviewers: readonly ReviewerDefinition[], overrides?: ReviewerOverrides): string;
@@ -26,5 +17,5 @@ export declare function appliedSampling(runtime: {
26
17
  readonly sampling?: AppliedSampling;
27
18
  }, requested?: Sampling): AppliedSampling;
28
19
  export declare function agentProvenance(agents: readonly ResolvedAgent[], runtime: Pick<AgentRuntime, "appliedTo">): Record<string, AgentProvenance>;
29
- export declare function runProvenance(input: ProvenanceInput, runtime: Pick<AgentRuntime, "sampling" | "appliedTo">, reviewers: readonly ReviewerDefinition[], agents: readonly ResolvedAgent[], overrides?: ReviewerOverrides): RunProvenance;
20
+ export declare function runProvenance(input: ProvenanceInput, runtime: Pick<AgentRuntime, "sampling" | "appliedTo">, reviewers: readonly ReviewerDefinition[], agents: readonly ResolvedAgent[], overrides?: ReviewerOverrides, rules?: readonly SourcedRule[]): RunProvenance;
30
21
  //# sourceMappingURL=provenance.d.ts.map
@@ -1,6 +1,6 @@
1
- import { createHash } from "node:crypto";
2
1
  import { RELOCATE_SYSTEM_PROMPT } from "../anchor/relocate.js";
3
2
  import { GROUPING_SYSTEM_PROMPT } from "../bundle/grouping.js";
3
+ import { shortHash } from "../hash.js";
4
4
  import { JUDGE_SYSTEM_PROMPT } from "../judge/prompt.js";
5
5
  import { PLAN_SYSTEM_PROMPT } from "../review/plan-phase.js";
6
6
  import { buildReviewPrompt } from "../review/prompt.js";
@@ -8,7 +8,7 @@ import { VERIFY_SYSTEM_PROMPT } from "../verify/prompt.js";
8
8
  // A short digest of a JSON value, the same whatever order its keys were
9
9
  // written in.
10
10
  export function stableHash(value) {
11
- return createHash("sha256").update(canonicalJson(value)).digest("hex").slice(0, 16);
11
+ return shortHash(canonicalJson(value));
12
12
  }
13
13
  function canonicalJson(value) {
14
14
  if (Array.isArray(value))
@@ -58,18 +58,19 @@ export function appliedSampling(runtime, requested = {}) {
58
58
  }
59
59
  // A runtime that cannot say what it applied applied no effort.
60
60
  export function agentProvenance(agents, runtime) {
61
- const entries = agents.map(({ id, tier, effort }) => {
61
+ const entries = agents.map(({ id, tier, effort, models }) => {
62
+ const base = { tier, ...(models ? { models: [...models] } : {}) };
62
63
  if (effort === undefined)
63
- return [id, { tier }];
64
+ return [id, base];
64
65
  if (!runtime.appliedTo)
65
- return [id, { tier, effort, applied: false }];
66
+ return [id, { ...base, effort, applied: false }];
66
67
  const applied = runtime.appliedTo(id);
67
68
  if (!applied)
68
- return [id, { tier, effort }];
69
+ return [id, { ...base, effort }];
69
70
  return [
70
71
  id,
71
72
  {
72
- tier,
73
+ ...base,
73
74
  effort,
74
75
  applied: applied.effort,
75
76
  ...(applied.notApplied?.length ? { notApplied: [...applied.notApplied] } : {}),
@@ -78,13 +79,24 @@ export function agentProvenance(agents, runtime) {
78
79
  });
79
80
  return Object.fromEntries(entries);
80
81
  }
81
- export function runProvenance(input, runtime, reviewers, agents, overrides) {
82
+ export function runProvenance(input, runtime, reviewers, agents, overrides, rules = []) {
82
83
  return {
83
84
  ocraVersion: input.ocraVersion,
84
85
  promptHash: promptHash(reviewers, overrides),
85
86
  configHash: input.configHash,
86
87
  sampling: appliedSampling(runtime, input.sampling),
87
88
  agents: agentProvenance(agents, runtime),
89
+ ...(rules.length > 0 ? { rules: rules.map(ruleProvenance) } : {}),
90
+ ...(input.accountSettings
91
+ ? { accountSettings: { version: input.accountSettings.version } }
92
+ : {}),
93
+ };
94
+ }
95
+ function ruleProvenance({ path, rule, source }) {
96
+ return {
97
+ path: typeof path === "string" ? [path] : [...path],
98
+ rule,
99
+ ...(source ? { source } : {}),
88
100
  };
89
101
  }
90
102
  //# sourceMappingURL=provenance.js.map
@@ -1,47 +1,5 @@
1
- import type { AnchorContext } from "../anchor/anchor.js";
2
- import type { BundlePolicy } from "../bundle/bundle.js";
3
- import type { FileGrouper } from "../bundle/grouping.js";
4
- import type { AgentRuntime, VcsAdapter } from "../contracts.js";
5
- import type { ReviewerDefinition } from "../review/reviewer.js";
6
- import type { RepoRule } from "../rules/repo-rules.js";
7
- import type { SarifLog } from "../sarif/schema.js";
8
- import type { SelectionPolicy } from "../select/select.js";
9
- import { type RoleSettings, type TierEfforts } from "./agents.js";
10
- import { type ReviewerOverrides } from "./matrix.js";
11
- import { type ProvenanceInput } from "./provenance.js";
12
- import { type ReviewEvent, type ReviewReport } from "./report.js";
13
- export { GUIDELINES_PATH } from "./plan.js";
14
- export interface ReviewOptions {
15
- vcs: VcsAdapter;
16
- runtime: AgentRuntime;
17
- reviewers?: readonly ReviewerDefinition[];
18
- reviewerOverrides?: ReviewerOverrides;
19
- effort?: TierEfforts;
20
- roles?: RoleSettings;
21
- rules?: readonly RepoRule[];
22
- readTrusted?: (path: string) => Promise<string | undefined>;
23
- selection?: SelectionPolicy;
24
- concurrency?: number;
25
- taskTimeoutMs?: number;
26
- runTimeoutMs?: number;
27
- verify?: boolean;
28
- judge?: boolean;
29
- maxCostUsd?: number;
30
- maxTasks?: number;
31
- fullReview?: boolean;
32
- ultra?: boolean;
33
- sarif?: readonly SarifLog[];
34
- runId?: string;
35
- provenance?: ProvenanceInput;
36
- signal?: AbortSignal;
37
- onEvent?: (event: ReviewEvent) => void;
38
- }
39
- export interface ReviewHooks {
40
- bundling?: BundlePolicy;
41
- grouper?: FileGrouper;
42
- relocate?: AnchorContext["relocate"] | false;
43
- abortGraceMs?: number;
44
- }
1
+ import type { ReviewReport } from "../report/report.js";
2
+ import { type ReviewHooks, type ReviewOptions } from "./options.js";
45
3
  export declare function review(options: ReviewOptions): Promise<ReviewReport>;
46
4
  export declare function reviewWithHooks(options: ReviewOptions & ReviewHooks): Promise<ReviewReport>;
47
5
  //# sourceMappingURL=run.d.ts.map