@counterfact-labs/cli 0.2.4 → 0.2.5
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/README.md +7 -1
- package/bundle/client-release.json +1 -1
- package/dist/adapters/anthropic.js +11 -2
- package/dist/adapters/completion.js +3 -0
- package/dist/adapters/durable-write.js +9 -2
- package/dist/adapters/files.js +25 -13
- package/dist/adapters/git-ignore.js +28 -14
- package/dist/adapters/git.js +1 -1
- package/dist/adapters/gitignore-output.js +41 -0
- package/dist/adapters/models.js +1 -6
- package/dist/adapters/output-paths.js +5 -2
- package/dist/adapters/public-instructions.js +1 -1
- package/dist/adapters/relay-plan.js +2 -5
- package/dist/adapters/release.js +2 -1
- package/dist/adapters/repository-files.js +164 -4
- package/dist/adapters/repository-root.js +18 -2
- package/dist/adapters/results.js +8 -4
- package/dist/adapters/settings.js +26 -1
- package/dist/adapters/snapshot.js +86 -15
- package/dist/analysis-core/analysis/finding-audience-switch.js +1 -0
- package/dist/analysis-core/analysis/schemas.js +1 -1
- package/dist/analysis-core/analysis/source-notes/types.js +1 -1
- package/dist/analysis-core/chunks/377MLK4M.js +21 -0
- package/dist/analysis-core/chunks/{D6AWHLRI.js → 3JWEFCTJ.js} +1 -1
- package/dist/analysis-core/chunks/{3227KXHF.js → 4H23CSUM.js} +1 -1
- package/dist/analysis-core/chunks/5DGPLXYB.js +1 -0
- package/dist/analysis-core/chunks/5TATKWLG.js +1 -0
- package/dist/analysis-core/chunks/{EH3QQ3T4.js → 6B2HILSY.js} +1 -1
- package/dist/analysis-core/chunks/6QY5BV5B.js +14 -0
- package/dist/analysis-core/chunks/6U2IR4XB.js +1 -0
- package/dist/analysis-core/chunks/A7WJJMRY.js +1 -0
- package/dist/analysis-core/chunks/C6X5GDG4.js +1 -0
- package/dist/analysis-core/chunks/DLPVYWHZ.js +1 -0
- package/dist/analysis-core/chunks/DZZBQDGO.js +1 -0
- package/dist/analysis-core/chunks/F3R4J3ND.js +1 -0
- package/dist/analysis-core/chunks/FOKDE64Y.js +1 -0
- package/dist/analysis-core/chunks/K2GNDX3W.js +1 -0
- package/dist/analysis-core/chunks/KTNA2KTN.js +7 -0
- package/dist/analysis-core/chunks/KWECQJ6X.js +1 -0
- package/dist/analysis-core/chunks/{SL27GMEN.js → M6HYSTQD.js} +1 -1
- package/dist/analysis-core/chunks/{ZAA44GPI.js → N7U5N42V.js} +1 -1
- package/dist/analysis-core/chunks/NIOS7U6C.js +41 -0
- package/dist/analysis-core/chunks/{QMIXCT62.js → OPMA32A6.js} +1 -1
- package/dist/analysis-core/chunks/PECX3OXB.js +1 -0
- package/dist/analysis-core/chunks/QFY6A3MS.js +66 -0
- package/dist/analysis-core/chunks/SKVEBOGA.js +1 -0
- package/dist/analysis-core/chunks/{T66VDFXF.js → STI4JE7L.js} +1 -1
- package/dist/analysis-core/chunks/SVMEWGD3.js +1 -0
- package/dist/analysis-core/chunks/X7WZAA7S.js +1 -0
- package/dist/analysis-core/chunks/YDBO7P4X.js +1 -0
- package/dist/analysis-core/chunks/YUY436SM.js +1 -0
- package/dist/analysis-core/chunks/ZTOVBAG7.js +1 -0
- package/dist/analysis-core/contracts/file-safety.js +1 -0
- package/dist/analysis-core/contracts/relay-analysis.js +1 -0
- package/dist/analysis-core/contracts/requests.js +1 -1
- package/dist/analysis-core/conventions/analysis-fit.js +1 -1
- package/dist/analysis-core/conventions/file-admission.js +1 -1
- package/dist/analysis-core/data/finding-types.js +1 -1
- package/dist/analysis-core/findings/sites.js +1 -0
- package/dist/analysis-core/github/repo-key.js +1 -1
- package/dist/analysis-core/import/outside-loader-sources.js +1 -1
- package/dist/analysis-core/index.js +3 -3
- package/dist/analysis-core/llm/output-limit.js +1 -1
- package/dist/analysis-core/llm/types.js +1 -0
- package/dist/analysis-core/requests/answer-formats.js +1 -1
- package/dist/analysis-core/requests/headline-request.js +1 -1
- package/dist/analysis-core/requests/local-plan.js +1 -1
- package/dist/analysis-core/requests/registry.js +1 -1
- package/dist/analysis-core/requests/template-version.js +1 -1
- package/dist/analysis-core/requests/tools.js +1 -1
- package/dist/analysis-core/settings.js +1 -1
- package/dist/analysis-core/stages/engine-entry.js +1 -0
- package/dist/analysis-core/stages/execution-ports.js +1 -0
- package/dist/bundle/seal/deserialise.js +9 -1
- package/dist/bundle/seal/engine.js +76 -0
- package/dist/bundle/seal/freeze.js +9 -0
- package/dist/bundle/seal/metadata.js +3 -0
- package/dist/bundle/seal/open-engine.js +26 -0
- package/dist/bundle/seal/open.js +2 -8
- package/dist/cli/commands/analyze.js +36 -4
- package/dist/cli/commands/finding.js +9 -3
- package/dist/cli/context.js +4 -1
- package/dist/cli/finding-display.js +39 -0
- package/dist/cli/finding-lookup.js +92 -0
- package/dist/cli/finding-settings.js +5 -0
- package/dist/cli/fix-requests.js +42 -0
- package/dist/cli/intake-payload.js +19 -11
- package/dist/cli/main.js +9 -4
- package/dist/cli/mcp.js +65 -18
- package/dist/cli/relay-check.js +46 -13
- package/dist/cli/relay-preparation.js +28 -5
- package/dist/cli/result-check.js +68 -0
- package/dist/cli/summary.js +10 -3
- package/dist/contract/agent-choice.js +15 -0
- package/dist/contract/agent-proposal.js +38 -0
- package/dist/contract/attestation.js +106 -0
- package/dist/contract/cli-refusals.js +3 -0
- package/dist/contract/cli-version.js +1 -1
- package/dist/contract/console.js +21 -16
- package/dist/contract/engine.js +44 -0
- package/dist/contract/findings.js +28 -0
- package/dist/contract/fix-requests.js +30 -0
- package/dist/contract/messages.js +6 -94
- package/dist/contract/public-report.js +1 -0
- package/dist/contract/runtime-environment.js +12 -1
- package/dist/core/analysis/run-to-end.js +7 -52
- package/dist/gatekeeper/attestation.js +1 -1
- package/dist/gatekeeper/channel-binding.js +15 -0
- package/dist/gatekeeper/cli-api.js +12 -2
- package/dist/gatekeeper/connection-exchange.js +16 -12
- package/dist/gatekeeper/model.js +2 -1
- package/dist/gatekeeper/production-attestation.js +23 -17
- package/dist/gatekeeper/trust/policy.js +4 -1
- package/dist/gatekeeper/trust/schema.js +4 -0
- package/dist/transport/kms.js +25 -0
- package/package.json +4 -3
- package/dist/adapters/quality.js +0 -6
- package/dist/adapters/report.js +0 -29
- package/dist/analysis-core/analysis/analysis-flags.js +0 -1
- package/dist/analysis-core/analysis/finding-quality/config.js +0 -1
- package/dist/analysis-core/analysis/finding-quality/policy.js +0 -1
- package/dist/analysis-core/analysis/headlines/attachment.js +0 -1
- package/dist/analysis-core/analysis/headlines/input.js +0 -1
- package/dist/analysis-core/chunks/3CKW5JIF.js +0 -1
- package/dist/analysis-core/chunks/6YCABS5T.js +0 -1
- package/dist/analysis-core/chunks/7OYIBWX3.js +0 -1
- package/dist/analysis-core/chunks/DRGDIIFA.js +0 -1
- package/dist/analysis-core/chunks/FTODBFQW.js +0 -1
- package/dist/analysis-core/chunks/HPIAEQHE.js +0 -37
- package/dist/analysis-core/chunks/IVDDV6CU.js +0 -14
- package/dist/analysis-core/chunks/JF4GYMOZ.js +0 -1
- package/dist/analysis-core/chunks/K5OTWBTT.js +0 -22
- package/dist/analysis-core/chunks/MXXNED6N.js +0 -7
- package/dist/analysis-core/chunks/NCWEOJVJ.js +0 -6
- package/dist/analysis-core/chunks/O652FQQH.js +0 -1
- package/dist/analysis-core/chunks/OFBJNHC6.js +0 -1
- package/dist/analysis-core/chunks/QV2EOS7U.js +0 -1
- package/dist/analysis-core/chunks/STZOC7LN.js +0 -1
- package/dist/analysis-core/chunks/T2SAP7OV.js +0 -60
- package/dist/analysis-core/chunks/T5TREZCQ.js +0 -1
- package/dist/analysis-core/chunks/TDNTU4TF.js +0 -1
- package/dist/analysis-core/chunks/U5HOEVPE.js +0 -1
- package/dist/analysis-core/chunks/UEWL3GMQ.js +0 -1
- package/dist/analysis-core/chunks/V7BFUTM7.js +0 -1
- package/dist/core/analysis/finding-quality/config.js +0 -4
- package/dist/core/analysis/structural-run.js +0 -16
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { analysisRelease } from "./engine.js";
|
|
2
3
|
import { executionRequest } from "../analysis-core/contracts/requests.js";
|
|
3
|
-
import {
|
|
4
|
+
import { compactJwtPattern, hexChallenge } from "./attestation.js";
|
|
5
|
+
export { PRODUCTION_EVIDENCE_VERSION, RELAY_CHANNEL_AUDIENCE, RELAY_PORT, RELAY_URL, RELAY_HEALTH_PATH, RELAY_HEALTH_URL, GOOGLE_ATTESTATION_ISSUER, MAX_ATTESTATION_BYTES, attestationChallenge, productionEvidence, evidenceBinding, googleAttestationClaims, observedAttestationClaims, probeAttestationClaims, attestationClaims } from "./attestation.js";
|
|
4
6
|
/**
|
|
5
7
|
* The messages that cross between the customer's machine and the sealed relay. This module is the only owner of
|
|
6
|
-
* their shape: the relay, the gatekeeper and the bundle tooling
|
|
8
|
+
* their analysis shape: the relay, the gatekeeper and the bundle tooling import these schemas and never redefine them.
|
|
9
|
+
* Public identity schemas are owned by attestation.ts and re-exported here for existing consumers.
|
|
7
10
|
* Design: docs/design/sealed-model-relay.md and docs/design/relay-contract.md.
|
|
8
11
|
*/
|
|
9
|
-
const compactJwtPattern = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
10
|
-
const hexChallenge = z.string().length(64).regex(/^[0-9a-f]+$/);
|
|
11
12
|
/** The wire adds routing identity to the core's data-only execution envelope. */
|
|
12
13
|
export const relayRequest = executionRequest.extend({
|
|
13
14
|
bundleVersion: z.string().min(1).max(128),
|
|
@@ -125,102 +126,13 @@ export const relayHealthResponse = z.discriminatedUnion("ok", [
|
|
|
125
126
|
code: z.enum(["bad_request", "unavailable"]),
|
|
126
127
|
}).strict(),
|
|
127
128
|
]);
|
|
128
|
-
export const PRODUCTION_EVIDENCE_VERSION = 1;
|
|
129
|
-
export const RELAY_CHANNEL_AUDIENCE = "https://relay.counterfactlabs.com";
|
|
130
|
-
// Passthrough forwarding keeps the non-root workload's listener port unchanged.
|
|
131
|
-
export const RELAY_PORT = 8443;
|
|
132
|
-
export const RELAY_URL = `${RELAY_CHANNEL_AUDIENCE}:${RELAY_PORT}`;
|
|
133
|
-
export const RELAY_HEALTH_PATH = "/health";
|
|
134
|
-
export const RELAY_HEALTH_URL = `${RELAY_URL}${RELAY_HEALTH_PATH}`;
|
|
135
|
-
export const GOOGLE_ATTESTATION_ISSUER = "https://confidentialcomputing.googleapis.com";
|
|
136
|
-
export const MAX_ATTESTATION_BYTES = 32 * 1024;
|
|
137
|
-
export const attestationChallenge = z.object({
|
|
138
|
-
version: z.literal(PRODUCTION_EVIDENCE_VERSION),
|
|
139
|
-
challenge: hexChallenge,
|
|
140
|
-
}).strict();
|
|
141
|
-
export const productionEvidence = z.object({
|
|
142
|
-
version: z.literal(PRODUCTION_EVIDENCE_VERSION),
|
|
143
|
-
token: z.string().max(MAX_ATTESTATION_BYTES).regex(compactJwtPattern),
|
|
144
|
-
}).strict();
|
|
145
|
-
/** Google's launcher accepts up to six caller nonces, each at most 74 characters. */
|
|
146
|
-
export const evidenceBinding = z.object({
|
|
147
|
-
audience: z.string().min(1).max(256).regex(/^[A-Za-z0-9:/._-]+$/),
|
|
148
|
-
nonces: z.array(z.string().min(1).max(74).regex(/^[A-Za-z0-9_:-]+$/)).min(1).max(6),
|
|
149
|
-
}).strict();
|
|
150
|
-
/** Native claims are interpreted only after the PKI chain and token signature are authenticated. */
|
|
151
|
-
export const googleAttestationClaims = z.object({
|
|
152
|
-
iss: z.literal(GOOGLE_ATTESTATION_ISSUER),
|
|
153
|
-
aud: z.string(),
|
|
154
|
-
sub: z.string(),
|
|
155
|
-
iat: z.number().int(),
|
|
156
|
-
nbf: z.number().int(),
|
|
157
|
-
exp: z.number().int(),
|
|
158
|
-
eat_nonce: z.union([z.string(), z.array(z.string()).min(1).max(6)]),
|
|
159
|
-
secboot: z.literal(true),
|
|
160
|
-
dbgstat: z.literal("disabled-since-boot"),
|
|
161
|
-
oemid: z.literal(11129),
|
|
162
|
-
hwmodel: z.string(),
|
|
163
|
-
swname: z.literal("CONFIDENTIAL_SPACE"),
|
|
164
|
-
swversion: z.array(z.string()).length(1),
|
|
165
|
-
google_service_accounts: z.array(z.string()).min(1),
|
|
166
|
-
development: z.never().optional(),
|
|
167
|
-
identity: z.never().optional(),
|
|
168
|
-
submods: z.object({
|
|
169
|
-
confidential_space: z.object({
|
|
170
|
-
support_attributes: z.array(z.string()),
|
|
171
|
-
monitoring_enabled: z.object({ memory: z.literal(false) }).passthrough(),
|
|
172
|
-
}).passthrough(),
|
|
173
|
-
container: z.object({
|
|
174
|
-
image_digest: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
175
|
-
image_signatures: z.array(z.object({
|
|
176
|
-
key_id: z.string(), signature: z.string().min(1),
|
|
177
|
-
signature_algorithm: z.literal("RSASSA_PSS_SHA256"),
|
|
178
|
-
}).passthrough()).min(1),
|
|
179
|
-
// Google omits both override claims when nothing was overridden; when present they must still be empty.
|
|
180
|
-
cmd_override: z.array(z.unknown()).length(0).optional(),
|
|
181
|
-
env_override: z.object({}).strict().optional(),
|
|
182
|
-
// Real tokens list the container's own environment; the relay's start-up rule decides which settings are allowed.
|
|
183
|
-
env: z.record(z.string(), z.string()).refine(env => {
|
|
184
|
-
try {
|
|
185
|
-
checkRuntimeEnvironment(env);
|
|
186
|
-
return true;
|
|
187
|
-
}
|
|
188
|
-
catch {
|
|
189
|
-
return false;
|
|
190
|
-
}
|
|
191
|
-
}),
|
|
192
|
-
}).passthrough(),
|
|
193
|
-
}).passthrough(),
|
|
194
|
-
}).passthrough();
|
|
195
|
-
/** Authenticated observations describe a refused workload without granting it an admitted identity. */
|
|
196
|
-
export const observedAttestationClaims = googleAttestationClaims.extend({
|
|
197
|
-
dbgstat: z.string(),
|
|
198
|
-
submods: googleAttestationClaims.shape.submods.extend({
|
|
199
|
-
container: googleAttestationClaims.shape.submods.shape.container.extend({
|
|
200
|
-
image_signatures: z.array(googleAttestationClaims.shape.submods.shape.container.shape.image_signatures.element),
|
|
201
|
-
cmd_override: z.array(z.unknown()).optional(),
|
|
202
|
-
env_override: z.record(z.string(), z.unknown()).optional(),
|
|
203
|
-
}),
|
|
204
|
-
}),
|
|
205
|
-
});
|
|
206
|
-
/**
|
|
207
|
-
* Local development claims. These cannot establish production identity; production uses native Google claims.
|
|
208
|
-
*/
|
|
209
|
-
export const attestationClaims = z.object({
|
|
210
|
-
iss: z.string().url(),
|
|
211
|
-
/** The relay image's digest. Must be one we published. */
|
|
212
|
-
imageDigest: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
213
|
-
/** Hash of the relay's channel public key, so the token is bound to this connection. */
|
|
214
|
-
channelKeyHash: z.string().regex(/^[0-9a-f]{64}$/),
|
|
215
|
-
exp: z.number().int(),
|
|
216
|
-
iat: z.number().int(),
|
|
217
|
-
}).passthrough();
|
|
218
129
|
const assetMetadata = z.object({
|
|
219
130
|
/** HMAC-SHA256 keyed by a secret stored only in the encrypted payload. */
|
|
220
131
|
fingerprint: z.string().regex(/^[0-9a-f]{64}$/),
|
|
221
132
|
size: z.number().int().nonnegative(),
|
|
222
133
|
}).strict();
|
|
223
134
|
export const bundleMetadata = z.object({
|
|
135
|
+
analysis: analysisRelease.optional(),
|
|
224
136
|
templates: z.record(z.string().min(1), assetMetadata.extend({
|
|
225
137
|
role: z.enum(["required", "optional"]),
|
|
226
138
|
answerFormats: z.array(z.string().min(1)).min(1),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { projectPublicFinding, projectPublicReport, unredactedAnswer, publicReportSchema } from "../analysis-core/contracts/relay-analysis.js";
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
// The pinned distroless base image sets SSL_CERT_FILE to its bundled certificates. The relay accepts exactly that
|
|
2
2
|
// value, so the image works while no operator setting can point the relay at a different trust store.
|
|
3
3
|
export const BASE_CERTIFICATE_FILE = "/etc/ssl/certs/ca-certificates.crt";
|
|
4
|
+
export const runtimeIdentities = Object.freeze({ loader: 65532, engine: 65533 });
|
|
4
5
|
const fixedValues = Object.freeze({ SSL_CERT_FILE: BASE_CERTIFICATE_FILE });
|
|
6
|
+
export const relayRawClockSetting = Object.freeze({ name: "COUNTERFACT_RELAY_RAW_CLOCK", value: "1" });
|
|
7
|
+
export const allowedRuntimeOverrides = Object.freeze({
|
|
8
|
+
[relayRawClockSetting.name]: relayRawClockSetting.value,
|
|
9
|
+
});
|
|
10
|
+
/** Only the clock rollback setting may differ from the signed image's environment. */
|
|
11
|
+
export function allowsRuntimeOverrides(overrides) {
|
|
12
|
+
return Object.entries(overrides).every(([name, value]) => Object.hasOwn(allowedRuntimeOverrides, name) && allowedRuntimeOverrides[name] === value);
|
|
13
|
+
}
|
|
5
14
|
// Native startup consumes these data, so loader checks have the same owner as runtime checks.
|
|
6
15
|
export const runtimeEnvironmentPolicy = Object.freeze({
|
|
7
16
|
fixedValues,
|
|
17
|
+
forwardedValues: Object.entries(allowedRuntimeOverrides).map(([name, value]) => `${name}=${value}`),
|
|
8
18
|
forbiddenPrefixes: ["CF_RELAY_", "ANTHROPIC_", "GOOGLE_AUTH_", "LD_"],
|
|
9
|
-
forbiddenNames: ["GOOGLE_APPLICATION_CREDENTIALS", "NODE_OPTIONS", "
|
|
19
|
+
forbiddenNames: ["GOOGLE_APPLICATION_CREDENTIALS", "NODE_OPTIONS", "NODE_V8_COVERAGE", "NODE_COMPILE_CACHE", "NODE_REDIRECT_WARNINGS", "NODE_DEBUG", "NODE_DEBUG_NATIVE",
|
|
20
|
+
"NODE_USE_ENV_PROXY", "NODE_EXTRA_CA_CERTS",
|
|
10
21
|
"NODE_TLS_REJECT_UNAUTHORIZED", "SSL_CERT_DIR", "GLIBC_TUNABLES", "GCONV_PATH"],
|
|
11
22
|
forbiddenNamesIgnoringCase: ["http_proxy", "https_proxy", "all_proxy"],
|
|
12
23
|
});
|
|
@@ -1,55 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { mapStage, inspectStage, sourceNotesStage, headlinesStage, applyAnalysisDelta, buildAnalysisResult } from "../../analysis-core/index.js";
|
|
4
|
-
import { readFindingQualityConfig } from "./finding-quality/config.js";
|
|
5
|
-
import { buildLocalReport } from "../../adapters/report.js";
|
|
6
|
-
import { runStructures } from "./structural-run.js";
|
|
1
|
+
import { NO_PROGRESS } from "../../analysis-core/stages/execution-ports.js";
|
|
2
|
+
import { runEngineAnalysis } from "../../analysis-core/stages/engine-entry.js";
|
|
7
3
|
import { analysisExecution } from "../../adapters/models.js";
|
|
8
|
-
/**
|
|
4
|
+
/** Product startup selects ports; the shared runner owns the stage order. */
|
|
9
5
|
export async function runAnalysisToEnd(input, model, settings = {}, options = {}) {
|
|
10
|
-
const execution = await analysisExecution(model, options
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (!Object.keys(input.files).length)
|
|
15
|
-
throw new JobError("empty_folder", "No admitted source files were found.");
|
|
16
|
-
let prepared = { repos: [{ key: input.repoKey, kind: "fs", files: input.files, ...(input.root !== undefined ? { root: input.root } : {}) }],
|
|
17
|
-
warnings: input.warnings ?? [], ...(input.fragment ? { mapped: [input.fragment] } : {}) };
|
|
18
|
-
const ports = { readers: [], model: llm, instructions: execution.instructions, requestTools: async () => tools, context: {},
|
|
19
|
-
progress: { checkpoint: async () => { }, assertHeld: () => { }, elapsedMs: () => 0, log: () => { } } };
|
|
20
|
-
for (;;) {
|
|
21
|
-
const delta = await mapStage({ phase: "mapping", state: prepared, settings, execution: { scopeConcurrency: 4, forLocal: true,
|
|
22
|
-
preparation: { capUsd: 20, confirmPrice: false, qualityConfig } } }, ports);
|
|
23
|
-
prepared = applyAnalysisDelta(prepared, delta);
|
|
24
|
-
if (delta.next !== "mapping")
|
|
25
|
-
break;
|
|
26
|
-
}
|
|
27
|
-
prepared = { ...prepared, analysisFlags: { ...flags, sourceNotes: !options.findingsOnly && flags.sourceNotes },
|
|
28
|
-
findingQuality: { config: qualityConfig }, warnings: [...(prepared.warnings ?? []), ...qualityConfig.diagnostics] };
|
|
29
|
-
let phase = "inspecting";
|
|
30
|
-
ports.progress.checkpoint = async (fields, part) => {
|
|
31
|
-
prepared = { ...prepared, ...fields, ...(part ? { passResults: { ...prepared.passResults, [part.index]: part.result } } : {}) };
|
|
32
|
-
};
|
|
33
|
-
while (phase !== "structuring") {
|
|
34
|
-
const step = phase === "inspecting" ? inspectStage : sourceNotesStage;
|
|
35
|
-
const delta = await step({ phase, state: prepared, settings, execution: { scopeConcurrency: 4, passConcurrency: 4, forLocal: true } }, ports);
|
|
36
|
-
prepared = applyAnalysisDelta(prepared, delta);
|
|
37
|
-
phase = delta.next;
|
|
38
|
-
}
|
|
39
|
-
const output = () => buildAnalysisResult({ phase: "persisting", state: prepared, settings, execution: { scopeConcurrency: 4 } });
|
|
40
|
-
// Structural child references index the local display order, including optional ranking.
|
|
41
|
-
const report = buildLocalReport(input.repoKey, output(), prepared);
|
|
42
|
-
if (!options.findingsOnly) {
|
|
43
|
-
const findingsRaw = prepared.findingsRaw;
|
|
44
|
-
const structural = await runStructures(settings, llm, { repos: prepared.repos,
|
|
45
|
-
fragments: [{ repoKey: input.repoKey, fragment: prepared.mapped[0] }],
|
|
46
|
-
graph: report.graph, findings: report.findings, state: prepared }, { execution });
|
|
47
|
-
// Structural child references keep display order; wording uses the original cleaned order.
|
|
48
|
-
prepared = { ...structural.state, findingsRaw };
|
|
49
|
-
}
|
|
50
|
-
prepared = applyAnalysisDelta(prepared, await headlinesStage({ phase: "persisting", state: prepared, settings,
|
|
51
|
-
execution: { scopeConcurrency: 4, forLocal: true } }, ports));
|
|
52
|
-
const result = output();
|
|
53
|
-
await options.resultSink?.(result);
|
|
54
|
-
return buildLocalReport(input.repoKey, result, prepared);
|
|
6
|
+
const execution = await analysisExecution(model, options);
|
|
7
|
+
return runEngineAnalysis({ ...input, settings }, { ...execution,
|
|
8
|
+
progress: NO_PROGRESS,
|
|
9
|
+
}, options);
|
|
55
10
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash, verify } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { MAX_ATTESTATION_BYTES, attestationClaims } from "../contract/
|
|
3
|
+
import { MAX_ATTESTATION_BYTES, attestationClaims } from "../contract/attestation.js";
|
|
4
4
|
import { decodeBase64url } from "../transport/base64url.js";
|
|
5
5
|
export function attestationPolicy(settings, trust) {
|
|
6
6
|
return { ...trust, allowDevelopment: settings.CF_RELAY_DEV === "1" };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PRODUCTION_EVIDENCE_VERSION, RELAY_CHANNEL_AUDIENCE, attestationChallenge } from "../contract/attestation.js";
|
|
2
|
+
import { AttestationError } from "./attestation.js";
|
|
3
|
+
/** Both peers supply bytes from their actual TLS socket; the transport owns freshness and socket reuse. */
|
|
4
|
+
export function channelEvidenceBinding(binding) {
|
|
5
|
+
try {
|
|
6
|
+
attestationChallenge.parse({ version: PRODUCTION_EVIDENCE_VERSION, challenge: binding.challenge });
|
|
7
|
+
if (!(binding.exportedKeyMaterial instanceof Uint8Array) || binding.exportedKeyMaterial.byteLength !== 32)
|
|
8
|
+
throw new Error();
|
|
9
|
+
return { audience: RELAY_CHANNEL_AUDIENCE,
|
|
10
|
+
nonces: [Buffer.from(binding.exportedKeyMaterial).toString("base64url"), binding.challenge] };
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
throw new AttestationError("Invalid production attestation channel binding");
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -4,6 +4,8 @@ import { consoleSchemeAllowed } from "../contract/console-url.js";
|
|
|
4
4
|
import { cliApiMessages } from "../contract/cli-api-messages.js";
|
|
5
5
|
import { emailSignInMessages } from "../contract/email-sign-in-messages.js";
|
|
6
6
|
import { CLI_BODY_LIMIT } from "../cli/api-types.js";
|
|
7
|
+
import { findingNumberParamsSchema } from "../contract/findings.js";
|
|
8
|
+
import { claimFixRequestBodySchema, claimFixRequestParamsSchema } from "../contract/fix-requests.js";
|
|
7
9
|
export { DEFAULT_CONSOLE_URL as DEFAULT_URL } from "../setup-pings/client.js";
|
|
8
10
|
export class ApiError extends Error {
|
|
9
11
|
status;
|
|
@@ -36,6 +38,14 @@ function retryAfterMs(value, rejectNegativeSeconds = false) {
|
|
|
36
38
|
return Number.isFinite(date) ? Math.max(0, date - Date.now()) : undefined;
|
|
37
39
|
}
|
|
38
40
|
function requestBody(path, body, emailRoute) {
|
|
41
|
+
if (path === "fix-requests" && body === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
const lookup = /^projects\/([^/]+)\/findings\/([^/]+)$/.exec(path);
|
|
44
|
+
if (lookup && body === undefined && findingNumberParamsSchema.safeParse({ projectId: lookup[1], seq: lookup[2] }).success)
|
|
45
|
+
return undefined;
|
|
46
|
+
const claim = /^fix-requests\/([^/]+)\/claim$/.exec(path);
|
|
47
|
+
if (claim && claimFixRequestParamsSchema.safeParse({ id: claim[1] }).success && claimFixRequestBodySchema.safeParse(body).success)
|
|
48
|
+
return {};
|
|
39
49
|
if ((path === "balance" || path === "checks/mode" || /^findings\/[a-zA-Z0-9_-]+$/.test(path)) && body === undefined)
|
|
40
50
|
return undefined;
|
|
41
51
|
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
@@ -95,7 +105,7 @@ export class ApiClient {
|
|
|
95
105
|
throw new Error("COUNTERFACT_URL must be an HTTP or HTTPS address without credentials or query fields.");
|
|
96
106
|
this.baseUrl = url.href.replace(/\/+$/, "");
|
|
97
107
|
}
|
|
98
|
-
async request(path, body, authenticated = true) {
|
|
108
|
+
async request(path, body, authenticated = true, options = {}) {
|
|
99
109
|
const emailRoute = Object.hasOwn(emailRoutes, path) ? emailRoutes[path] : undefined;
|
|
100
110
|
const throwIfAborted = () => {
|
|
101
111
|
if (emailRoute && this.signal?.aborted)
|
|
@@ -119,7 +129,7 @@ export class ApiClient {
|
|
|
119
129
|
}
|
|
120
130
|
const controller = new AbortController();
|
|
121
131
|
const cancel = () => controller.abort(this.signal?.reason);
|
|
122
|
-
const timeout = setTimeout(() => controller.abort(), 120_000);
|
|
132
|
+
const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 120_000);
|
|
123
133
|
timeout.unref();
|
|
124
134
|
this.signal?.addEventListener("abort", cancel, { once: true });
|
|
125
135
|
try {
|
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import { RELAY_MAX_FRAME_BYTES, deliveryReceipt, relayAnswer, relayAnswerFrame, relayRequest } from "../contract/messages.js";
|
|
2
|
+
import { unredactedAnswer } from "../contract/public-report.js";
|
|
2
3
|
export class RelayConnectionError extends Error {
|
|
3
4
|
name = "RelayConnectionError";
|
|
4
5
|
constructor() { super("Relay connection failed"); }
|
|
5
6
|
}
|
|
7
|
+
/** Both carriers retry the same confirmation, never another paid request. */
|
|
8
|
+
export async function acknowledgeDelivery(options, confirmation) {
|
|
9
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
10
|
+
options.valid();
|
|
11
|
+
const receipt = await options.exchange("/delivery", confirmation, 1024);
|
|
12
|
+
if (receipt.status === 200) {
|
|
13
|
+
deliveryReceipt.parse(receipt.body);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
throw new RelayConnectionError();
|
|
18
|
+
}
|
|
6
19
|
/** Calls and delivery retries share the authenticated transport and run in input order. */
|
|
7
20
|
export function createRelayExchange(options) {
|
|
8
21
|
let queue = Promise.resolve();
|
|
@@ -18,23 +31,14 @@ export function createRelayExchange(options) {
|
|
|
18
31
|
const frame = legacy?.success ? { answer: legacy.data, delivery: undefined } : relayAnswerFrame.parse(response.body);
|
|
19
32
|
if (frame.answer.nonce !== request.nonce)
|
|
20
33
|
throw new Error();
|
|
34
|
+
if (frame.answer.ok)
|
|
35
|
+
unredactedAnswer(frame.answer);
|
|
21
36
|
if (frame.delivery) {
|
|
22
37
|
const { confirmation } = frame.delivery;
|
|
23
38
|
if (confirmation.callId !== request.callId)
|
|
24
39
|
throw new Error();
|
|
25
40
|
// The relay enforces its deadline on its own clock; local clock drift must not discard a paid answer.
|
|
26
|
-
|
|
27
|
-
for (let attempt = 0; attempt < 2; attempt++) {
|
|
28
|
-
options.valid();
|
|
29
|
-
const receipt = await options.exchange("/delivery", confirmation, 1024);
|
|
30
|
-
if (receipt.status === 200) {
|
|
31
|
-
deliveryReceipt.parse(receipt.body);
|
|
32
|
-
acknowledged = true;
|
|
33
|
-
break;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
if (!acknowledged)
|
|
37
|
-
throw new Error();
|
|
41
|
+
await acknowledgeDelivery(options, confirmation);
|
|
38
42
|
}
|
|
39
43
|
return frame.answer;
|
|
40
44
|
}
|
package/dist/gatekeeper/model.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { unredactedAnswer } from "../contract/public-report.js";
|
|
2
3
|
import { executionRequest } from "../analysis-core/contracts/requests.js";
|
|
3
4
|
export class ModelConfigurationError extends Error {
|
|
4
5
|
name = "ModelConfigurationError";
|
|
@@ -62,7 +63,7 @@ export function relayModel(options) {
|
|
|
62
63
|
catch {
|
|
63
64
|
// A failed counter must not discard an answer or expose the sink's error text.
|
|
64
65
|
}
|
|
65
|
-
return reply
|
|
66
|
+
return unredactedAnswer(reply);
|
|
66
67
|
},
|
|
67
68
|
};
|
|
68
69
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { constants, verify, X509Certificate } from "node:crypto";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { GOOGLE_ATTESTATION_ISSUER, MAX_ATTESTATION_BYTES, PRODUCTION_EVIDENCE_VERSION,
|
|
3
|
+
import { GOOGLE_ATTESTATION_ISSUER, MAX_ATTESTATION_BYTES, PRODUCTION_EVIDENCE_VERSION, evidenceBinding, googleAttestationClaims, observedAttestationClaims, probeAttestationClaims, productionEvidence } from "../contract/attestation.js";
|
|
4
4
|
import { decodeBase64url } from "../transport/base64url.js";
|
|
5
5
|
import { isApprovedHardware } from "./trust/hardware.js";
|
|
6
6
|
import { AttestationError } from "./attestation.js";
|
|
7
7
|
import { validateCertificatePath } from "./certificate-path.js";
|
|
8
8
|
import { validateProductionTrust, validateWorkloadPolicy } from "./trust/policy.js";
|
|
9
|
+
import { channelEvidenceBinding } from "./channel-binding.js";
|
|
10
|
+
export { channelEvidenceBinding } from "./channel-binding.js";
|
|
9
11
|
/** A published client needs every trust constraint configured before it can connect to production. */
|
|
10
12
|
export function assertProductionTrustConfigured(value) {
|
|
11
13
|
try {
|
|
@@ -20,19 +22,6 @@ const headerSchema = z.object({
|
|
|
20
22
|
alg: z.literal("RS256"), typ: z.literal("JWT").optional(), kid: z.string().max(256).optional(),
|
|
21
23
|
x5c: z.array(z.string().min(1).max(8192)).min(1).max(5),
|
|
22
24
|
}).strict();
|
|
23
|
-
/** Both peers supply bytes from their actual TLS socket; the transport owns freshness and socket reuse. */
|
|
24
|
-
export function channelEvidenceBinding(binding) {
|
|
25
|
-
try {
|
|
26
|
-
attestationChallenge.parse({ version: PRODUCTION_EVIDENCE_VERSION, challenge: binding.challenge });
|
|
27
|
-
if (!(binding.exportedKeyMaterial instanceof Uint8Array) || binding.exportedKeyMaterial.byteLength !== 32)
|
|
28
|
-
throw new Error();
|
|
29
|
-
return { audience: RELAY_CHANNEL_AUDIENCE,
|
|
30
|
-
nonces: [Buffer.from(binding.exportedKeyMaterial).toString("base64url"), binding.challenge] };
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
throw new AttestationError("Invalid production attestation channel binding");
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
25
|
/** The caller's binding comes from the channel/health/action owner, never from the token being verified. */
|
|
37
26
|
export async function verifyProductionEvidence(token, binding, trust, now = Math.floor(Date.now() / 1000)) {
|
|
38
27
|
let validated;
|
|
@@ -57,6 +46,20 @@ export async function verifyWorkloadEvidence(token, binding, policy, now = Math.
|
|
|
57
46
|
}
|
|
58
47
|
return verifyEvidence(token, binding, validated, now);
|
|
59
48
|
}
|
|
49
|
+
/** Bootstrap may bound this candidate before verification; it is never an authenticated time sample. */
|
|
50
|
+
export function unverifiedEvidenceIssueTime(token) {
|
|
51
|
+
try {
|
|
52
|
+
productionEvidence.parse({ version: PRODUCTION_EVIDENCE_VERSION, token });
|
|
53
|
+
const candidate = JSON.parse(decodeBase64url(token.split(".")[1]).toString("utf8"));
|
|
54
|
+
const iat = candidate?.iat;
|
|
55
|
+
if (typeof iat !== "number" || !Number.isSafeInteger(iat) || !Number.isSafeInteger(iat * 1000))
|
|
56
|
+
throw new Error();
|
|
57
|
+
return iat;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
throw new AttestationError("Malformed production attestation evidence");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
60
63
|
async function authenticate(token, binding, roots, now) {
|
|
61
64
|
try {
|
|
62
65
|
productionEvidence.parse({ version: PRODUCTION_EVIDENCE_VERSION, token });
|
|
@@ -99,14 +102,17 @@ function validateClaimsBinding(claims, binding, now) {
|
|
|
99
102
|
}
|
|
100
103
|
/**
|
|
101
104
|
* Reviewed roots authenticate probe facts; this result cannot substitute for workload admission.
|
|
102
|
-
*
|
|
103
|
-
*
|
|
105
|
+
* Only the contract owner's probe shape may relax missing signature/support arrays. Caller schemas
|
|
106
|
+
* can impose stricter validation, but freshness, binding, issuer and all other claim rules stay fixed.
|
|
104
107
|
*/
|
|
105
108
|
export async function observeGoogleEvidence(token, binding, roots, now = Math.floor(Date.now() / 1000), claimsSchema = observedAttestationClaims) {
|
|
106
109
|
const payload = await authenticate(token, binding, roots, now);
|
|
107
110
|
try {
|
|
108
|
-
const
|
|
111
|
+
const rawClaims = JSON.parse(payload.toString("utf8"));
|
|
112
|
+
const claims = probeAttestationClaims.parse(rawClaims);
|
|
109
113
|
validateClaimsBinding(claims, binding, now);
|
|
114
|
+
// Isolate even passthrough fields from caller mutation and discard any rewritten parser output.
|
|
115
|
+
claimsSchema.parse(structuredClone(rawClaims));
|
|
110
116
|
return { claims };
|
|
111
117
|
}
|
|
112
118
|
catch {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { enginePin } from "../../contract/engine.js";
|
|
1
2
|
import { X509Certificate } from "node:crypto";
|
|
2
3
|
import { z } from "zod";
|
|
3
4
|
import { hardwareModels } from "./hardware.js";
|
|
@@ -30,7 +31,9 @@ export const workloadPolicy = z.object({
|
|
|
30
31
|
}).strict();
|
|
31
32
|
const productionTrust = workloadPolicy.extend({
|
|
32
33
|
imageDigests: z.array(z.string().regex(/^sha256:[0-9a-f]{64}$/)).min(1),
|
|
33
|
-
})
|
|
34
|
+
engineReleases: z.array(z.strictObject({ imageDigest: z.string().regex(/^sha256:[0-9a-f]{64}$/), engine: enginePin })).min(1).optional(),
|
|
35
|
+
}).refine(value => !value.engineReleases || value.engineReleases.every(release => value.imageDigests.includes(release.imageDigest)) &&
|
|
36
|
+
new Set(value.engineReleases.map(release => release.imageDigest)).size === value.engineReleases.length, "Engine release image differs");
|
|
34
37
|
export function validateWorkloadPolicy(value) {
|
|
35
38
|
return workloadPolicy.parse(value);
|
|
36
39
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const maxBytes = 64 * 1024;
|
|
2
|
+
export function kmsKeyName(value) {
|
|
3
|
+
if (!/^projects\/[a-z][a-z0-9-]{4,62}\/locations\/[a-z0-9-]+\/keyRings\/[A-Za-z0-9_-]+\/cryptoKeys\/[A-Za-z0-9_-]+$/.test(value)) {
|
|
4
|
+
throw new Error("Invalid KMS key configuration");
|
|
5
|
+
}
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
export function kmsKeyVersionName(value) {
|
|
9
|
+
kmsKeyForVersion(value);
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
export function kmsKeyForVersion(value) {
|
|
13
|
+
const match = /^(.*)\/cryptoKeyVersions\/[1-9][0-9]*$/.exec(value);
|
|
14
|
+
if (!match)
|
|
15
|
+
throw new Error("Invalid KMS key configuration");
|
|
16
|
+
return kmsKeyName(match[1]);
|
|
17
|
+
}
|
|
18
|
+
export function kmsBase64(value) {
|
|
19
|
+
if (typeof value !== "string" || value.length < 4 || value.length > maxBytes)
|
|
20
|
+
throw new Error();
|
|
21
|
+
const bytes = Buffer.from(value, "base64");
|
|
22
|
+
if (bytes.toString("base64") !== value)
|
|
23
|
+
throw new Error();
|
|
24
|
+
return bytes;
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@counterfact-labs/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
|
+
"homepage": "https://counterfactlabs.com",
|
|
5
|
+
"relaySource": "https://github.com/counterfact-labs/sealed-relay",
|
|
4
6
|
"type": "module",
|
|
5
7
|
"files": [
|
|
6
8
|
"dist/**/*.js",
|
|
@@ -21,7 +23,6 @@
|
|
|
21
23
|
"test": "tsx --test ${TEST_SHARD:+--test-shard=$TEST_SHARD} --test-concurrency=4 --test-timeout=600000 \"core/**/*.test.ts\" \"adapters/**/*.test.ts\" \"cli/**/*.test.ts\" \"bench/**/*.test.ts\" \"bundle/**/*.test.ts\" \"contract/**/*.test.ts\" \"gatekeeper/**/*.test.ts\" \"relay/**/*.test.ts\" \"transport/**/*.test.ts\" \"packages/core/src/**/*.test.ts\" \"packages/core/*.test.ts\" \"packages/setup-pings/src/**/*.test.ts\" \"scripts/**/*.test.ts\"",
|
|
22
24
|
"build:core": "npm run build --workspace @counterfact-labs/analysis-core",
|
|
23
25
|
"build:setup-pings": "npm run build --workspace @counterfact-labs/setup-pings",
|
|
24
|
-
"prepare": "npm run build:core && npm run build:setup-pings",
|
|
25
26
|
"pretest": "npm run build:core && npm run build:setup-pings",
|
|
26
27
|
"release:core": "tsx scripts/release-core.ts",
|
|
27
28
|
"build:cli": "npm run build:setup-pings && tsx scripts/build-cli.ts",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"tsx": "4.23.15",
|
|
45
46
|
"typescript": "6.0.3",
|
|
46
47
|
"typescript-eslint": "8.64.0",
|
|
47
|
-
"@counterfact-labs/analysis-core": "0.8.
|
|
48
|
+
"@counterfact-labs/analysis-core": "0.8.2",
|
|
48
49
|
"@counterfact-labs/setup-pings": "0.1.0"
|
|
49
50
|
},
|
|
50
51
|
"workspaces": [
|
package/dist/adapters/quality.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { readFindingQualityConfig as readSharedConfig } from "../analysis-core/analysis/finding-quality/config.js";
|
|
2
|
-
import { readableRequestTools } from "./instructions.js";
|
|
3
|
-
// Local startup has one provider and has not approved recall or imported code evidence.
|
|
4
|
-
export function readLocalQualityConfig(settings, tools = readableRequestTools()) {
|
|
5
|
-
return readSharedConfig(settings, tools, { codeInputs: false, recall: false, secondOpinion: false });
|
|
6
|
-
}
|
package/dist/adapters/report.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { rankFindings } from "../analysis-core/analysis/finding-quality/policy.js";
|
|
2
|
-
import { attachHeadlineResults } from "../analysis-core/analysis/headlines/attachment.js";
|
|
3
|
-
/** The local view keeps presentation ranking and reading diagnostics beside the shared result. */
|
|
4
|
-
export function buildLocalReport(repoKey, result, state) {
|
|
5
|
-
const quality = result.findingQuality;
|
|
6
|
-
const checked = { ...(state.findingCheck?.state?.result ?? { kept: result.findings, dropped: [], warnings: [] }) };
|
|
7
|
-
// Source explanations refresh the audit without changing the saved checker decision.
|
|
8
|
-
if (quality?.assessments && checked.qualityAudit)
|
|
9
|
-
checked.qualityAudit = {
|
|
10
|
-
coverage: quality.coverage ?? [], verdicts: quality.verdicts ?? [], assessments: quality.assessments,
|
|
11
|
-
...(quality.shadow ? { shadow: quality.shadow } : {}),
|
|
12
|
-
};
|
|
13
|
-
const attached = attachHeadlineResults(result.findings, result.structures, result.findingHeadlines ?? [], result.findingHeadlineDiagnostics);
|
|
14
|
-
const wording = new Map(attached.rows.filter(row => row.target === "finding")
|
|
15
|
-
.map(row => [row.index, { headline: row.headline, ifLeft: row.ifLeft }]));
|
|
16
|
-
const structureWording = new Map(attached.rows.filter(row => row.target === "structure")
|
|
17
|
-
.map(row => [row.index, { headline: row.headline, ifLeft: row.ifLeft }]));
|
|
18
|
-
const structures = structureWording.size ? result.structures.map((proposal, index) => structureWording.has(index)
|
|
19
|
-
? { ...proposal, ...structureWording.get(index) } : proposal) : result.structures;
|
|
20
|
-
const findings = wording.size
|
|
21
|
-
? result.findings.map((finding, index) => wording.has(index) ? { ...finding, ...wording.get(index) } : finding)
|
|
22
|
-
: result.findings;
|
|
23
|
-
const ranked = state.findingQuality?.config.switches.ranking ? rankFindings(findings, quality?.assessments ?? []) : undefined;
|
|
24
|
-
return { repoKey, findings: ranked?.ordered ?? findings, structures, graph: result.graph, warnings: result.warnings,
|
|
25
|
-
...(attached.diagnostics ? { findingHeadlineDiagnostics: attached.diagnostics } : {}),
|
|
26
|
-
skippedFiles: state.inspectPlan?.skipped ?? [], passes: state.inspectPlan?.passes.length ?? 1, findingCheck: checked,
|
|
27
|
-
...(ranked ? { ranking: { defaultIds: ranked.defaultIds, hiddenIds: ranked.hiddenIds, emptyMessage: ranked.emptyMessage } } : {}),
|
|
28
|
-
};
|
|
29
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a,b,c}from"../chunks/OFBJNHC6.js";export{c as analysisFlagsOf,a as readAnalysisFlags,b as readParallelPassSettings};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as a,o as b,p as c,q as d,r as e,s as f}from"../../chunks/DRGDIIFA.js";import"../../chunks/6YCABS5T.js";import"../../chunks/SL27GMEN.js";import"../../chunks/3CKW5JIF.js";import"../../chunks/STZOC7LN.js";import"../../chunks/MJGB25S5.js";import"../../chunks/UEWL3GMQ.js";import"../../chunks/OFBJNHC6.js";import"../../chunks/3227KXHF.js";import"../../chunks/HPIAEQHE.js";import"../../chunks/74FPPPIG.js";import"../../chunks/EH3QQ3T4.js";import"../../chunks/JKWTHRUR.js";import"../../chunks/FSLWD2PE.js";import"../../chunks/JF4GYMOZ.js";import"../../chunks/3GUKUEEJ.js";import"../../chunks/T5TREZCQ.js";import"../../chunks/724WZMYW.js";export{f as assertFindingQualityPrompts,b as findingAnalysisTemplate,e as findingQualityConfigOf,a as findingQualityPromptNames,c as plannedFindingQualityCalls,d as readFindingQualityConfig};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as a,j as b}from"../../chunks/MXXNED6N.js";import"../../chunks/U5HOEVPE.js";import"../../chunks/HPIAEQHE.js";import"../../chunks/74FPPPIG.js";import"../../chunks/EH3QQ3T4.js";import"../../chunks/JKWTHRUR.js";import"../../chunks/FSLWD2PE.js";import"../../chunks/JF4GYMOZ.js";import"../../chunks/3GUKUEEJ.js";import"../../chunks/T5TREZCQ.js";import"../../chunks/724WZMYW.js";export{a as assessFindings,b as rankFindings};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a,b,c,d}from"../../chunks/O652FQQH.js";import"../../chunks/57M4OQJM.js";import"../../chunks/IBCFGUHI.js";import"../../chunks/HPIAEQHE.js";import"../../chunks/74FPPPIG.js";import"../../chunks/EH3QQ3T4.js";import"../../chunks/JKWTHRUR.js";import"../../chunks/FSLWD2PE.js";import"../../chunks/JF4GYMOZ.js";import"../../chunks/3GUKUEEJ.js";import"../../chunks/T5TREZCQ.js";import"../../chunks/724WZMYW.js";export{d as attachHeadlineResults,c as attachHeadlineRows,a as headlineTargetFingerprint,b as headlineWordingAt};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as b,b as c}from"../../chunks/FTODBFQW.js";import{c as a}from"../../chunks/ZAA44GPI.js";import"../../chunks/3227KXHF.js";import"../../chunks/O652FQQH.js";import"../../chunks/57M4OQJM.js";import"../../chunks/IBCFGUHI.js";import"../../chunks/HPIAEQHE.js";import"../../chunks/74FPPPIG.js";import"../../chunks/EH3QQ3T4.js";import"../../chunks/JKWTHRUR.js";import"../../chunks/FSLWD2PE.js";import"../../chunks/JF4GYMOZ.js";import"../../chunks/3GUKUEEJ.js";import"../../chunks/T5TREZCQ.js";import"../../chunks/724WZMYW.js";export{b as buildHeadlineInput,c as headlineInputHash,a as headlineRequest};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as C,b as F}from"./STZOC7LN.js";import{a as c}from"./MJGB25S5.js";import{z as t}from"zod";var O=Object.freeze(["CF_MULTI_PASS","CF_SPLIT_CHECK","CF_FINDING_CHECK","CF_SOURCE_NOTES","CF_PARALLEL_PASSES","CF_PASS_CONCURRENCY","CF_PARALLEL_SCOPE_CHECK","CF_FINDING_QUALITY","CF_FINDING_FULL_CONTEXT","CF_FINDING_PRECISION_RULES","CF_PROMPT_AGREE","CF_FINDING_SECOND_OPINION","CF_FINDING_RANKING","CF_FINDING_SEMANTIC_MATCHING","CF_FINDING_CODE_INPUTS","CF_FINDING_RECALL","CF_FINDING_RECALL_VARIANT","CF_FINDING_SECOND_OPINION_MODEL","CF_FINDING_SECOND_OPINION_PROVIDER","CF_FIX_EXPECTED_OUTCOME","CF_UNTRUSTED_CONTENT_CHECK","CF_FINDING_BETTER_AS_CODE","CF_CODE_AGENTS","CF_CODE_AGENTS_MODEL","CF_FINDING_DEDUPE","CF_ANALYSIS_IMPORTED_AGENTS","CF_RECALL_SIGNALS","CF_READING_NOTE_AGENT_ONLY","CF_SPLIT_HELPER_TOOLS","CF_CODE_PROMPT_LOADERS","CF_CODE_PROMPT_FUNCTIONS","CF_READING_PRIORITY","CF_LOCAL_SYMLINK_GUARD","CF_IMPORT_EXAMPLE_FILTER","CF_IMPORT_OUTSIDE_LOADERS","CF_SECRET_SCAN","CF_RESPECT_GITIGNORE","CF_IMPORT_COVERAGE","CF_IMPORT_MANIFEST","CF_IMPORT_SCOPED_SCAN","CF_IMPORT_INCLUDE_EXAMPLES","CF_IMPORT_WEAK_CODE_FALLBACK","CF_REFUSE_TOO_LARGE","CF_FINDING_HEADLINES","CF_IMPORT_LAYOUTS","CF_DISCOVERY_SKILLS","CF_IMPORT_CALLS","CF_PROMPT_CACHE","CF_MODEL_READER","CF_LEGACY_TOOL_LISTS"]),a=O.filter(e=>e!=="CF_IMPORT_OUTSIDE_LOADERS"&&e!=="CF_SECRET_SCAN"&&e!=="CF_RESPECT_GITIGNORE"&&e!=="CF_IMPORT_COVERAGE"&&e!=="CF_IMPORT_MANIFEST"&&e!=="CF_IMPORT_SCOPED_SCAN"&&e!=="CF_IMPORT_INCLUDE_EXAMPLES"&&e!=="CF_IMPORT_WEAK_CODE_FALLBACK"&&e!=="CF_REFUSE_TOO_LARGE");function N(e,_="request"){return Object.freeze(Object.fromEntries((_==="saved"?O:a).filter(i=>Object.hasOwn(e,i)).map(i=>[i,e[i]])))}var p=t.partialRecord(t.enum(a),t.string()),E=t.lazy(()=>t.union([t.string(),t.number(),t.boolean(),t.null(),t.array(E),t.record(t.string(),E)])),l=t.object({data:t.record(t.string(),E),settings:p,maxInputBytes:t.number().int().positive().optional()}).strict(),S=t.string().min(1).max(128).regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]*$/),T=t.object({maxTokens:t.number().int().positive().optional(),effort:t.enum(["low","medium","high","max"]).optional(),thinking:t.literal("disabled").optional(),promptCache:t.boolean().optional()}).strict(),R=t.object({template:t.string().min(1),inputs:l,answerFormat:t.string().min(1),model:S,limits:T.optional()}).strict();function P(e,_={},o){let i={data:e.inputs,settings:N(_),...o===void 0?{}:{maxInputBytes:o}};return R.parse({...e,answerFormat:Object.hasOwn(r,e.template)?A(e.template,e.answerFormat,_):e.answerFormat,limits:{...e.limits,promptCache:c(_,{template:e.template},e.model).enabled},inputs:JSON.parse(JSON.stringify(i))})}var n=(e,..._)=>Object.freeze({role:e,answerFormats:Object.freeze(_)}),s=F().map(e=>e.name),r=Object.freeze({"derive-findings":n("required",...s),"derive-findings-legacy":n("required",...s),"derive-findings-no-outcome":n("required",...s),"derive-findings-legacy-no-outcome":n("required",...s),"benchmark-judge":n("required","judge"),"judge-code-prompt":n("optional","codeJudge"),"derive-structure":n("optional","structures"),"structure-recheck":n("optional","recheck"),"derive-shape":n("optional","shape"),"scope-items":n("optional","structureScope"),"scope-findings":n("optional","scope"),"check-findings":n("optional","check"),"check-findings-precision-v1":n("optional","check"),"second-opinion":n("optional","opinion"),"explain-sources":n("optional","sourceNotes"),"finding-headlines":n("optional","findingHeadlines")});function D(){return r}function f(e,_,o){let i=o??(e==="derive"?"derive-findings":"check-findings");if(!Object.keys(r).filter(I=>r[I].answerFormats.includes(e==="derive"?"findings":"check")).includes(i))throw new Error("Unknown analysis template");return e==="derive"&&!C(_).switches.expectedOutcome&&!i.endsWith("-no-outcome")?`${i}-no-outcome`:i}function A(e,_,o){let i=_==="findings"?C(o).name:_;if(!Object.hasOwn(r,e)||!r[e].answerFormats.includes(i))throw new Error("Unsupported template answer format");return i}function g(e,_,o){if(o(_),!Object.hasOwn(r,e)||r[e].role!=="optional")throw _}export{O as a,N as b,l as c,S as d,T as e,R as f,P as g,D as h,f as i,A as j,g as k};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var n=Object.freeze({"benchmark-judge":"score_match","judge-code-prompt":"judge-code-prompt","derive-findings":"derive_findings","derive-findings-legacy":"derive_findings","derive-findings-no-outcome":"derive_findings","derive-findings-legacy-no-outcome":"derive_findings","derive-structure":"derive_structure","structure-recheck":"structure_recheck","derive-shape":"derive_shape","scope-items":"scope_check_structure","scope-findings":"scope_check","explain-sources":"explain_sources","finding-headlines":"finding_headlines","check-findings":"finding_check","check-findings-precision-v1":"finding_check","second-opinion":"finding_second_opinion"});function c(e){if(!Object.hasOwn(n,e))throw new Error("Unknown analysis template");return n[e]}function s(e){return Object.fromEntries(Object.entries(e).map(([i,r])=>[i,{...r,route:c(i)}]))}export{c as a,s as b};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{h as G}from"./NCWEOJVJ.js";import{Aa as $,Ba as P,Ca as w,Fa as M,Ga as y,Ta as D,a as l,b as N,e as T,ga as E,o as C,qa as I,u as R,wa as F,za as _}from"./HPIAEQHE.js";import{a as b,c as x}from"./T5TREZCQ.js";var k="Some of this agent's files weren't read, so findings may be missing.";var B=r=>r.CF_READING_PRIORITY!=="0";var U=new Set(["system prompt","soul","knowledge","config","tools","mcp"]);function L(r){let t=new Set;for(let s of r.nodes)for(let f of s.files??[])U.has(f.role)&&t.add(f.path);let n=new Set(r.edges.filter(s=>s.kind==="delegates").map(s=>s.to));for(let s of r.nodes)n.has(s.id)&&s.sourceRef&&t.add(s.sourceRef.path);return t}function V(r){return new Set([...r.nodes,...r.edges].flatMap(t=>t.sourceRef?[t.sourceRef.path]:[]))}var p=6e4,j=r=>{if(r.length<=p)return r;let t=r.endsWith(E)?E:"";return(t?r.slice(0,-t.length):r).slice(0,p)+t};function Z(r,t){let n=[...r].filter(s=>t[s]!==void 0&&j(t[s])!==t[s]).sort();return n.length===0?null:`${n.length} core file${n.length===1?" was":"s were"} longer than ${p/1e3} KB, so only the first ${p/1e3} KB ${n.length===1?"was":"were"} read: ${n.join(", ")}`}var A=r=>r.split("/").slice(0,-1).join("/"),Y=/(agent|prompt|tool|llm|model)/i,z=2.5;function K(r,t){if(!B(r))return{enabled:!1,tierOf:()=>6};if(t.repos?.some(e=>e.kind==="github"&&b(e.root)))return v(r,t,t.repos);let n=t.scopes??(T(r)?G(r,t.paths):void 0),s=t.graph?L(t.graph):new Set,f=new Set(t.graph?.nodes.flatMap(e=>(e.files??[]).filter(o=>o.role==="code"&&l(o.path)).map(o=>o.path))??[]),i=new Set(t.graph?.nodes.flatMap(e=>(e.files??[]).filter(o=>o.role==="system prompt").map(o=>o.path))??[]),a=e=>N(e)&&(I.includes(e.split("/").pop().toLowerCase())||/(^|\/)system_prompt_[^/]+\.md$/i.test(e)||y.test(e)),c=e=>{if(s.has(e))return 1;if(f.has(e))return 2;let o=P(r,e,n),d=R(o,{nested:!0});if(d?.reference)return 5;if(d?.definition||F.test(o))return 4;if(d||/(^|\/)(docs?|references)\//i.test(o)||$.test(e.split("/").pop()))return 5;if(_(o)||w(r,e,n)&&_(e.split("/").pop())||a(e))return 1;if(l(e)){if(Y.test(e))return z;if(M.test(e))return 3}return 6};for(let e of t.paths)c(e)===1&&a(e)&&i.add(e);let m=[...i].flatMap(e=>{let o=A(e);return[o,...o?[A(o)]:[]]}),h=e=>l(e)&&m.some(o=>A(e)===o),u=new Map(t.paths.map(e=>{let o=c(e);return[e,o>2&&h(e)?2:o]})),g=[...u].filter(([e,o])=>o<=2&&l(e)).map(([e])=>e),O=D(Object.fromEntries(g.flatMap(e=>t.files?.[e]===void 0?[]:[[e,t.files[e]]])),t.paths);for(let e of O)l(e)&&!R(P(r,e,n),{nested:!0})&&(u.get(e)??6)>2&&u.set(e,2);return{enabled:!0,tierOf:e=>u.get(e)??c(e)}}function v(r,t,n){let s=new Map;for(let f of n){let i=f.kind==="github"?f.root:void 0,a=t.paths.filter(e=>f.files?.[e]!==void 0&&!s.has(e)),c=e=>x(e,i)??(f.files?.[e]!==void 0?e:null),m=e=>{let o=e?c(e.path):null;return o===null?null:{path:o}},h=t.graph&&{nodes:t.graph.nodes.map(e=>({...e,sourceRef:m(e.sourceRef),files:e.files?.flatMap(o=>{let d=c(o.path);return d===null?[]:[{...o,path:d}]})})),edges:t.graph.edges.map(e=>({...e,sourceRef:m(e.sourceRef)}))},u=a.flatMap(e=>{let o=c(e);return o===null?[]:[o]}),g=Object.fromEntries(a.flatMap(e=>{let o=c(e);return o===null||t.files?.[e]===void 0?[]:[[o,t.files[e]]]})),O=K(r,{paths:u,files:g,graph:h});for(let e of a)s.set(e,O.tierOf(c(e)??e))}return{enabled:!0,tierOf:f=>s.get(f)??6}}function H(r,t){return r.enabled?t.filter(n=>["too-large","total","allowance"].includes(n.reason)&&r.tierOf(n.path)<3).map(n=>n.path):[]}function W(r){return r.slice(0,3)}function q(r,t=!1){let n=W(r);if(!n.length)return;let s=t?". "+k:", so some findings may be missing";return`${n.join(", ")} ${n.length===1?"was":"were"} left out${s}`}function ue(r,t){return q(H(r,t))}function de(r,t){return r.enabled&&r.tierOf(t)<3}function me(r,t,n){let s=C.sourceFetch.codeFileBytes;return r.enabled&&r.tierOf(t)<3&&l(t)&&n>s?{size:s,readBytes:s}:{size:n}}function pe(r,t){return r.enabled&&r.tierOf(t)<3&&l(t)}function S(r){return r.split("/").length-1}function he(r,t,n){return w(r,t,n)?0:M.test(t)?1+Math.min(S(t),3)/10:S(t)<=2?2:S(t)<=4?3:4}function ge(r,t){return(r.tier??0)-(t.tier??0)||r.score-t.score||r.size-t.size}function Oe(r,t,n,s){return[...r].sort((f,i)=>(s?.enabled?s.tierOf(f)-s.tierOf(i):0)||Number(n.has(i))-Number(n.has(f))||t[f].length-t[i].length||(f<i?-1:1))}function Re(r,t,n,s){return[...r].sort((f,i)=>(s?.enabled?s.tierOf(f.path)-s.tierOf(i.path):0)||Number(t.has(i.path))-Number(t.has(f.path))||Number(n.has(i.path))-Number(n.has(f.path))||f.text.length-i.text.length)}export{B as a,L as b,V as c,j as d,Z as e,K as f,H as g,W as h,q as i,ue as j,de as k,me as l,pe as m,he as n,ge as o,Oe as p,Re as q};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as U}from"./6YCABS5T.js";import{c as V}from"./SL27GMEN.js";import{i as b,j as v}from"./3CKW5JIF.js";import{c as y}from"./MJGB25S5.js";import{a as K}from"./OFBJNHC6.js";import{a as u,b as w}from"./3227KXHF.js";import{ub as Y}from"./HPIAEQHE.js";import{c as k,f as M}from"./JKWTHRUR.js";var l=u.chat,s=8,I=1,W=40,N=6e4,S=16e3,Q=8e4,f=4e3,q=1536,R=8192,B=1024;function h(e){return R+e*q+B}function A(e,t="legacy"){return t==="whole-file"?N+Q+f*e+4e3*4:N+(S+f)*e+4e3*2}function pe(e,t,o,n,c="legacy"){if(!o||t===0)return null;let r=Math.ceil(t/s),i=1+I,p=h(t)+(R+B)*(r-1),_={template:n};if(c==="whole-file"){let F=Math.floor(t/s),d=t%s,a=M(A(s,c))*F+(d?M(A(d,c)):0);return y(e,_,"Double-check findings",l,a*i,p*i)}let C=N*r+(S+f)*t;return y(e,_,"Double-check findings",l,(M(C)+4e3*r)*i,p*i)}var Ce=8e5;function L(e,t,o,n,c,r,i){return{routeId:U(t),templateId:t,answerFormatId:v(t,o,e),model:n,calls:c,maxInputBytes:r,maxInputTokens:2e5,maxOutputTokens:i??V({model:n})}}function X(e,t){let o=e.CF_FINDING_QUALITY==="1",n=o&&e.CF_FINDING_FULL_CONTEXT==="1",c=o&&e.CF_FINDING_PRECISION_RULES==="1",r=t?.check.name??(c?"check-findings-precision-v1":"check-findings");return{enabled:o,fullContext:n,precisionRules:c,prompts:{derive:t?.derive.name??"derive-findings-legacy",check:r==="check-findings-legacy"?"check-findings":r}}}function $(e){return X({},e.prompts).prompts}function G(e,t,{enabled:o,prompts:n}){return b(e,t,o?n[e]:void 0)}function Ae(e,t,o){return G(e,t,{enabled:o?.switches.enabled??!1,prompts:X({},o?.prompts).prompts})}function Fe(e,t,o,n){let c=K(e),r=X(e),{fullContext:i}=r,p=G("derive",e,r),_=G("check",e,r),C=i?"whole-file":"legacy";return{findings:o,derive:L(e,p,"findings",u.generate,t,n),check:c.findingCheck?L(e,_,"check",l,Math.ceil(o/s)*(I+1),Math.max(n,A(s,C)),h(s)):null}}function g(e){if(e&&typeof e=="object"){for(let t of Object.values(e))g(t);Object.freeze(e)}return e}function ee(e,t,o={}){let{enabled:n,fullContext:c,precisionRules:r,prompts:i}=X(e),p=m=>n&&e[m]==="1",_=p("CF_FINDING_SECOND_OPINION"),C=p("CF_FINDING_RANKING"),F=n&&e.CF_FINDING_SEMANTIC_MATCHING!=="0",d=o.codeInputs!==!1&&n&&e.CF_FINDING_CODE_INPUTS!=="0",a=[],x=e.CF_FINDING_RECALL_VARIANT,D=o.recall!==!1&&p("CF_FINDING_RECALL")&&(x==="request-18"||x==="two-sweeps")?x:"off";o.recall!==!1&&p("CF_FINDING_RECALL")&&D==="off"&&a.push("Recall was skipped: no supported variant was selected.");let P=null,H=null;if(o.recall===!1&&e.CF_FINDING_RECALL==="1"&&a.push("Recall isn't available in local checks yet, so CF_FINDING_RECALL has no effect."),o.codeInputs===!1&&e.CF_FINDING_CODE_INPUTS==="1"&&a.push("Code evidence isn't available in local checks yet, so CF_FINDING_CODE_INPUTS has no effect."),_&&o.secondOpinion===!1&&a.push("Second opinion was skipped: local analysis supports Anthropic only."),_&&o.secondOpinion!==!1){let m=e.CF_FINDING_SECOND_OPINION_MODEL??"",E=Object.hasOwn(k,m)?k[m]:void 0,O=k[l];E&&E.provider===e.CF_FINDING_SECOND_OPINION_PROVIDER&&E.provider!==O.provider&&E.input<=O.input&&E.output<=O.output&&(E.input<O.input||E.output<O.output)?(P=m,H=E.provider):a.push("Second opinion was skipped: configure a priced, cheaper model from a different provider.")}return g({ruleVersion:n?"precision-v1":"legacy",switches:{enabled:n,fullContext:c,precisionRules:r,secondOpinion:_,ranking:C,semanticMatching:F,codeInputs:d,recall:D!=="off"},prompts:{derive:t.promptVersion(i.derive,e),check:t.promptVersion(i.check,e)},models:{derive:u.generate,check:l,scope:u.mechanical,secondOpinion:P},caps:{coreBytes:N,siteBytes:S,findingTextBytes:f,siteWindowLines:W,citedBatchBytes:c?8e4:0,passBytes:15e4,passContextBytes:6e4,maxPasses:4,passFindings:D==="request-18"?18:Y,totalFindings:24,deriveOutputTokens:w,checkBatchSize:s,checkOutputTokens:h(s),checkMaxRetries:I,checkOverheadTokens:4e3,secondOpinionBatchSize:4,secondOpinionInputBytes:A(4)+(c?8e4:0),secondOpinionOutputTokens:2048,secondOpinionMaxRetries:I},recallVariant:D,displayPolicyVersion:C?"support-v1":"legacy",meaningMatchingVersion:F?"meaning-v1":"legacy",codeInputScopeVersion:d?"owned-code-v1":"legacy",secondOpinionProvider:H,diagnostics:a})}function De(e,t){return t?g(structuredClone(t)):ee({},e)}function ke(e,t,o={}){let n=$(e);e.switches.enabled&&t.assertPromptVersions([{...e.prompts.derive,name:n.derive},{...e.prompts.check,name:n.check}],o)}export{l as a,s as b,I as c,W as d,N as e,S as f,Q as g,f as h,h as i,A as j,pe as k,Ce as l,L as m,$ as n,Ae as o,Fe as p,ee as q,De as r,ke as s};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{a as p}from"./O652FQQH.js";import{b as l}from"./57M4OQJM.js";import{createHash as d}from"node:crypto";function u({repo:o,body:r}){let[t,...i]=r.evidence,n=r.split,s=e=>e.map(a=>({path:a.path??null,startLine:a.startLine,endLine:a.endLine}));return{kind:"structure",impact:r.kind,cause:r.cause,category:null,question:null,fixSummaries:[],site:t?{repo:o,path:t.path,line:t.line}:null,excerpt:t?.excerpt??null,otherSites:i.map(e=>({repo:o,path:e.path,line:e.line,excerpt:e.excerpt})),structure:{title:r.title,subKind:r.subKind,files:r.files.map(e=>({path:e.path,action:e.action,role:e.role,unit:e.unit,loadMode:e.loadMode,loadVia:e.loadVia,purpose:e.purpose})),segments:r.segments.map(e=>({path:e.path,startLine:e.startLine,endLine:e.endLine,to:e.to,disposition:e.disposition,into:e.into?{path:e.into.path,line:e.into.line}:null,reason:e.reason})),reorder:r.reorder?{path:r.reorder.path,startLine:r.reorder.startLine,endLine:r.reorder.endLine,steps:r.reorder.steps.map(e=>({from:e.from,reason:e.reason}))}:null,toolMoves:r.toolMoves.map(e=>({tool:e.tool,fromUnit:e.fromUnit,toUnit:e.toUnit,reason:e.reason})),split:n?{frontDoor:{job:n.frontDoor.job,skills:[...n.frontDoor.skills]},subAgents:n.subAgents.map(e=>({job:e.job,description:e.description,path:e.path,handoff:e.handoff??null,skills:e.skills.map(a=>({from:a.from,to:a.to})),tools:[...e.tools],movedKnowledge:s(e.movedKnowledge),neededKnowledge:s(e.neededKnowledge)}))}:null}}}function x(o,r=[]){return{evidence:[...o.map((t,i)=>({key:`f${i}`,kind:"finding",impact:t.kind,structure:null,cause:t.cause,category:t.category??null,question:t.question,site:t.site?{repo:t.siteRepo,path:t.site.path,line:t.site.line}:null,excerpt:t.excerpt,otherSites:t.otherSites.map(n=>({repo:n.repo,path:n.path,line:n.line,excerpt:n.excerpt})),fixSummaries:t.fixes.flatMap(n=>typeof n.summary=="string"&&n.summary.trim()?[n.summary]:[])})),...r.map((t,i)=>({key:`s${i}`,...u(t)}))],positions:[...o.map((t,i)=>({key:`f${i}`,target:"finding",index:i,fingerprint:p("finding",t)})),...r.map((t,i)=>({key:`s${i}`,target:"structure",index:i,fingerprint:p("structure",t)}))]}}function L(o,r){return d("sha256").update(l({batch:o,requestIdentity:r})).digest("hex")}export{x as a,L as b};
|