@guilz-dev/belay 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/LICENSE +21 -0
- package/README.md +268 -0
- package/agent-belay-logo.png +0 -0
- package/dist/adapters/claude/adapter.d.ts +7 -0
- package/dist/adapters/claude/adapter.js +114 -0
- package/dist/adapters/claude/hooks.d.ts +13 -0
- package/dist/adapters/claude/hooks.js +49 -0
- package/dist/adapters/claude/runtime-entry.d.ts +4 -0
- package/dist/adapters/claude/runtime-entry.js +260 -0
- package/dist/adapters/codex/adapter.d.ts +7 -0
- package/dist/adapters/codex/adapter.js +73 -0
- package/dist/adapters/codex/hooks.d.ts +21 -0
- package/dist/adapters/codex/hooks.js +78 -0
- package/dist/adapters/codex/runtime-entry.d.ts +4 -0
- package/dist/adapters/codex/runtime-entry.js +237 -0
- package/dist/adapters/cursor/adapter.d.ts +7 -0
- package/dist/adapters/cursor/adapter.js +29 -0
- package/dist/adapters/cursor/hooks.d.ts +2 -0
- package/dist/adapters/cursor/hooks.js +26 -0
- package/dist/adapters/cursor/runtime-entry.d.ts +4 -0
- package/dist/adapters/cursor/runtime-entry.js +143 -0
- package/dist/adapters/layouts/claude.d.ts +2 -0
- package/dist/adapters/layouts/claude.js +40 -0
- package/dist/adapters/layouts/codex.d.ts +2 -0
- package/dist/adapters/layouts/codex.js +43 -0
- package/dist/adapters/layouts/cursor.d.ts +2 -0
- package/dist/adapters/layouts/cursor.js +40 -0
- package/dist/adapters/layouts/index.d.ts +7 -0
- package/dist/adapters/layouts/index.js +23 -0
- package/dist/adapters/layouts/protected-paths.d.ts +3 -0
- package/dist/adapters/layouts/protected-paths.js +15 -0
- package/dist/adapters/layouts/scope.d.ts +19 -0
- package/dist/adapters/layouts/scope.js +86 -0
- package/dist/adapters/layouts/types.d.ts +14 -0
- package/dist/adapters/layouts/types.js +1 -0
- package/dist/adapters/registry.d.ts +4 -0
- package/dist/adapters/registry.js +14 -0
- package/dist/adapters/shared/gate-runtime.d.ts +51 -0
- package/dist/adapters/shared/gate-runtime.js +518 -0
- package/dist/adapters/shared/repo-root.d.ts +2 -0
- package/dist/adapters/shared/repo-root.js +17 -0
- package/dist/adapters/types.d.ts +19 -0
- package/dist/adapters/types.js +1 -0
- package/dist/branding.d.ts +3 -0
- package/dist/branding.js +3 -0
- package/dist/bundle/claude-runtime.mjs +5323 -0
- package/dist/bundle/codex-runtime.mjs +5310 -0
- package/dist/bundle/cursor-runtime.mjs +5208 -0
- package/dist/cleanup-orphans.d.ts +7 -0
- package/dist/cleanup-orphans.js +59 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +631 -0
- package/dist/commands/approve.d.ts +14 -0
- package/dist/commands/approve.js +65 -0
- package/dist/commands/audit.d.ts +59 -0
- package/dist/commands/audit.js +132 -0
- package/dist/commands/classify-for-report.d.ts +9 -0
- package/dist/commands/classify-for-report.js +85 -0
- package/dist/commands/doctor.d.ts +3 -0
- package/dist/commands/doctor.js +366 -0
- package/dist/commands/dogfood.d.ts +5 -0
- package/dist/commands/dogfood.js +71 -0
- package/dist/commands/explain.d.ts +3 -0
- package/dist/commands/explain.js +133 -0
- package/dist/commands/health-snapshot.d.ts +2 -0
- package/dist/commands/health-snapshot.js +166 -0
- package/dist/commands/init-wizard.d.ts +16 -0
- package/dist/commands/init-wizard.js +50 -0
- package/dist/commands/metrics.d.ts +7 -0
- package/dist/commands/metrics.js +89 -0
- package/dist/commands/recover.d.ts +3 -0
- package/dist/commands/recover.js +105 -0
- package/dist/commands/report.d.ts +3 -0
- package/dist/commands/report.js +65 -0
- package/dist/commands/revoke.d.ts +5 -0
- package/dist/commands/revoke.js +22 -0
- package/dist/commands/simulate.d.ts +14 -0
- package/dist/commands/simulate.js +55 -0
- package/dist/commands/status.d.ts +5 -0
- package/dist/commands/status.js +107 -0
- package/dist/config-io.d.ts +23 -0
- package/dist/config-io.js +180 -0
- package/dist/conformance/guarantee-table.d.ts +14 -0
- package/dist/conformance/guarantee-table.js +95 -0
- package/dist/conformance/types.d.ts +6 -0
- package/dist/conformance/types.js +1 -0
- package/dist/core/approval-service.d.ts +26 -0
- package/dist/core/approval-service.js +41 -0
- package/dist/core/approval-token.d.ts +11 -0
- package/dist/core/approval-token.js +61 -0
- package/dist/core/approval.d.ts +19 -0
- package/dist/core/approval.js +58 -0
- package/dist/core/audit-analysis.d.ts +10 -0
- package/dist/core/audit-analysis.js +147 -0
- package/dist/core/audit-metrics.d.ts +51 -0
- package/dist/core/audit-metrics.js +155 -0
- package/dist/core/audit-query.d.ts +11 -0
- package/dist/core/audit-query.js +142 -0
- package/dist/core/audit-summary.d.ts +33 -0
- package/dist/core/audit-summary.js +111 -0
- package/dist/core/audit-types.d.ts +65 -0
- package/dist/core/audit-types.js +2 -0
- package/dist/core/capability/allowlist.d.ts +10 -0
- package/dist/core/capability/allowlist.js +53 -0
- package/dist/core/capability/broker.d.ts +17 -0
- package/dist/core/capability/broker.js +29 -0
- package/dist/core/capability/index.d.ts +5 -0
- package/dist/core/capability/index.js +4 -0
- package/dist/core/capability/paths.d.ts +1 -0
- package/dist/core/capability/paths.js +20 -0
- package/dist/core/capability/reasons.d.ts +2 -0
- package/dist/core/capability/reasons.js +4 -0
- package/dist/core/capability/types.d.ts +10 -0
- package/dist/core/capability/types.js +1 -0
- package/dist/core/capability-approval.d.ts +28 -0
- package/dist/core/capability-approval.js +43 -0
- package/dist/core/classify-subagent.d.ts +2 -0
- package/dist/core/classify-subagent.js +69 -0
- package/dist/core/classify-tool.d.ts +3 -0
- package/dist/core/classify-tool.js +311 -0
- package/dist/core/config-layers.d.ts +23 -0
- package/dist/core/config-layers.js +59 -0
- package/dist/core/config.d.ts +219 -0
- package/dist/core/config.js +720 -0
- package/dist/core/control-plane-isolation.d.ts +10 -0
- package/dist/core/control-plane-isolation.js +83 -0
- package/dist/core/custom-command-match.d.ts +2 -0
- package/dist/core/custom-command-match.js +8 -0
- package/dist/core/egress/allowlist.d.ts +7 -0
- package/dist/core/egress/allowlist.js +33 -0
- package/dist/core/egress/env.d.ts +3 -0
- package/dist/core/egress/env.js +17 -0
- package/dist/core/egress/fingerprint.d.ts +3 -0
- package/dist/core/egress/fingerprint.js +35 -0
- package/dist/core/egress/policy.d.ts +8 -0
- package/dist/core/egress/policy.js +47 -0
- package/dist/core/egress/proxy-server.d.ts +21 -0
- package/dist/core/egress/proxy-server.js +263 -0
- package/dist/core/egress/types.d.ts +25 -0
- package/dist/core/egress/types.js +1 -0
- package/dist/core/egress-approval.d.ts +48 -0
- package/dist/core/egress-approval.js +129 -0
- package/dist/core/fingerprint.d.ts +6 -0
- package/dist/core/fingerprint.js +24 -0
- package/dist/core/gate-contract.d.ts +48 -0
- package/dist/core/gate-contract.js +50 -0
- package/dist/core/gate-engine.d.ts +20 -0
- package/dist/core/gate-engine.js +172 -0
- package/dist/core/glob.d.ts +1 -0
- package/dist/core/glob.js +39 -0
- package/dist/core/index.d.ts +19 -0
- package/dist/core/index.js +15 -0
- package/dist/core/integrity.d.ts +15 -0
- package/dist/core/integrity.js +68 -0
- package/dist/core/judge-api-key.d.ts +4 -0
- package/dist/core/judge-api-key.js +11 -0
- package/dist/core/judge-config.d.ts +29 -0
- package/dist/core/judge-config.js +85 -0
- package/dist/core/judge-doctor.d.ts +7 -0
- package/dist/core/judge-doctor.js +124 -0
- package/dist/core/judgment.d.ts +6 -0
- package/dist/core/judgment.js +38 -0
- package/dist/core/notify.d.ts +13 -0
- package/dist/core/notify.js +44 -0
- package/dist/core/path-utils.d.ts +12 -0
- package/dist/core/path-utils.js +107 -0
- package/dist/core/reclassify.d.ts +15 -0
- package/dist/core/reclassify.js +82 -0
- package/dist/core/recover-advice.d.ts +30 -0
- package/dist/core/recover-advice.js +177 -0
- package/dist/core/recover-git-probe.d.ts +8 -0
- package/dist/core/recover-git-probe.js +50 -0
- package/dist/core/recover-select.d.ts +10 -0
- package/dist/core/recover-select.js +60 -0
- package/dist/core/scrub.d.ts +3 -0
- package/dist/core/scrub.js +87 -0
- package/dist/core/shell-substitution.d.ts +6 -0
- package/dist/core/shell-substitution.js +130 -0
- package/dist/core/shell-tokenizer.d.ts +5 -0
- package/dist/core/shell-tokenizer.js +129 -0
- package/dist/core/shell-unparseable.d.ts +4 -0
- package/dist/core/shell-unparseable.js +96 -0
- package/dist/core/transactional/diff-evaluator.d.ts +2 -0
- package/dist/core/transactional/diff-evaluator.js +84 -0
- package/dist/core/transactional/eligibility.d.ts +4 -0
- package/dist/core/transactional/eligibility.js +44 -0
- package/dist/core/transactional/git-worktree.d.ts +13 -0
- package/dist/core/transactional/git-worktree.js +189 -0
- package/dist/core/transactional/index.d.ts +5 -0
- package/dist/core/transactional/index.js +4 -0
- package/dist/core/transactional/reasons.d.ts +4 -0
- package/dist/core/transactional/reasons.js +8 -0
- package/dist/core/transactional/runner.d.ts +2 -0
- package/dist/core/transactional/runner.js +113 -0
- package/dist/core/transactional/types.d.ts +46 -0
- package/dist/core/transactional/types.js +1 -0
- package/dist/core/types.d.ts +90 -0
- package/dist/core/types.js +1 -0
- package/dist/core/v2/adapter.d.ts +14 -0
- package/dist/core/v2/adapter.js +118 -0
- package/dist/core/v2/containment.d.ts +19 -0
- package/dist/core/v2/containment.js +91 -0
- package/dist/core/v2/egress-classify.d.ts +7 -0
- package/dist/core/v2/egress-classify.js +216 -0
- package/dist/core/v2/fingerprint.d.ts +1 -0
- package/dist/core/v2/fingerprint.js +4 -0
- package/dist/core/v2/index.d.ts +12 -0
- package/dist/core/v2/index.js +10 -0
- package/dist/core/v2/judge-audit.d.ts +2 -0
- package/dist/core/v2/judge-audit.js +15 -0
- package/dist/core/v2/judge-factory.d.ts +25 -0
- package/dist/core/v2/judge-factory.js +75 -0
- package/dist/core/v2/judge-outbound.d.ts +12 -0
- package/dist/core/v2/judge-outbound.js +73 -0
- package/dist/core/v2/judge.d.ts +47 -0
- package/dist/core/v2/judge.js +264 -0
- package/dist/core/v2/launcher-resolve.d.ts +12 -0
- package/dist/core/v2/launcher-resolve.js +190 -0
- package/dist/core/v2/overrides.d.ts +7 -0
- package/dist/core/v2/overrides.js +37 -0
- package/dist/core/v2/parser.d.ts +21 -0
- package/dist/core/v2/parser.js +213 -0
- package/dist/core/v2/types.d.ts +67 -0
- package/dist/core/v2/types.js +1 -0
- package/dist/core/v2/verdict.d.ts +2 -0
- package/dist/core/v2/verdict.js +699 -0
- package/dist/corpus/evaluate.d.ts +24 -0
- package/dist/corpus/evaluate.js +69 -0
- package/dist/defaults.d.ts +18 -0
- package/dist/defaults.js +155 -0
- package/dist/egress-daemon.d.ts +1 -0
- package/dist/egress-daemon.js +52 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +15 -0
- package/dist/installer/bootstrap.d.ts +5 -0
- package/dist/installer/bootstrap.js +61 -0
- package/dist/installer/runtime-artifacts.d.ts +3 -0
- package/dist/installer/runtime-artifacts.js +23 -0
- package/dist/installer/scope-config.d.ts +8 -0
- package/dist/installer/scope-config.js +25 -0
- package/dist/installer.d.ts +22 -0
- package/dist/installer.js +169 -0
- package/dist/node-resolution.d.ts +8 -0
- package/dist/node-resolution.js +237 -0
- package/dist/operational-insights.d.ts +19 -0
- package/dist/operational-insights.js +24 -0
- package/dist/presets.d.ts +4 -0
- package/dist/presets.js +95 -0
- package/dist/services/egress-service.d.ts +57 -0
- package/dist/services/egress-service.js +334 -0
- package/dist/services/sandbox-service.d.ts +38 -0
- package/dist/services/sandbox-service.js +95 -0
- package/dist/templates.d.ts +7 -0
- package/dist/templates.js +56 -0
- package/dist/types.d.ts +230 -0
- package/dist/types.js +1 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +65 -0
- package/skills/belay/SKILL.md +52 -0
- package/skills/belay/belay-approve.md +7 -0
- package/skills/belay/belay-explain.md +11 -0
- package/skills/belay/belay-recover.md +13 -0
- package/skills/belay/belay-report.md +7 -0
- package/skills/belay/belay-status.md +9 -0
- package/skills/belay/belay-why.md +11 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { FsScopeAllowlistFile } from './capability/types.js';
|
|
2
|
+
export type BelayMode = 'enforce' | 'audit';
|
|
3
|
+
export type HookVerdict = 'allow' | 'allow_flagged' | 'deny_pending_approval';
|
|
4
|
+
export type Reversibility = 'reversible' | 'recoverable_with_cost' | 'irreversible';
|
|
5
|
+
export interface Assessment {
|
|
6
|
+
reversibility: Reversibility;
|
|
7
|
+
external: boolean;
|
|
8
|
+
blastRadius: string;
|
|
9
|
+
confidence: number;
|
|
10
|
+
signals: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface V2TraceFields {
|
|
13
|
+
location: string;
|
|
14
|
+
opacity: string;
|
|
15
|
+
effect: string;
|
|
16
|
+
confidence: string;
|
|
17
|
+
would: string;
|
|
18
|
+
by: string;
|
|
19
|
+
commandRedacted?: string;
|
|
20
|
+
commandFingerprint?: string;
|
|
21
|
+
signals?: string[];
|
|
22
|
+
judgeProvider?: 'openai-compatible' | 'ollama' | 'fallback';
|
|
23
|
+
judgeModelRequested?: string;
|
|
24
|
+
judgeModelResolved?: string;
|
|
25
|
+
judgeLatencyMs?: number;
|
|
26
|
+
judgeOutboundRedacted?: boolean;
|
|
27
|
+
judgeFallbackReason?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ClassifyResult {
|
|
30
|
+
verdict: HookVerdict;
|
|
31
|
+
reason: string;
|
|
32
|
+
fingerprint: string;
|
|
33
|
+
assessment: Assessment;
|
|
34
|
+
normalizedCommand?: string;
|
|
35
|
+
summary?: string;
|
|
36
|
+
v2?: V2TraceFields;
|
|
37
|
+
}
|
|
38
|
+
export type UnknownLocalEffectPolicy = 'allow_flagged' | 'deny';
|
|
39
|
+
export type UnparseableShellPolicy = 'allow_flagged' | 'deny';
|
|
40
|
+
export type ControlPlaneIntegrity = 'hash-pinned' | 'none';
|
|
41
|
+
export interface ScrubOptions {
|
|
42
|
+
maskApprovalIds?: boolean;
|
|
43
|
+
maskBearerTokens?: boolean;
|
|
44
|
+
maskAuthHeaders?: boolean;
|
|
45
|
+
maskKeyValueSecrets?: boolean;
|
|
46
|
+
maskHighEntropyStrings?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface ConfidenceThresholds {
|
|
49
|
+
allow: number;
|
|
50
|
+
flag: number;
|
|
51
|
+
}
|
|
52
|
+
export interface ClassifierOptions {
|
|
53
|
+
strictChains?: boolean;
|
|
54
|
+
customExternalCommands?: string[];
|
|
55
|
+
customAllowCommands?: string[];
|
|
56
|
+
sensitivePaths?: string[];
|
|
57
|
+
unknownLocalEffect?: UnknownLocalEffectPolicy;
|
|
58
|
+
unparseableShell?: UnparseableShellPolicy;
|
|
59
|
+
controlPlaneDir?: string | null;
|
|
60
|
+
protectedArtifactRoots?: string[];
|
|
61
|
+
confidenceThresholds?: ConfidenceThresholds;
|
|
62
|
+
scrubOptions?: ScrubOptions;
|
|
63
|
+
/** When true, L1 egress proxy is the external-effect boundary. */
|
|
64
|
+
egressEnabled?: boolean;
|
|
65
|
+
/** When true with egress enabled, external command rules become early warnings only. */
|
|
66
|
+
demoteL3External?: boolean;
|
|
67
|
+
/** When true with sandbox enabled, outside-repo rules defer to fs-scope allowlist. */
|
|
68
|
+
brokerFsScope?: boolean;
|
|
69
|
+
fsScopeAllowlist?: FsScopeAllowlistFile;
|
|
70
|
+
/** Test override: inject Tier1 judge without changing config.judge. */
|
|
71
|
+
tier1Judge?: import('./v2/types.js').Tier1Judge;
|
|
72
|
+
}
|
|
73
|
+
export interface ApprovalRecord {
|
|
74
|
+
approvalId: string;
|
|
75
|
+
kind: 'shell' | 'subagent' | 'tool' | 'egress' | 'capability';
|
|
76
|
+
fingerprint: string;
|
|
77
|
+
repoRoot: string;
|
|
78
|
+
reason: string;
|
|
79
|
+
summary: string;
|
|
80
|
+
createdAt: string;
|
|
81
|
+
expiresAt: string;
|
|
82
|
+
approvedAt?: string;
|
|
83
|
+
/** Original gated input for explain-last-ask (ApprovalState v2). */
|
|
84
|
+
input?: string;
|
|
85
|
+
inputKind?: 'shell' | 'tool' | 'subagent';
|
|
86
|
+
}
|
|
87
|
+
export interface ApprovalStateFile {
|
|
88
|
+
version: 1 | 2;
|
|
89
|
+
approvals: ApprovalRecord[];
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { BelayConfigV4 } from '../config.js';
|
|
2
|
+
import type { ClassifierOptions, ClassifyResult } from '../types.js';
|
|
3
|
+
import type { Tier1Judge, VerdictContext, VerdictResult } from './types.js';
|
|
4
|
+
export declare function buildVerdictContext(params: {
|
|
5
|
+
cwd: string;
|
|
6
|
+
repoRoot: string;
|
|
7
|
+
config: BelayConfigV4;
|
|
8
|
+
options?: ClassifierOptions;
|
|
9
|
+
judge?: Tier1Judge;
|
|
10
|
+
trustedCwd?: boolean;
|
|
11
|
+
}): VerdictContext;
|
|
12
|
+
export declare function classifyShell(command: string, cwd: string, repoRoot: string, config: BelayConfigV4, options?: ClassifierOptions, judge?: Tier1Judge): Promise<ClassifyResult>;
|
|
13
|
+
export declare function verdictToClassifyResult(result: VerdictResult): ClassifyResult;
|
|
14
|
+
export declare function verdictAuditFields(result: VerdictResult): Record<string, unknown>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { judgeTraceAuditFields } from './judge-audit.js';
|
|
2
|
+
import { createJudgeFromConfig } from './judge-factory.js';
|
|
3
|
+
import { verdict } from './verdict.js';
|
|
4
|
+
export function buildVerdictContext(params) {
|
|
5
|
+
const protectedArtifactRoots = [
|
|
6
|
+
...(params.options?.protectedArtifactRoots ?? []),
|
|
7
|
+
...(params.options?.controlPlaneDir ? [params.options.controlPlaneDir] : []),
|
|
8
|
+
];
|
|
9
|
+
return {
|
|
10
|
+
cwd: params.cwd,
|
|
11
|
+
repoRoot: params.repoRoot,
|
|
12
|
+
trustedCwd: params.trustedCwd ?? Boolean(params.cwd),
|
|
13
|
+
sensitivePaths: params.options?.sensitivePaths ?? params.config.classifier.sensitivePaths,
|
|
14
|
+
protectedArtifactRoots: protectedArtifactRoots.length > 0 ? [...new Set(protectedArtifactRoots)] : undefined,
|
|
15
|
+
customAllowCommands: params.options?.customAllowCommands ?? params.config.overrides.allow,
|
|
16
|
+
customExternalCommands: params.options?.customExternalCommands ?? params.config.overrides.external,
|
|
17
|
+
judge: params.judge ?? params.options?.tier1Judge ?? createJudgeFromConfig(params.config),
|
|
18
|
+
mode: params.config.mode,
|
|
19
|
+
unknownLocalEffect: params.options?.unknownLocalEffect ?? params.config.policy.unknownLocalEffect,
|
|
20
|
+
unparseableShell: params.options?.unparseableShell ?? params.config.policy.unparseableShell,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export async function classifyShell(command, cwd, repoRoot, config, options = {}, judge) {
|
|
24
|
+
const context = buildVerdictContext({ cwd, repoRoot, config, options, judge });
|
|
25
|
+
const result = await verdict(command, context);
|
|
26
|
+
return verdictToClassifyResult(result);
|
|
27
|
+
}
|
|
28
|
+
function mapLegacyReason(result) {
|
|
29
|
+
if (result.reason === 'repo_outside_mutation') {
|
|
30
|
+
return result.effect === 'read_only' ? 'outside_repo_redirect' : 'outside_repo_mutation';
|
|
31
|
+
}
|
|
32
|
+
if (result.reason === 'tier0_external') {
|
|
33
|
+
return 'external_effect';
|
|
34
|
+
}
|
|
35
|
+
if (result.reason === 'high_stakes_path') {
|
|
36
|
+
return 'protected_artifact';
|
|
37
|
+
}
|
|
38
|
+
if (result.reason === 'opaque_execution' &&
|
|
39
|
+
/\|\s*(bash|sh|zsh|dash|fish)\b/.test(result.commandRedacted)) {
|
|
40
|
+
return 'pipe_to_shell';
|
|
41
|
+
}
|
|
42
|
+
if (result.reason === 'launcher_unresolved' || result.reason === 'makefile_missing') {
|
|
43
|
+
return 'unknown_local_effect';
|
|
44
|
+
}
|
|
45
|
+
if (result.reason === 'npm_script_undefined' || result.reason === 'package_json_missing') {
|
|
46
|
+
return 'unknown_local_effect';
|
|
47
|
+
}
|
|
48
|
+
if (result.reason === 'repo_local_mutation') {
|
|
49
|
+
return 'local_mutation';
|
|
50
|
+
}
|
|
51
|
+
return result.reason;
|
|
52
|
+
}
|
|
53
|
+
export function verdictToClassifyResult(result) {
|
|
54
|
+
const external = result.location === 'external' ||
|
|
55
|
+
result.location === 'repo_outside' ||
|
|
56
|
+
result.effect === 'remote_mutation';
|
|
57
|
+
const legacyReason = mapLegacyReason(result);
|
|
58
|
+
const hookVerdict = result.permission === 'ask'
|
|
59
|
+
? 'deny_pending_approval'
|
|
60
|
+
: legacyReason === 'command_substitution' ||
|
|
61
|
+
legacyReason === 'unknown_local_effect' ||
|
|
62
|
+
legacyReason === 'unparseable_shell' ||
|
|
63
|
+
result.effect === 'local_mutation'
|
|
64
|
+
? 'allow_flagged'
|
|
65
|
+
: 'allow';
|
|
66
|
+
const assessment = {
|
|
67
|
+
reversibility: result.effect === 'read_only'
|
|
68
|
+
? 'reversible'
|
|
69
|
+
: result.permission === 'allow'
|
|
70
|
+
? 'recoverable_with_cost'
|
|
71
|
+
: 'irreversible',
|
|
72
|
+
external,
|
|
73
|
+
blastRadius: result.location,
|
|
74
|
+
confidence: result.confidence === 'deterministic'
|
|
75
|
+
? 0.95
|
|
76
|
+
: result.confidence === 'llm'
|
|
77
|
+
? 0.75
|
|
78
|
+
: hookVerdict === 'allow_flagged'
|
|
79
|
+
? 0.75
|
|
80
|
+
: 0.7,
|
|
81
|
+
signals: result.signals,
|
|
82
|
+
};
|
|
83
|
+
return {
|
|
84
|
+
verdict: hookVerdict,
|
|
85
|
+
reason: legacyReason,
|
|
86
|
+
fingerprint: result.fingerprint,
|
|
87
|
+
assessment,
|
|
88
|
+
normalizedCommand: result.commandRedacted,
|
|
89
|
+
summary: result.commandRedacted,
|
|
90
|
+
v2: {
|
|
91
|
+
location: result.location,
|
|
92
|
+
opacity: result.opacity,
|
|
93
|
+
effect: result.effect,
|
|
94
|
+
confidence: result.confidence,
|
|
95
|
+
would: result.permission,
|
|
96
|
+
by: 'v2',
|
|
97
|
+
commandRedacted: result.commandRedacted,
|
|
98
|
+
commandFingerprint: result.fingerprint,
|
|
99
|
+
signals: result.signals,
|
|
100
|
+
...judgeTraceAuditFields(result.judgeTrace),
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function verdictAuditFields(result) {
|
|
105
|
+
return {
|
|
106
|
+
schemaVersion: 2,
|
|
107
|
+
commandRedacted: result.commandRedacted,
|
|
108
|
+
commandFingerprint: result.fingerprint,
|
|
109
|
+
location: result.location,
|
|
110
|
+
opacity: result.opacity,
|
|
111
|
+
effect: result.effect,
|
|
112
|
+
confidence: result.confidence,
|
|
113
|
+
would: result.permission,
|
|
114
|
+
by: 'v2',
|
|
115
|
+
signals: result.signals,
|
|
116
|
+
...judgeTraceAuditFields(result.judgeTrace),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { VerdictLocation } from './types.js';
|
|
2
|
+
export interface PathTargetAnalysis {
|
|
3
|
+
location: VerdictLocation;
|
|
4
|
+
isHighStakes: boolean;
|
|
5
|
+
signals: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveTrustedPath(token: string, trustedCwd: string, trusted: boolean): string | null;
|
|
8
|
+
export declare function locationForPath(resolvedPath: string | null, repoRoot: string): VerdictLocation;
|
|
9
|
+
export declare function isGitPath(resolvedPath: string, repoRoot: string): boolean;
|
|
10
|
+
export declare function isHighStakesPath(resolvedPath: string, repoRoot: string, sensitivePaths: string[], protectedRoots?: string[]): boolean;
|
|
11
|
+
export declare function analyzePathTargets(params: {
|
|
12
|
+
targets: string[];
|
|
13
|
+
cwd: string;
|
|
14
|
+
repoRoot: string;
|
|
15
|
+
trustedCwd: boolean;
|
|
16
|
+
sensitivePaths: string[];
|
|
17
|
+
protectedArtifactRoots?: string[];
|
|
18
|
+
}): PathTargetAnalysis;
|
|
19
|
+
export declare function cwdRelative(repoRoot: string, cwd: string): string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { matchesSensitivePath } from '../glob.js';
|
|
3
|
+
import { canonicalPath, pathWithinRoot, relativeWithinRepo, resolveMutationTarget, } from '../path-utils.js';
|
|
4
|
+
function expandHome(token) {
|
|
5
|
+
if (token === '~' || token.startsWith('~/')) {
|
|
6
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? '';
|
|
7
|
+
if (!home) {
|
|
8
|
+
return token;
|
|
9
|
+
}
|
|
10
|
+
return token === '~' ? home : path.join(home, token.slice(2));
|
|
11
|
+
}
|
|
12
|
+
return token;
|
|
13
|
+
}
|
|
14
|
+
export function resolveTrustedPath(token, trustedCwd, trusted) {
|
|
15
|
+
if (!token || token === '--' || token.startsWith('-')) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (!trusted || !trustedCwd) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const expanded = expandHome(token);
|
|
22
|
+
if (path.isAbsolute(expanded)) {
|
|
23
|
+
return canonicalPath(expanded);
|
|
24
|
+
}
|
|
25
|
+
return canonicalPath(path.resolve(trustedCwd, expanded));
|
|
26
|
+
}
|
|
27
|
+
export function locationForPath(resolvedPath, repoRoot) {
|
|
28
|
+
if (!resolvedPath) {
|
|
29
|
+
return 'unknown';
|
|
30
|
+
}
|
|
31
|
+
if (pathWithinRoot(repoRoot, resolvedPath)) {
|
|
32
|
+
return 'repo_local';
|
|
33
|
+
}
|
|
34
|
+
return 'repo_outside';
|
|
35
|
+
}
|
|
36
|
+
export function isGitPath(resolvedPath, repoRoot) {
|
|
37
|
+
const relative = relativeWithinRepo(repoRoot, resolvedPath);
|
|
38
|
+
if (!relative) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const normalized = relative.replaceAll('\\', '/');
|
|
42
|
+
return normalized === '.git' || normalized.startsWith('.git/');
|
|
43
|
+
}
|
|
44
|
+
export function isHighStakesPath(resolvedPath, repoRoot, sensitivePaths, protectedRoots = []) {
|
|
45
|
+
if (isGitPath(resolvedPath, repoRoot)) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
const relative = relativeWithinRepo(repoRoot, resolvedPath);
|
|
49
|
+
const checkPath = relative ?? resolvedPath;
|
|
50
|
+
if (matchesSensitivePath(checkPath.replaceAll('\\', '/'), sensitivePaths)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return protectedRoots.some((root) => pathWithinRoot(root, resolvedPath));
|
|
54
|
+
}
|
|
55
|
+
export function analyzePathTargets(params) {
|
|
56
|
+
const signals = [];
|
|
57
|
+
if (!params.trustedCwd || !params.cwd) {
|
|
58
|
+
return {
|
|
59
|
+
location: 'unknown',
|
|
60
|
+
isHighStakes: false,
|
|
61
|
+
signals: ['missing_trusted_cwd'],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const locations = new Set();
|
|
65
|
+
let isHighStakes = false;
|
|
66
|
+
for (const target of params.targets) {
|
|
67
|
+
const resolved = resolveTrustedPath(target, params.cwd, params.trustedCwd) ??
|
|
68
|
+
resolveMutationTarget(target, params.cwd);
|
|
69
|
+
const location = locationForPath(resolved, params.repoRoot);
|
|
70
|
+
locations.add(location);
|
|
71
|
+
if (resolved &&
|
|
72
|
+
isHighStakesPath(resolved, params.repoRoot, params.sensitivePaths, params.protectedArtifactRoots)) {
|
|
73
|
+
isHighStakes = true;
|
|
74
|
+
signals.push('high_stakes_path');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
let location = 'unknown';
|
|
78
|
+
if (locations.size === 0) {
|
|
79
|
+
location = 'unknown';
|
|
80
|
+
}
|
|
81
|
+
else if (locations.size === 1) {
|
|
82
|
+
location = [...locations][0] ?? 'unknown';
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
location = 'mixed';
|
|
86
|
+
}
|
|
87
|
+
return { location, isHighStakes, signals };
|
|
88
|
+
}
|
|
89
|
+
export function cwdRelative(repoRoot, cwd) {
|
|
90
|
+
return relativeWithinRepo(repoRoot, cwd) ?? cwd;
|
|
91
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier0 egress tool classification (SPEC v2.1.3 R33–R34).
|
|
3
|
+
* destructive → Tier0 ask | read → Tier0 allow | ambiguous → Tier1 (fail-closed)
|
|
4
|
+
*/
|
|
5
|
+
export type EgressClassification = 'destructive' | 'read' | 'ambiguous';
|
|
6
|
+
export declare function isEgressToolHead(head: string): boolean;
|
|
7
|
+
export declare function classifyEgressTool(head: string, tokens: string[]): EgressClassification | null;
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier0 egress tool classification (SPEC v2.1.3 R33–R34).
|
|
3
|
+
* destructive → Tier0 ask | read → Tier0 allow | ambiguous → Tier1 (fail-closed)
|
|
4
|
+
*/
|
|
5
|
+
const EGRESS_TOOL_HEADS = new Set([
|
|
6
|
+
'aws',
|
|
7
|
+
'curl',
|
|
8
|
+
'gh',
|
|
9
|
+
'gcloud',
|
|
10
|
+
'heroku',
|
|
11
|
+
'kubectl',
|
|
12
|
+
'netlify',
|
|
13
|
+
'vercel',
|
|
14
|
+
'wget',
|
|
15
|
+
]);
|
|
16
|
+
const READ_VERB_PATTERN = /\b(ls|list|describe|get|view|logs|status|top|head|explain)\b/;
|
|
17
|
+
const CURL_DATA_FLAGS = new Set(['-d', '-F', '-T', '--post-data', '--post-file', '--upload-file']);
|
|
18
|
+
const CURL_DATA_PREFIXES = ['--data', '--form', '--upload-file', '--post-'];
|
|
19
|
+
const KUBECTL_DESTRUCTIVE = new Set([
|
|
20
|
+
'apply',
|
|
21
|
+
'cordon',
|
|
22
|
+
'create',
|
|
23
|
+
'delete',
|
|
24
|
+
'drain',
|
|
25
|
+
'exec',
|
|
26
|
+
'patch',
|
|
27
|
+
'replace',
|
|
28
|
+
'rollout',
|
|
29
|
+
'scale',
|
|
30
|
+
]);
|
|
31
|
+
const KUBECTL_READ = new Set(['describe', 'get', 'logs', 'top']);
|
|
32
|
+
export function isEgressToolHead(head) {
|
|
33
|
+
return EGRESS_TOOL_HEADS.has(head);
|
|
34
|
+
}
|
|
35
|
+
export function classifyEgressTool(head, tokens) {
|
|
36
|
+
if (!EGRESS_TOOL_HEADS.has(head)) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (head === 'curl' || head === 'wget') {
|
|
40
|
+
return classifyCurlWget(tokens);
|
|
41
|
+
}
|
|
42
|
+
if (head === 'aws') {
|
|
43
|
+
return classifyAws(tokens);
|
|
44
|
+
}
|
|
45
|
+
if (head === 'gh') {
|
|
46
|
+
return classifyGh(tokens);
|
|
47
|
+
}
|
|
48
|
+
if (head === 'gcloud') {
|
|
49
|
+
return classifyGcloud(tokens);
|
|
50
|
+
}
|
|
51
|
+
if (head === 'kubectl') {
|
|
52
|
+
return classifyKubectl(tokens);
|
|
53
|
+
}
|
|
54
|
+
if (head === 'heroku') {
|
|
55
|
+
return classifyHeroku(tokens);
|
|
56
|
+
}
|
|
57
|
+
if (head === 'vercel') {
|
|
58
|
+
return classifyVercel(tokens);
|
|
59
|
+
}
|
|
60
|
+
if (head === 'netlify') {
|
|
61
|
+
return classifyNetlify(tokens);
|
|
62
|
+
}
|
|
63
|
+
return 'ambiguous';
|
|
64
|
+
}
|
|
65
|
+
function classifyCurlWget(tokens) {
|
|
66
|
+
const args = tokens.slice(1);
|
|
67
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
68
|
+
const token = args[index];
|
|
69
|
+
if (!token) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (CURL_DATA_FLAGS.has(token)) {
|
|
73
|
+
return 'destructive';
|
|
74
|
+
}
|
|
75
|
+
if (CURL_DATA_PREFIXES.some((prefix) => token.startsWith(prefix))) {
|
|
76
|
+
return 'destructive';
|
|
77
|
+
}
|
|
78
|
+
if (token.startsWith('--method=')) {
|
|
79
|
+
const method = token.slice('--method='.length).toUpperCase();
|
|
80
|
+
if (method !== 'GET' && method !== 'HEAD') {
|
|
81
|
+
return 'destructive';
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (token === '-X' || token === '--request') {
|
|
85
|
+
const method = (args[index + 1] ?? '').toUpperCase();
|
|
86
|
+
if (method && method !== 'GET' && method !== 'HEAD') {
|
|
87
|
+
return 'destructive';
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (token.startsWith('@')) {
|
|
91
|
+
return 'destructive';
|
|
92
|
+
}
|
|
93
|
+
if (token.includes('@') && /(^|[^\\])@/.test(token)) {
|
|
94
|
+
return 'destructive';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return 'read';
|
|
98
|
+
}
|
|
99
|
+
function classifyAws(tokens) {
|
|
100
|
+
const rest = tokens.slice(1);
|
|
101
|
+
const joined = rest.join(' ').toLowerCase();
|
|
102
|
+
if (/\bs3\s+rm\b/.test(joined)) {
|
|
103
|
+
return 'destructive';
|
|
104
|
+
}
|
|
105
|
+
if (/\bs3\s+sync\b/.test(joined)) {
|
|
106
|
+
return 'destructive';
|
|
107
|
+
}
|
|
108
|
+
if (/\bs3\s+cp\b/.test(joined)) {
|
|
109
|
+
const s3Args = rest.filter((token) => token.startsWith('s3://'));
|
|
110
|
+
if (s3Args.length >= 2) {
|
|
111
|
+
return 'ambiguous';
|
|
112
|
+
}
|
|
113
|
+
const lastToken = rest[rest.length - 1] ?? '';
|
|
114
|
+
if (lastToken.startsWith('s3://')) {
|
|
115
|
+
return 'destructive';
|
|
116
|
+
}
|
|
117
|
+
if (s3Args.length === 1 && !lastToken.startsWith('s3://')) {
|
|
118
|
+
return 'read';
|
|
119
|
+
}
|
|
120
|
+
return 'ambiguous';
|
|
121
|
+
}
|
|
122
|
+
if (/\b(delete|terminate)\b/.test(joined)) {
|
|
123
|
+
return 'destructive';
|
|
124
|
+
}
|
|
125
|
+
if (/\b(put|create|update)\b/.test(joined)) {
|
|
126
|
+
return 'destructive';
|
|
127
|
+
}
|
|
128
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
129
|
+
return 'read';
|
|
130
|
+
}
|
|
131
|
+
return 'ambiguous';
|
|
132
|
+
}
|
|
133
|
+
function classifyGh(tokens) {
|
|
134
|
+
const joined = tokens.slice(1).join(' ').toLowerCase();
|
|
135
|
+
if (/\brelease\s+create\b/.test(joined)) {
|
|
136
|
+
return 'destructive';
|
|
137
|
+
}
|
|
138
|
+
if (/\brepo\s+(delete|create)\b/.test(joined)) {
|
|
139
|
+
return 'destructive';
|
|
140
|
+
}
|
|
141
|
+
if (/\bpr\s+merge\b/.test(joined)) {
|
|
142
|
+
return 'destructive';
|
|
143
|
+
}
|
|
144
|
+
if (/\bsecret\s+set\b/.test(joined)) {
|
|
145
|
+
return 'destructive';
|
|
146
|
+
}
|
|
147
|
+
if (/\bworkflow\s+run\b/.test(joined)) {
|
|
148
|
+
return 'destructive';
|
|
149
|
+
}
|
|
150
|
+
if (/\bapi\b/.test(joined) && /\s(-x|--method)\s+(post|put|patch|delete)\b/.test(joined)) {
|
|
151
|
+
return 'destructive';
|
|
152
|
+
}
|
|
153
|
+
if (/\bpr\s+list\b/.test(joined)) {
|
|
154
|
+
return 'read';
|
|
155
|
+
}
|
|
156
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
157
|
+
return 'read';
|
|
158
|
+
}
|
|
159
|
+
return 'ambiguous';
|
|
160
|
+
}
|
|
161
|
+
function classifyGcloud(tokens) {
|
|
162
|
+
const joined = tokens.slice(1).join(' ').toLowerCase();
|
|
163
|
+
if (/\b(delete|create|update|deploy)\b/.test(joined)) {
|
|
164
|
+
return 'destructive';
|
|
165
|
+
}
|
|
166
|
+
if (/\bset-/.test(joined)) {
|
|
167
|
+
return 'destructive';
|
|
168
|
+
}
|
|
169
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
170
|
+
return 'read';
|
|
171
|
+
}
|
|
172
|
+
return 'ambiguous';
|
|
173
|
+
}
|
|
174
|
+
function classifyKubectl(tokens) {
|
|
175
|
+
const sub = (tokens[1] ?? '').toLowerCase();
|
|
176
|
+
if (KUBECTL_DESTRUCTIVE.has(sub)) {
|
|
177
|
+
return 'destructive';
|
|
178
|
+
}
|
|
179
|
+
if (KUBECTL_READ.has(sub)) {
|
|
180
|
+
return 'read';
|
|
181
|
+
}
|
|
182
|
+
return 'ambiguous';
|
|
183
|
+
}
|
|
184
|
+
function classifyHeroku(tokens) {
|
|
185
|
+
const joined = tokens.slice(1).join(' ').toLowerCase();
|
|
186
|
+
if (/\bdeploy\b/.test(joined) ||
|
|
187
|
+
/pg:reset/.test(joined) ||
|
|
188
|
+
/ps:scale/.test(joined) ||
|
|
189
|
+
/\bdestroy\b/.test(joined)) {
|
|
190
|
+
return 'destructive';
|
|
191
|
+
}
|
|
192
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
193
|
+
return 'read';
|
|
194
|
+
}
|
|
195
|
+
return 'ambiguous';
|
|
196
|
+
}
|
|
197
|
+
function classifyVercel(tokens) {
|
|
198
|
+
const joined = tokens.slice(1).join(' ').toLowerCase();
|
|
199
|
+
if (/\bdeploy\b/.test(joined) || /--prod\b/.test(joined) || /\bdestroy\b/.test(joined)) {
|
|
200
|
+
return 'destructive';
|
|
201
|
+
}
|
|
202
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
203
|
+
return 'read';
|
|
204
|
+
}
|
|
205
|
+
return 'ambiguous';
|
|
206
|
+
}
|
|
207
|
+
function classifyNetlify(tokens) {
|
|
208
|
+
const joined = tokens.slice(1).join(' ').toLowerCase();
|
|
209
|
+
if (/\bdeploy\b/.test(joined) || /--prod\b/.test(joined)) {
|
|
210
|
+
return 'destructive';
|
|
211
|
+
}
|
|
212
|
+
if (READ_VERB_PATTERN.test(joined)) {
|
|
213
|
+
return 'read';
|
|
214
|
+
}
|
|
215
|
+
return 'ambiguous';
|
|
216
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function verdictFingerprint(cwdRelative: string, commandRedacted: string): string;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { buildVerdictContext, classifyShell, verdictAuditFields, verdictToClassifyResult, } from './adapter.js';
|
|
2
|
+
export { analyzePathTargets, cwdRelative, resolveTrustedPath } from './containment.js';
|
|
3
|
+
export { verdictFingerprint } from './fingerprint.js';
|
|
4
|
+
export type { Tier1JudgeTrace, TracedTier1Judge } from './judge.js';
|
|
5
|
+
export { createCursorJudge, createDeterministicJudgeStub, createFailClosedJudge, createOllamaJudge, createOpenAiCompatibleJudge, prescanInterpreterCode, tier1RequiresAsk, } from './judge.js';
|
|
6
|
+
export { judgeTraceAuditFields } from './judge-audit.js';
|
|
7
|
+
export { createJudgeFromConfig, judgeConfigSummary, loadPinnedJudgeModels, resetPinnedJudgeModelsCache, resolveCloudModel, } from './judge-factory.js';
|
|
8
|
+
export { scrubOutboundForJudge } from './judge-outbound.js';
|
|
9
|
+
export { isRoutineLauncher, resolveLauncherRecipe } from './launcher-resolve.js';
|
|
10
|
+
export { parseSegment, peelTransparentWrappers, segmentOpacity, splitTopLevelSegments, } from './parser.js';
|
|
11
|
+
export type { JudgeTrace, Tier1EvaluateInput, Tier1Judge, Tier1Verdict, VerdictConfidence, VerdictContext, VerdictEffect, VerdictLocation, VerdictOpacity, VerdictPermission, VerdictResult, } from './types.js';
|
|
12
|
+
export { verdict } from './verdict.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { buildVerdictContext, classifyShell, verdictAuditFields, verdictToClassifyResult, } from './adapter.js';
|
|
2
|
+
export { analyzePathTargets, cwdRelative, resolveTrustedPath } from './containment.js';
|
|
3
|
+
export { verdictFingerprint } from './fingerprint.js';
|
|
4
|
+
export { createCursorJudge, createDeterministicJudgeStub, createFailClosedJudge, createOllamaJudge, createOpenAiCompatibleJudge, prescanInterpreterCode, tier1RequiresAsk, } from './judge.js';
|
|
5
|
+
export { judgeTraceAuditFields } from './judge-audit.js';
|
|
6
|
+
export { createJudgeFromConfig, judgeConfigSummary, loadPinnedJudgeModels, resetPinnedJudgeModelsCache, resolveCloudModel, } from './judge-factory.js';
|
|
7
|
+
export { scrubOutboundForJudge } from './judge-outbound.js';
|
|
8
|
+
export { isRoutineLauncher, resolveLauncherRecipe } from './launcher-resolve.js';
|
|
9
|
+
export { parseSegment, peelTransparentWrappers, segmentOpacity, splitTopLevelSegments, } from './parser.js';
|
|
10
|
+
export { verdict } from './verdict.js';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function judgeTraceAuditFields(trace) {
|
|
2
|
+
if (!trace) {
|
|
3
|
+
return {};
|
|
4
|
+
}
|
|
5
|
+
return {
|
|
6
|
+
judgeProvider: trace.provider,
|
|
7
|
+
judgeModelRequested: trace.modelRequested,
|
|
8
|
+
judgeModelResolved: trace.modelResolved,
|
|
9
|
+
judgeLatencyMs: trace.latencyMs,
|
|
10
|
+
...(trace.outboundRedacted !== undefined
|
|
11
|
+
? { judgeOutboundRedacted: trace.outboundRedacted }
|
|
12
|
+
: {}),
|
|
13
|
+
...(trace.fallbackReason ? { judgeFallbackReason: trace.fallbackReason } : {}),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { BelayConfigV4, BelayJudgeConfig } from '../config.js';
|
|
2
|
+
import { type TracedTier1Judge } from './judge.js';
|
|
3
|
+
export declare function resetPinnedJudgeModelsCache(): void;
|
|
4
|
+
export declare function loadPinnedJudgeModels(): Promise<{
|
|
5
|
+
'openai-compatible': {
|
|
6
|
+
autoResolved: string;
|
|
7
|
+
};
|
|
8
|
+
ollama: {
|
|
9
|
+
ciPin: string;
|
|
10
|
+
};
|
|
11
|
+
}>;
|
|
12
|
+
export declare function resolveCloudModel(requested: string, pinned: {
|
|
13
|
+
autoResolved: string;
|
|
14
|
+
}): {
|
|
15
|
+
requested: string;
|
|
16
|
+
resolved: string;
|
|
17
|
+
};
|
|
18
|
+
/** @deprecated Use resolveCloudModel */
|
|
19
|
+
export declare const resolveCursorModel: typeof resolveCloudModel;
|
|
20
|
+
export declare function createJudgeFromConfig(config: BelayConfigV4, options?: {
|
|
21
|
+
pinnedModels?: {
|
|
22
|
+
autoResolved: string;
|
|
23
|
+
};
|
|
24
|
+
}): TracedTier1Judge;
|
|
25
|
+
export declare function judgeConfigSummary(judge: BelayJudgeConfig): string;
|