@claudexor/review 1.0.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.
@@ -0,0 +1,95 @@
1
+ import { isAbsolute, relative, resolve } from "node:path";
2
+ function hasEvidence(f) {
3
+ return (f.evidence.files.length > 0 ||
4
+ f.evidence.diff_hunks.length > 0 ||
5
+ f.evidence.commands.length > 0 ||
6
+ f.evidence.logs.length > 0);
7
+ }
8
+ function isSameOrInside(parent, target) {
9
+ const rel = relative(resolve(parent), resolve(target));
10
+ const firstPart = rel.split(/[\\/]+/)[0];
11
+ return rel === "" || (!!rel && firstPart !== ".." && !isAbsolute(rel));
12
+ }
13
+ function hasTraversalSegment(pathValue) {
14
+ return pathValue.split(/[\\/]+/).some((part) => part === "..");
15
+ }
16
+ function isSafeRelativeEvidencePath(pathValue, options) {
17
+ if (!pathValue || hasTraversalSegment(pathValue))
18
+ return false;
19
+ if (isAbsolute(pathValue))
20
+ return false;
21
+ const roots = [options.candidateRoot, options.evidenceDir].filter((value) => typeof value === "string" && value.length > 0);
22
+ if (roots.length === 0)
23
+ return true;
24
+ return roots.some((root) => isSameOrInside(root, resolve(root, pathValue)));
25
+ }
26
+ function validateEvidence(evidence, options) {
27
+ let invalidPathCount = 0;
28
+ const files = evidence.files.filter((file) => {
29
+ const ok = isSafeRelativeEvidencePath(file.path, options);
30
+ if (!ok)
31
+ invalidPathCount++;
32
+ return ok;
33
+ });
34
+ const logs = evidence.logs.filter((log) => {
35
+ const ok = isSafeRelativeEvidencePath(log.path, options);
36
+ if (!ok)
37
+ invalidPathCount++;
38
+ return ok;
39
+ });
40
+ return {
41
+ evidence: {
42
+ files,
43
+ logs,
44
+ diff_hunks: evidence.diff_hunks,
45
+ commands: evidence.commands,
46
+ },
47
+ invalidPathCount,
48
+ };
49
+ }
50
+ /**
51
+ * Deterministic revalidation (no LLM): enforces the evidence invariants that
52
+ * always hold — no evidence -> cannot block; out-of-scope/insufficient pass
53
+ * through; a NEEDS_HUMAN escalation stays a blocking human gate.
54
+ */
55
+ export function deterministicDecision(f, options = {}) {
56
+ if (["fixed", "rebutted", "accepted_risk", "duplicate"].includes(f.status)) {
57
+ return { status: f.status };
58
+ }
59
+ if (f.severity === "OUT_OF_SCOPE")
60
+ return { status: "out_of_scope" };
61
+ if (f.severity === "INSUFFICIENT_EVIDENCE")
62
+ return { status: "insufficient_evidence" };
63
+ // A reviewer escalation to a human BLOCKS until a human decides — it must
64
+ // never silently downgrade to a non-blocking accepted risk.
65
+ if (f.severity === "NEEDS_HUMAN")
66
+ return { status: "accepted", note: "human decision required" };
67
+ if (f.severity === "BLOCK" || f.severity === "FIX_FIRST") {
68
+ const validated = validateEvidence(f.evidence, options);
69
+ const candidate = { ...f, evidence: validated.evidence };
70
+ if (!hasEvidence(candidate)) {
71
+ return {
72
+ status: "insufficient_evidence",
73
+ note: validated.invalidPathCount > 0
74
+ ? "invalid evidence paths -> cannot block"
75
+ : "no evidence -> cannot block",
76
+ };
77
+ }
78
+ }
79
+ return { status: "accepted" };
80
+ }
81
+ /**
82
+ * Revalidate every finding deterministically. Each finding's status is recorded;
83
+ * the evidence-free BLOCK/FIX_FIRST invariant is applied so a reviewer cannot
84
+ * leave an evidence-free finding in a blocking state.
85
+ */
86
+ export async function revalidateFindings(findings, options = {}) {
87
+ const out = [];
88
+ for (const f of findings) {
89
+ const validated = validateEvidence(f.evidence, options);
90
+ const d = deterministicDecision(f, options);
91
+ out.push({ ...f, evidence: validated.evidence, status: d.status, revalidation_note: d.note });
92
+ }
93
+ return out;
94
+ }
95
+ //# sourceMappingURL=revalidate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"revalidate.js","sourceRoot":"","sources":["../src/revalidate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkB1D,SAAS,WAAW,CAAC,CAAgB;IACnC,OAAO,CACL,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAC3B,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QAChC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QAC9B,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAC3B,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,MAAc,EAAE,MAAc;IACpD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,OAAO,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,0BAA0B,CAAC,SAAiB,EAAE,OAA0B;IAC/E,IAAI,CAAC,SAAS,IAAI,mBAAmB,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAC/D,CAAC,KAAK,EAAmB,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAC1E,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,gBAAgB,CACvB,QAAyB,EACzB,OAA0B;IAE1B,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QAC3C,MAAM,EAAE,GAAG,0BAA0B,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,EAAE;YAAE,gBAAgB,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QACxC,MAAM,EAAE,GAAG,0BAA0B,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,EAAE;YAAE,gBAAgB,EAAE,CAAC;QAC5B,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE;YACR,KAAK;YACL,IAAI;YACJ,UAAU,EAAE,QAAQ,CAAC,UAAU;YAC/B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;SAC5B;QACD,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,CAAgB,EAChB,UAA6B,EAAE;IAE/B,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;IACD,IAAI,CAAC,CAAC,QAAQ,KAAK,cAAc;QAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IACrE,IAAI,CAAC,CAAC,QAAQ,KAAK,uBAAuB;QAAE,OAAO,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;IACvF,0EAA0E;IAC1E,4DAA4D;IAC5D,IAAI,CAAC,CAAC,QAAQ,KAAK,aAAa;QAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,yBAAyB,EAAE,CAAC;IACjG,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;QACzD,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,CAAC;QACzD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,OAAO;gBACL,MAAM,EAAE,uBAAuB;gBAC/B,IAAI,EACF,SAAS,CAAC,gBAAgB,GAAG,CAAC;oBAC5B,CAAC,CAAC,wCAAwC;oBAC1C,CAAC,CAAC,6BAA6B;aACpC,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAyB,EACzB,UAA6B,EAAE;IAE/B,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,gBAAgB,CAAC,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACxD,MAAM,CAAC,GAAG,qBAAqB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,85 @@
1
+ import { type HarnessAdapter } from "@claudexor/core";
2
+ import type { AuthPreference, EffortHint, ProviderFamily, ReviewFinding, RouteProof } from "@claudexor/schema";
3
+ import { FallbackReason } from "@claudexor/schema";
4
+ export interface ReviewerSpec {
5
+ adapter: HarnessAdapter;
6
+ providerFamily: ProviderFamily;
7
+ requestedModel?: string | null;
8
+ requestedEffort?: EffortHint | null;
9
+ authPreference?: AuthPreference | null;
10
+ }
11
+ export interface ReviewCandidateInput {
12
+ /** Anonymized label (e.g. "Candidate A") — never reveal which model produced it. */
13
+ candidateLabel: string;
14
+ diff: string;
15
+ evidenceDir: string;
16
+ /** Persistent local artifact directory for raw reviewer telemetry. Defaults under evidenceDir for tests. */
17
+ artifactsDir?: string;
18
+ cwd: string;
19
+ reviewers: ReviewerSpec[];
20
+ reviewerTimeoutMs?: number;
21
+ transientRetryPolicy?: TransientRetryPolicy;
22
+ /** Child-env composition for the reviewer harnesses (defaults to mirror_native).
23
+ * Reviewer runs are paid harness children too, so they must honor the configured
24
+ * env isolation (clean) the same way candidate runs do. */
25
+ envInheritance?: "mirror_native" | "clean";
26
+ /** Scoped harness HOME/config-dir env (HOME, CODEX_HOME, CLAUDE_CONFIG_DIR, …)
27
+ * for the reviewer children, so a reviewer's native state (codex session
28
+ * rollouts, claude config) is contained in a per-review scoped home instead of
29
+ * the operator's real ~/.codex / ~/.claude (CLAUDEXOR_BIBLE §6). The codex
30
+ * route-proof transcript is read from this same CODEX_HOME, so route proof still
31
+ * verifies. Adapters seed auth into these dirs. */
32
+ env?: Record<string, string>;
33
+ signal?: AbortSignal;
34
+ onReviewerEvent?: (event: ReviewerProgressEvent) => void;
35
+ }
36
+ export interface ReviewCandidateResult {
37
+ findings: ReviewFinding[];
38
+ routeProofs: RouteProof[];
39
+ reviewerRequests: {
40
+ harness_id: string;
41
+ provider_family: ProviderFamily;
42
+ requested_model: string | null;
43
+ requested_effort: string | null;
44
+ }[];
45
+ /** True only when >=2 distinct provider families returned parseable JSON. Not a route-proof claim. */
46
+ crossFamilyHealthy: boolean;
47
+ healthyProviders: ProviderFamily[];
48
+ /** True only when >=2 distinct provider families have verified route proofs. */
49
+ crossFamilyVerified: boolean;
50
+ distinctProviders: ProviderFamily[];
51
+ /** Observed reviewer panel spend (budget truth: reviewers are paid work). */
52
+ reviewSpendUsd: number;
53
+ reviewSpendEstimated: boolean;
54
+ }
55
+ export interface TransientRetryPolicy {
56
+ maxRetries: number;
57
+ initialDelayMs: number;
58
+ maxDelayMs: number;
59
+ }
60
+ export interface ReviewerProgressEvent {
61
+ type: "reviewer.started" | "reviewer.first_event" | "reviewer.auth_switched" | "reviewer.completed" | "reviewer.timed_out" | "reviewer.failed";
62
+ harness_id: string;
63
+ provider_family: ProviderFamily;
64
+ requested_model: string | null;
65
+ requested_effort: EffortHint | null;
66
+ observed_model?: string | null;
67
+ observed_source?: RouteProof["observed"]["evidence_source"];
68
+ route_proof_status?: RouteProof["status"];
69
+ from_auth_mode?: string;
70
+ to_auth_mode?: string;
71
+ reason?: FallbackReason;
72
+ artifact_dir: string;
73
+ at: string;
74
+ duration_ms?: number;
75
+ message?: string;
76
+ }
77
+ /**
78
+ * Cross-family review of one anonymized candidate. Each reviewer runs its review
79
+ * intent and emits JSON findings; we attach route proofs and verify the
80
+ * reviewers span >= 2 distinct provider families.
81
+ */
82
+ export declare function reviewCandidate(input: ReviewCandidateInput): Promise<ReviewCandidateResult>;
83
+ /** Test-only alias for the preserve-set extractor. */
84
+ export declare function __testExtractDiffTouchedPaths(diff: string): Set<string>;
85
+ //# sourceMappingURL=reviewEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewEngine.d.ts","sourceRoot":"","sources":["../src/reviewEngine.ts"],"names":[],"mappings":"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"}