agentskeptic 1.1.0 → 1.1.2
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 +22 -36
- package/config/marketing.json +6 -5
- package/dist/actionableFailure.d.ts.map +1 -1
- package/dist/actionableFailure.js +15 -0
- package/dist/actionableFailure.js.map +1 -1
- package/dist/assurance/assurancePathArgs.d.ts.map +1 -1
- package/dist/assurance/assurancePathArgs.js +1 -0
- package/dist/assurance/assurancePathArgs.js.map +1 -1
- package/dist/certificateDigest.d.ts +4 -0
- package/dist/certificateDigest.d.ts.map +1 -0
- package/dist/certificateDigest.js +7 -0
- package/dist/certificateDigest.js.map +1 -0
- package/dist/certificateDigest.test.d.ts +2 -0
- package/dist/certificateDigest.test.d.ts.map +1 -0
- package/dist/certificateDigest.test.js +14 -0
- package/dist/certificateDigest.test.js.map +1 -0
- package/dist/cli/initCommand.d.ts +2 -0
- package/dist/cli/initCommand.d.ts.map +1 -0
- package/dist/cli/initCommand.js +135 -0
- package/dist/cli/initCommand.js.map +1 -0
- package/dist/cli/lockOrchestration.d.ts.map +1 -1
- package/dist/cli/lockOrchestration.js +29 -4
- package/dist/cli/lockOrchestration.js.map +1 -1
- package/dist/cli/migrateCommand.d.ts +6 -0
- package/dist/cli/migrateCommand.d.ts.map +1 -0
- package/dist/cli/migrateCommand.js +97 -0
- package/dist/cli/migrateCommand.js.map +1 -0
- package/dist/cli.js +94 -109
- package/dist/cli.js.map +1 -1
- package/dist/cliArgv.test.d.ts +2 -0
- package/dist/cliArgv.test.d.ts.map +1 -0
- package/dist/cliArgv.test.js +34 -0
- package/dist/cliArgv.test.js.map +1 -0
- package/dist/cliOperationalCodes.d.ts +6 -0
- package/dist/cliOperationalCodes.d.ts.map +1 -1
- package/dist/cliOperationalCodes.js +6 -0
- package/dist/cliOperationalCodes.js.map +1 -1
- package/dist/commercial/activationCorrelation.d.ts +3 -0
- package/dist/commercial/activationCorrelation.d.ts.map +1 -0
- package/dist/commercial/activationCorrelation.js +6 -0
- package/dist/commercial/activationCorrelation.js.map +1 -0
- package/dist/commercial/getCurrentUsage.d.ts +16 -0
- package/dist/commercial/getCurrentUsage.d.ts.map +1 -0
- package/dist/commercial/getCurrentUsage.js +12 -0
- package/dist/commercial/getCurrentUsage.js.map +1 -0
- package/dist/commercial/licensePreflight.d.ts +1 -0
- package/dist/commercial/licensePreflight.d.ts.map +1 -1
- package/dist/commercial/licensePreflight.js +12 -77
- package/dist/commercial/licensePreflight.js.map +1 -1
- package/dist/commercial/postVerifyOutcomeBeacon.d.ts +2 -0
- package/dist/commercial/postVerifyOutcomeBeacon.d.ts.map +1 -1
- package/dist/commercial/postVerifyOutcomeBeacon.js +8 -13
- package/dist/commercial/postVerifyOutcomeBeacon.js.map +1 -1
- package/dist/compare.acceptance.test.js +25 -0
- package/dist/compare.acceptance.test.js.map +1 -1
- package/dist/compareRunManifest.d.ts +32 -0
- package/dist/compareRunManifest.d.ts.map +1 -0
- package/dist/compareRunManifest.js +60 -0
- package/dist/compareRunManifest.js.map +1 -0
- package/dist/debug-ui/app.css +42 -0
- package/dist/debug-ui/app.js +206 -15
- package/dist/debug-ui/index.html +11 -4
- package/dist/debug-ui/urlState.d.ts +15 -0
- package/dist/debug-ui/urlState.js +92 -0
- package/dist/debugCorpus.test.js +33 -7
- package/dist/debugCorpus.test.js.map +1 -1
- package/dist/debugPanels.d.ts +0 -3
- package/dist/debugPanels.d.ts.map +1 -1
- package/dist/debugPanels.js +0 -23
- package/dist/debugPanels.js.map +1 -1
- package/dist/debugPanels.test.js +16 -15
- package/dist/debugPanels.test.js.map +1 -1
- package/dist/debugServer.d.ts.map +1 -1
- package/dist/debugServer.js +19 -16
- package/dist/debugServer.js.map +1 -1
- package/dist/debugServer.test.js +18 -9
- package/dist/debugServer.test.js.map +1 -1
- package/dist/debugUiUrlState.test.d.ts +2 -0
- package/dist/debugUiUrlState.test.d.ts.map +1 -0
- package/dist/debugUiUrlState.test.js +49 -0
- package/dist/debugUiUrlState.test.js.map +1 -0
- package/dist/decisionGate.assertSafe.test.js +2 -2
- package/dist/decisionGate.assertSafe.test.js.map +1 -1
- package/dist/decisionGate.d.ts +2 -1
- package/dist/decisionGate.d.ts.map +1 -1
- package/dist/decisionGate.js +2 -1
- package/dist/decisionGate.js.map +1 -1
- package/dist/decisionGate.persistBundle.test.js +3 -3
- package/dist/decisionGate.persistBundle.test.js.map +1 -1
- package/dist/discovery-payload-v1.json +1 -1
- package/dist/enforceCli.d.ts.map +1 -1
- package/dist/enforceCli.js +15 -40
- package/dist/enforceCli.js.map +1 -1
- package/dist/enforceStateful.d.ts +2 -0
- package/dist/enforceStateful.d.ts.map +1 -0
- package/dist/enforceStateful.js +88 -0
- package/dist/enforceStateful.js.map +1 -0
- package/dist/enforcementProjection.d.ts +17 -0
- package/dist/enforcementProjection.d.ts.map +1 -0
- package/dist/enforcementProjection.js +20 -0
- package/dist/enforcementProjection.js.map +1 -0
- package/dist/executionTrace.test.js +35 -0
- package/dist/executionTrace.test.js.map +1 -1
- package/dist/executionTraceDiff.d.ts +36 -0
- package/dist/executionTraceDiff.d.ts.map +1 -0
- package/dist/executionTraceDiff.js +86 -0
- package/dist/executionTraceDiff.js.map +1 -0
- package/dist/executionTraceDiff.test.d.ts +2 -0
- package/dist/executionTraceDiff.test.d.ts.map +1 -0
- package/dist/executionTraceDiff.test.js +44 -0
- package/dist/executionTraceDiff.test.js.map +1 -0
- package/dist/failureOriginCatalog.d.ts.map +1 -1
- package/dist/failureOriginCatalog.js +3 -0
- package/dist/failureOriginCatalog.js.map +1 -1
- package/dist/firstFiveMinutesChecklist.d.ts +1 -1
- package/dist/firstFiveMinutesChecklist.d.ts.map +1 -1
- package/dist/firstFiveMinutesChecklist.js +2 -2
- package/dist/firstFiveMinutesChecklist.js.map +1 -1
- package/dist/index.d.ts +13 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -7
- package/dist/index.js.map +1 -1
- package/dist/operationalDisposition.d.ts +48 -0
- package/dist/operationalDisposition.d.ts.map +1 -1
- package/dist/operationalDisposition.js +48 -0
- package/dist/operationalDisposition.js.map +1 -1
- package/dist/publicDistribution.generated.d.ts +1 -1
- package/dist/publicDistribution.generated.js +1 -1
- package/dist/quickVerify/quickVerifyScope.d.ts +1 -1
- package/dist/quickVerify/quickVerifyScope.js +1 -1
- package/dist/regressionArtifact.d.ts +63 -0
- package/dist/regressionArtifact.d.ts.map +1 -0
- package/dist/regressionArtifact.js +290 -0
- package/dist/regressionArtifact.js.map +1 -0
- package/dist/runComparison.d.ts +0 -1
- package/dist/runComparison.d.ts.map +1 -1
- package/dist/runComparison.js +0 -83
- package/dist/runComparison.js.map +1 -1
- package/dist/runComparison.test.js +101 -57
- package/dist/runComparison.test.js.map +1 -1
- package/dist/schemaLoad.d.ts +1 -1
- package/dist/schemaLoad.d.ts.map +1 -1
- package/dist/schemaLoad.js +8 -0
- package/dist/schemaLoad.js.map +1 -1
- package/dist/sdk/AgentSkeptic.d.ts +37 -0
- package/dist/sdk/AgentSkeptic.d.ts.map +1 -0
- package/dist/sdk/AgentSkeptic.js +45 -0
- package/dist/sdk/AgentSkeptic.js.map +1 -0
- package/dist/sdk/Gate.d.ts +3 -0
- package/dist/sdk/Gate.d.ts.map +1 -0
- package/dist/sdk/Gate.js +2 -0
- package/dist/sdk/Gate.js.map +1 -0
- package/dist/sdk/_generated/openapi-types.d.ts +1034 -0
- package/dist/sdk/_generated/openapi-types.d.ts.map +1 -0
- package/dist/sdk/_generated/openapi-types.js +6 -0
- package/dist/sdk/_generated/openapi-types.js.map +1 -0
- package/dist/sdk/deprecate.d.ts +6 -0
- package/dist/sdk/deprecate.d.ts.map +1 -0
- package/dist/sdk/deprecate.js +14 -0
- package/dist/sdk/deprecate.js.map +1 -0
- package/dist/sdk/deprecatedPublicApi.d.ts +18 -0
- package/dist/sdk/deprecatedPublicApi.d.ts.map +1 -0
- package/dist/sdk/deprecatedPublicApi.js +36 -0
- package/dist/sdk/deprecatedPublicApi.js.map +1 -0
- package/dist/sdk/errors.d.ts +23 -0
- package/dist/sdk/errors.d.ts.map +1 -0
- package/dist/sdk/errors.js +28 -0
- package/dist/sdk/errors.js.map +1 -0
- package/dist/sdk/frameworks/next.d.ts +12 -0
- package/dist/sdk/frameworks/next.d.ts.map +1 -0
- package/dist/sdk/frameworks/next.js +29 -0
- package/dist/sdk/frameworks/next.js.map +1 -0
- package/dist/sdk/transport.d.ts +35 -0
- package/dist/sdk/transport.d.ts.map +1 -0
- package/dist/sdk/transport.js +180 -0
- package/dist/sdk/transport.js.map +1 -0
- package/dist/sortedJsonStringify.d.ts +2 -0
- package/dist/sortedJsonStringify.d.ts.map +1 -0
- package/dist/sortedJsonStringify.js +23 -0
- package/dist/sortedJsonStringify.js.map +1 -0
- package/dist/standardVerifyWorkflowCli.d.ts.map +1 -1
- package/dist/standardVerifyWorkflowCli.js +3 -2
- package/dist/standardVerifyWorkflowCli.js.map +1 -1
- package/dist/telemetry/maybeEmitOssClaimTicketUrl.d.ts +2 -0
- package/dist/telemetry/maybeEmitOssClaimTicketUrl.d.ts.map +1 -1
- package/dist/telemetry/maybeEmitOssClaimTicketUrl.js +13 -2
- package/dist/telemetry/maybeEmitOssClaimTicketUrl.js.map +1 -1
- package/dist/telemetry/postOssClaimContinuation.d.ts +1 -1
- package/dist/telemetry/postOssClaimContinuation.d.ts.map +1 -1
- package/dist/telemetry/postOssClaimContinuation.js +10 -6
- package/dist/telemetry/postOssClaimContinuation.js.map +1 -1
- package/dist/telemetry/postOssClaimTicket.d.ts +8 -0
- package/dist/telemetry/postOssClaimTicket.d.ts.map +1 -1
- package/dist/telemetry/postOssClaimTicket.js +31 -5
- package/dist/telemetry/postOssClaimTicket.js.map +1 -1
- package/dist/truthLayerError.d.ts +5 -2
- package/dist/truthLayerError.d.ts.map +1 -1
- package/dist/truthLayerError.js +6 -4
- package/dist/truthLayerError.js.map +1 -1
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/verificationDiagnostics.d.ts.map +1 -1
- package/dist/verificationDiagnostics.js +4 -1
- package/dist/verificationDiagnostics.js.map +1 -1
- package/dist/verificationPolicy.d.ts.map +1 -1
- package/dist/verificationPolicy.js +13 -0
- package/dist/verificationPolicy.js.map +1 -1
- package/dist/verificationUserPhrases.d.ts.map +1 -1
- package/dist/verificationUserPhrases.js +3 -0
- package/dist/verificationUserPhrases.js.map +1 -1
- package/dist/verify/batchVerifyTelemetrySubcommand.d.ts.map +1 -1
- package/dist/verify/batchVerifyTelemetrySubcommand.js +8 -1
- package/dist/verify/batchVerifyTelemetrySubcommand.js.map +1 -1
- package/dist/verifyAgentskeptic.d.ts +1 -1
- package/dist/verifyAgentskeptic.d.ts.map +1 -1
- package/dist/verifyAgentskeptic.js +3 -3
- package/dist/verifyAgentskeptic.js.map +1 -1
- package/dist/verifyAgentskeptic.test.js +5 -5
- package/dist/verifyAgentskeptic.test.js.map +1 -1
- package/dist/vitestMonorepoRoot.d.ts +10 -0
- package/dist/vitestMonorepoRoot.d.ts.map +1 -0
- package/dist/vitestMonorepoRoot.js +97 -0
- package/dist/vitestMonorepoRoot.js.map +1 -0
- package/dist/wireReasonCodes.d.ts +3 -0
- package/dist/wireReasonCodes.d.ts.map +1 -1
- package/dist/wireReasonCodes.js +3 -0
- package/dist/wireReasonCodes.js.map +1 -1
- package/package.json +46 -12
- package/schemas/agentskeptic-error-codes.json +608 -0
- package/schemas/compare-run-manifest-v1.schema.json +65 -0
- package/schemas/conformance-normalized-result.schema.json +73 -0
- package/schemas/connector-capabilities.schema.json +38 -0
- package/schemas/execution-trace-view.schema.json +1 -1
- package/schemas/openapi-commercial-v1.in.yaml +580 -14
- package/schemas/openapi-commercial-v1.yaml +580 -14
- package/schemas/quick-verify-report.schema.json +1 -1
- package/schemas/regression-artifact-v1.schema.json +212 -0
- package/scripts/discovery-payload.lib.cjs +3 -3
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type OutcomeCertificateRunKindForCompare = "contract_sql" | "contract_sql_langgraph_checkpoint_trust";
|
|
2
|
+
export type CertificateProfileV1 = {
|
|
3
|
+
mode: "uniform";
|
|
4
|
+
outcomeCertificateRunKind: OutcomeCertificateRunKindForCompare;
|
|
5
|
+
} | {
|
|
6
|
+
mode: "perRun";
|
|
7
|
+
entries: Array<{
|
|
8
|
+
runIndex: number;
|
|
9
|
+
outcomeCertificateRunKind: OutcomeCertificateRunKindForCompare;
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
export type CompareRunManifestEntryV1 = {
|
|
13
|
+
displayLabel: string;
|
|
14
|
+
workflowResult: string;
|
|
15
|
+
events: string;
|
|
16
|
+
};
|
|
17
|
+
export type CompareRunManifestV1 = {
|
|
18
|
+
schemaVersion: 1;
|
|
19
|
+
baseDirectory: string;
|
|
20
|
+
certificateProfile: CertificateProfileV1;
|
|
21
|
+
runs: CompareRunManifestEntryV1[];
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Read and validate a compare-run manifest. Resolves `baseDirectory` and validates certificate profile
|
|
25
|
+
* invariants (per-run index coverage) beyond JSON Schema.
|
|
26
|
+
*/
|
|
27
|
+
export declare function loadCompareRunManifest(manifestFilePath: string): {
|
|
28
|
+
manifest: CompareRunManifestV1;
|
|
29
|
+
baseDirAbs: string;
|
|
30
|
+
manifestFileAbs: string;
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=compareRunManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareRunManifest.d.ts","sourceRoot":"","sources":["../src/compareRunManifest.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,mCAAmC,GAAG,cAAc,GAAG,yCAAyC,CAAC;AAE7G,MAAM,MAAM,oBAAoB,GAC5B;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,yBAAyB,EAAE,mCAAmC,CAAC;CAChE,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,yBAAyB,EAAE,mCAAmC,CAAA;KAAE,CAAC,CAAC;CACtG,CAAC;AAEN,MAAM,MAAM,yBAAyB,GAAG;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,EAAE,CAAC,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,oBAAoB,CAAC;IACzC,IAAI,EAAE,yBAAyB,EAAE,CAAC;CACnC,CAAC;AAmCF;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,gBAAgB,EAAE,MAAM,GACvB;IAAE,QAAQ,EAAE,oBAAoB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,CA0BjF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { CLI_OPERATIONAL_CODES } from "./cliOperationalCodes.js";
|
|
4
|
+
import { loadSchemaValidator } from "./schemaLoad.js";
|
|
5
|
+
import { TruthLayerError } from "./truthLayerError.js";
|
|
6
|
+
function validateProfileAgainstRuns(m, baseDir) {
|
|
7
|
+
const n = m.runs.length;
|
|
8
|
+
if (m.certificateProfile.mode === "perRun") {
|
|
9
|
+
const e = m.certificateProfile.entries;
|
|
10
|
+
if (e.length !== n) {
|
|
11
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_MANIFEST_SCHEMA_INVALID, `certificateProfile.entries.length (${e.length}) must equal runs.length (${n})`);
|
|
12
|
+
}
|
|
13
|
+
const want = new Set(Array.from({ length: n }, (_, i) => i));
|
|
14
|
+
const got = new Set();
|
|
15
|
+
for (const ent of e) {
|
|
16
|
+
if (got.has(ent.runIndex)) {
|
|
17
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_MANIFEST_SCHEMA_INVALID, `duplicate runIndex ${ent.runIndex} in certificateProfile.entries`);
|
|
18
|
+
}
|
|
19
|
+
got.add(ent.runIndex);
|
|
20
|
+
}
|
|
21
|
+
if (got.size !== n || ![...got].every((i) => want.has(i))) {
|
|
22
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_MANIFEST_SCHEMA_INVALID, `certificateProfile.entries must list runIndex 0..${n - 1} exactly once each`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Read and validate a compare-run manifest. Resolves `baseDirectory` and validates certificate profile
|
|
28
|
+
* invariants (per-run index coverage) beyond JSON Schema.
|
|
29
|
+
*/
|
|
30
|
+
export function loadCompareRunManifest(manifestFilePath) {
|
|
31
|
+
const manifestFileAbs = path.resolve(manifestFilePath);
|
|
32
|
+
let raw;
|
|
33
|
+
try {
|
|
34
|
+
raw = readFileSync(manifestFileAbs, "utf8");
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
if (e instanceof TruthLayerError)
|
|
38
|
+
throw e;
|
|
39
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
40
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_MANIFEST_READ_FAILED, msg);
|
|
41
|
+
}
|
|
42
|
+
let parsed;
|
|
43
|
+
try {
|
|
44
|
+
parsed = JSON.parse(raw);
|
|
45
|
+
}
|
|
46
|
+
catch (e) {
|
|
47
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
48
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_INPUT_JSON_SYNTAX, msg);
|
|
49
|
+
}
|
|
50
|
+
const v = loadSchemaValidator("compare-run-manifest-v1");
|
|
51
|
+
if (!v(parsed)) {
|
|
52
|
+
const detail = JSON.stringify(v.errors ?? []);
|
|
53
|
+
throw new TruthLayerError(CLI_OPERATIONAL_CODES.COMPARE_MANIFEST_SCHEMA_INVALID, detail);
|
|
54
|
+
}
|
|
55
|
+
const m = parsed;
|
|
56
|
+
validateProfileAgainstRuns(m, manifestFileAbs);
|
|
57
|
+
const baseDirAbs = path.resolve(path.dirname(manifestFileAbs), m.baseDirectory);
|
|
58
|
+
return { manifest: m, baseDirAbs, manifestFileAbs };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=compareRunManifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compareRunManifest.js","sourceRoot":"","sources":["../src/compareRunManifest.ts"],"names":[],"mappings":"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"}
|
package/dist/debug-ui/app.css
CHANGED
|
@@ -16,6 +16,22 @@ header h1 {
|
|
|
16
16
|
margin: 0 0 1rem;
|
|
17
17
|
max-width: 52rem;
|
|
18
18
|
}
|
|
19
|
+
.cli-hint {
|
|
20
|
+
color: #c9d1d9;
|
|
21
|
+
margin: 0 0 1rem;
|
|
22
|
+
max-width: 52rem;
|
|
23
|
+
font-size: 0.95rem;
|
|
24
|
+
}
|
|
25
|
+
.cli-hint code {
|
|
26
|
+
display: block;
|
|
27
|
+
margin-top: 0.35rem;
|
|
28
|
+
padding: 0.45rem 0.6rem;
|
|
29
|
+
background: #161b22;
|
|
30
|
+
border: 1px solid #30363d;
|
|
31
|
+
border-radius: 6px;
|
|
32
|
+
color: #79c0ff;
|
|
33
|
+
font-size: 0.85rem;
|
|
34
|
+
}
|
|
19
35
|
.tabs {
|
|
20
36
|
display: flex;
|
|
21
37
|
gap: 0.5rem;
|
|
@@ -171,6 +187,32 @@ tr.selected {
|
|
|
171
187
|
border-color: #f0883e;
|
|
172
188
|
background: #2d1f12;
|
|
173
189
|
}
|
|
190
|
+
@keyframes tracePulseFocus {
|
|
191
|
+
0% {
|
|
192
|
+
box-shadow: 0 0 0 0 rgba(240, 136, 62, 0.55);
|
|
193
|
+
}
|
|
194
|
+
70% {
|
|
195
|
+
box-shadow: 0 0 0 10px rgba(240, 136, 62, 0);
|
|
196
|
+
}
|
|
197
|
+
100% {
|
|
198
|
+
box-shadow: 0 0 0 0 rgba(240, 136, 62, 0);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
.trace-step.pulse-focus {
|
|
202
|
+
animation: tracePulseFocus 0.85s ease-out 1;
|
|
203
|
+
}
|
|
204
|
+
.focus-target-list {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-wrap: wrap;
|
|
207
|
+
gap: 0.5rem;
|
|
208
|
+
margin-top: 0.5rem;
|
|
209
|
+
}
|
|
210
|
+
.focus-target-btn {
|
|
211
|
+
text-align: left;
|
|
212
|
+
max-width: 100%;
|
|
213
|
+
font-size: 0.8rem;
|
|
214
|
+
line-height: 1.3;
|
|
215
|
+
}
|
|
174
216
|
button {
|
|
175
217
|
cursor: pointer;
|
|
176
218
|
background: #21262d;
|
package/dist/debug-ui/app.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
|
+
DEBUG_CONSOLE_DEFAULT_TAB,
|
|
3
|
+
parseDebugConsoleUrl,
|
|
4
|
+
resolvedFilters,
|
|
5
|
+
serializeDebugConsoleUrl,
|
|
6
|
+
} from "./urlState.js";
|
|
2
7
|
|
|
3
8
|
const state = {
|
|
4
9
|
nextCursor: null,
|
|
5
10
|
filterParams: new URLSearchParams(),
|
|
6
11
|
selected: new Set(),
|
|
12
|
+
currentTab: DEBUG_CONSOLE_DEFAULT_TAB,
|
|
13
|
+
openRunId: null,
|
|
7
14
|
};
|
|
8
15
|
|
|
9
16
|
function api(path, opts) {
|
|
@@ -35,7 +42,6 @@ function buildFilterParamsFromForm() {
|
|
|
35
42
|
p.set(k, String(v));
|
|
36
43
|
}
|
|
37
44
|
}
|
|
38
|
-
// Unchecked checkboxes are omitted from FormData.
|
|
39
45
|
const includeLoadErrorsEl = form.querySelector('[name="includeLoadErrors"]');
|
|
40
46
|
if (includeLoadErrorsEl && !includeLoadErrorsEl.checked) {
|
|
41
47
|
p.set("includeLoadErrors", "false");
|
|
@@ -47,6 +53,84 @@ function buildFilterParamsFromForm() {
|
|
|
47
53
|
return p;
|
|
48
54
|
}
|
|
49
55
|
|
|
56
|
+
/** @param {Record<string, string>} filters */
|
|
57
|
+
function applyFiltersToForm(filters) {
|
|
58
|
+
const form = document.getElementById("filters");
|
|
59
|
+
const r = resolvedFilters(filters);
|
|
60
|
+
for (const el of form.querySelectorAll("input[name], select[name]")) {
|
|
61
|
+
const name = el.getAttribute("name");
|
|
62
|
+
if (!name || name === "includeLoadErrors" || name === "hasPathFindings") continue;
|
|
63
|
+
if (el instanceof HTMLSelectElement || el instanceof HTMLInputElement) {
|
|
64
|
+
el.value = r[name] ?? "";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const inc = form.querySelector('[name="includeLoadErrors"]');
|
|
68
|
+
if (inc instanceof HTMLInputElement) {
|
|
69
|
+
inc.checked = r.includeLoadErrors !== "false";
|
|
70
|
+
}
|
|
71
|
+
const hpf = form.querySelector('[name="hasPathFindings"]');
|
|
72
|
+
if (hpf instanceof HTMLInputElement) {
|
|
73
|
+
hpf.checked = r.hasPathFindings === "true";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** @param {URLSearchParams} p */
|
|
78
|
+
function filterObjectFromSearchParams(p) {
|
|
79
|
+
const keys = [
|
|
80
|
+
"loadStatus",
|
|
81
|
+
"workflowId",
|
|
82
|
+
"status",
|
|
83
|
+
"failureCategory",
|
|
84
|
+
"reasonCode",
|
|
85
|
+
"toolId",
|
|
86
|
+
"customerId",
|
|
87
|
+
"timeFrom",
|
|
88
|
+
"timeTo",
|
|
89
|
+
];
|
|
90
|
+
/** @type {Record<string, string>} */
|
|
91
|
+
const out = {};
|
|
92
|
+
for (const k of keys) {
|
|
93
|
+
const v = p.get(k);
|
|
94
|
+
if (v != null && v !== "") {
|
|
95
|
+
out[k] = v;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (p.has("includeLoadErrors")) {
|
|
99
|
+
out.includeLoadErrors = p.get("includeLoadErrors") === "true" ? "true" : "false";
|
|
100
|
+
} else {
|
|
101
|
+
out.includeLoadErrors = "true";
|
|
102
|
+
}
|
|
103
|
+
if (p.has("hasPathFindings")) {
|
|
104
|
+
out.hasPathFindings = p.get("hasPathFindings") === "true" ? "true" : "false";
|
|
105
|
+
} else {
|
|
106
|
+
out.hasPathFindings = "false";
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function pushUrl() {
|
|
112
|
+
const filters = filterObjectFromSearchParams(state.filterParams);
|
|
113
|
+
const q = serializeDebugConsoleUrl({
|
|
114
|
+
tab: state.currentTab,
|
|
115
|
+
run: state.openRunId,
|
|
116
|
+
filters,
|
|
117
|
+
});
|
|
118
|
+
const path = window.location.pathname || "/";
|
|
119
|
+
const url = q ? `${path}?${q}` : path;
|
|
120
|
+
history.replaceState(null, "", url);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function setActiveTab(tab) {
|
|
124
|
+
const t = tab === "patterns" || tab === "compare" ? tab : DEBUG_CONSOLE_DEFAULT_TAB;
|
|
125
|
+
state.currentTab = t;
|
|
126
|
+
document.querySelectorAll(".tab").forEach((b) => {
|
|
127
|
+
b.classList.toggle("active", b.dataset.tab === t);
|
|
128
|
+
});
|
|
129
|
+
document.querySelectorAll(".panel").forEach((p) => {
|
|
130
|
+
p.classList.toggle("active", p.id === `panel-${t}`);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
50
134
|
async function loadRuns(append) {
|
|
51
135
|
const p = new URLSearchParams(state.filterParams);
|
|
52
136
|
p.set("limit", "100");
|
|
@@ -117,16 +201,69 @@ function formatVerdictSurface(vs) {
|
|
|
117
201
|
</div>`;
|
|
118
202
|
}
|
|
119
203
|
|
|
204
|
+
function focusButtonLabel(t) {
|
|
205
|
+
const v = String(t.value);
|
|
206
|
+
const short = t.rationale && t.rationale.length > 72 ? `${t.rationale.slice(0, 69)}…` : t.rationale || `${t.kind}: ${v}`;
|
|
207
|
+
return `${t.kind}: ${v} — ${short}`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {HTMLElement} body
|
|
212
|
+
* @param {string} kind
|
|
213
|
+
* @param {string} value
|
|
214
|
+
*/
|
|
215
|
+
function scrollToFocusTarget(body, kind, value) {
|
|
216
|
+
for (const el of body.querySelectorAll(".trace-step")) {
|
|
217
|
+
if (kind === "seq" && el.getAttribute("data-seq") === value) {
|
|
218
|
+
pulseEl(el);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
if (kind === "ingestIndex" && el.getAttribute("data-ingest-index") === value) {
|
|
222
|
+
pulseEl(el);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (kind === "runEventId" && el.getAttribute("data-run-event-id") === value) {
|
|
226
|
+
pulseEl(el);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** @param {HTMLElement} el */
|
|
233
|
+
function pulseEl(el) {
|
|
234
|
+
el.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
235
|
+
el.classList.add("pulse-focus");
|
|
236
|
+
window.setTimeout(() => {
|
|
237
|
+
el.classList.remove("pulse-focus");
|
|
238
|
+
}, 900);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** @param {HTMLElement} body */
|
|
242
|
+
function wireFocusButtons(body) {
|
|
243
|
+
body.addEventListener("click", (ev) => {
|
|
244
|
+
const btn = ev.target && ev.target.closest && ev.target.closest(".focus-target-btn");
|
|
245
|
+
if (!btn || !(btn instanceof HTMLElement)) return;
|
|
246
|
+
const kind = btn.dataset.kind;
|
|
247
|
+
const value = btn.dataset.value;
|
|
248
|
+
if (!kind || value == null) return;
|
|
249
|
+
scrollToFocusTarget(body, kind, value);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
120
253
|
async function openDetail(runId) {
|
|
121
254
|
const drawer = document.getElementById("detail-drawer");
|
|
122
255
|
const body = document.getElementById("detail-body");
|
|
123
256
|
const title = document.getElementById("detail-title");
|
|
124
257
|
drawer.classList.remove("hidden");
|
|
258
|
+
state.openRunId = runId;
|
|
259
|
+
pushUrl();
|
|
125
260
|
title.textContent = `Run: ${runId}`;
|
|
126
261
|
body.innerHTML = "<p>Loading…</p>";
|
|
127
262
|
try {
|
|
128
263
|
const data = await api(`/api/runs/${encodeURIComponent(runId)}`);
|
|
129
264
|
if (data.loadStatus === "error") {
|
|
265
|
+
state.openRunId = runId;
|
|
266
|
+
pushUrl();
|
|
130
267
|
body.innerHTML = `
|
|
131
268
|
<p class="focus-panel"><strong>Load error</strong> <code>${escapeHtml(data.error.code)}</code></p>
|
|
132
269
|
<pre class="json-out">${escapeHtml(JSON.stringify(data, null, 2))}</pre>
|
|
@@ -135,10 +272,26 @@ async function openDetail(runId) {
|
|
|
135
272
|
}
|
|
136
273
|
let focusHtml = "";
|
|
137
274
|
const focusSet = new Set();
|
|
275
|
+
/** @type {{ targets: { kind: string; value: string | number; rationale: string }[] }} */
|
|
276
|
+
let focusPayload = { targets: [] };
|
|
138
277
|
try {
|
|
139
278
|
const focus = await api(`/api/runs/${encodeURIComponent(runId)}/focus`);
|
|
140
|
-
|
|
141
|
-
|
|
279
|
+
focusPayload = focus;
|
|
280
|
+
const buttons =
|
|
281
|
+
focus.targets && focus.targets.length
|
|
282
|
+
? focus.targets
|
|
283
|
+
.map((t) => {
|
|
284
|
+
const v = String(t.value);
|
|
285
|
+
const label = escapeHtml(focusButtonLabel(t));
|
|
286
|
+
return `<button type="button" class="focus-target-btn" data-kind="${escapeHtml(t.kind)}" data-value="${escapeHtml(v)}" title="${escapeHtml(t.rationale)}">${label}</button>`;
|
|
287
|
+
})
|
|
288
|
+
.join("")
|
|
289
|
+
: "";
|
|
290
|
+
focusHtml =
|
|
291
|
+
focus.targets && focus.targets.length
|
|
292
|
+
? `<div class="focus-panel" role="region" aria-label="Focus targets"><strong>Focus targets</strong><p class="meta">Click a target to scroll to the matching trace step.</p><div class="focus-target-list">${buttons}</div></div>`
|
|
293
|
+
: "";
|
|
294
|
+
for (const t of focus.targets || []) {
|
|
142
295
|
if (t.kind === "seq") focusSet.add(`seq:${t.value}`);
|
|
143
296
|
if (t.kind === "ingestIndex") focusSet.add(`ingest:${t.value}`);
|
|
144
297
|
if (t.kind === "runEventId") focusSet.add(`runEventId:${t.value}`);
|
|
@@ -156,7 +309,13 @@ async function openDetail(runId) {
|
|
|
156
309
|
(seqKey && focusSet.has(seqKey)) ||
|
|
157
310
|
focusSet.has(ingestKey) ||
|
|
158
311
|
(runEvKey && focusSet.has(runEvKey));
|
|
159
|
-
|
|
312
|
+
const seqAttr = seq != null ? ` data-seq="${escapeHtml(String(seq))}"` : "";
|
|
313
|
+
const ingestAttr = ` data-ingest-index="${escapeHtml(String(n.ingestIndex ?? ""))}"`;
|
|
314
|
+
const rev =
|
|
315
|
+
n.runEventId != null && n.runEventId !== ""
|
|
316
|
+
? ` data-run-event-id="${escapeHtml(String(n.runEventId))}"`
|
|
317
|
+
: "";
|
|
318
|
+
return `<div class="trace-step ${hit ? "focus-hit" : ""}" data-idx="${i}"${seqAttr}${ingestAttr}${rev}>${escapeHtml(JSON.stringify(n))}</div>`;
|
|
160
319
|
});
|
|
161
320
|
const trustHtml =
|
|
162
321
|
typeof data.runTrustPanelHtml === "string"
|
|
@@ -171,14 +330,25 @@ async function openDetail(runId) {
|
|
|
171
330
|
<h3>WorkflowResult</h3>
|
|
172
331
|
<pre class="json-out">${escapeHtml(JSON.stringify(data.workflowResult, null, 2))}</pre>
|
|
173
332
|
`;
|
|
333
|
+
if (focusPayload.targets && focusPayload.targets.length) {
|
|
334
|
+
wireFocusButtons(body);
|
|
335
|
+
}
|
|
336
|
+
pushUrl();
|
|
174
337
|
} catch (e) {
|
|
175
338
|
body.innerHTML = `<p class="focus-panel">Error: ${escapeHtml(e.message)}</p>`;
|
|
176
339
|
}
|
|
177
340
|
}
|
|
178
341
|
|
|
342
|
+
function closeDetail() {
|
|
343
|
+
document.getElementById("detail-drawer").classList.add("hidden");
|
|
344
|
+
state.openRunId = null;
|
|
345
|
+
pushUrl();
|
|
346
|
+
}
|
|
347
|
+
|
|
179
348
|
document.getElementById("filters").addEventListener("submit", (ev) => {
|
|
180
349
|
ev.preventDefault();
|
|
181
350
|
state.filterParams = buildFilterParamsFromForm();
|
|
351
|
+
pushUrl();
|
|
182
352
|
loadRuns(false).catch((e) => alert(e.message));
|
|
183
353
|
});
|
|
184
354
|
|
|
@@ -186,6 +356,7 @@ document.getElementById("clear-filters").addEventListener("click", () => {
|
|
|
186
356
|
document.getElementById("filters").reset();
|
|
187
357
|
document.querySelector('[name="includeLoadErrors"]').checked = true;
|
|
188
358
|
state.filterParams = buildFilterParamsFromForm();
|
|
359
|
+
pushUrl();
|
|
189
360
|
loadRuns(false).catch((e) => alert(e.message));
|
|
190
361
|
});
|
|
191
362
|
|
|
@@ -195,10 +366,8 @@ document.getElementById("load-more").addEventListener("click", () => {
|
|
|
195
366
|
|
|
196
367
|
document.querySelectorAll(".tab").forEach((btn) => {
|
|
197
368
|
btn.addEventListener("click", () => {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
btn.classList.add("active");
|
|
201
|
-
document.getElementById(`panel-${btn.dataset.tab}`).classList.add("active");
|
|
369
|
+
setActiveTab(btn.dataset.tab || DEBUG_CONSOLE_DEFAULT_TAB);
|
|
370
|
+
pushUrl();
|
|
202
371
|
});
|
|
203
372
|
});
|
|
204
373
|
|
|
@@ -224,10 +393,11 @@ document.getElementById("run-compare").addEventListener("click", async () => {
|
|
|
224
393
|
headers: { "Content-Type": "application/json" },
|
|
225
394
|
body: JSON.stringify({ runIds: ids }),
|
|
226
395
|
});
|
|
227
|
-
|
|
228
|
-
|
|
396
|
+
const html = data?.regression?.narrativeHtml;
|
|
397
|
+
if (typeof html === "string" && html.length > 0) {
|
|
398
|
+
out.innerHTML = html;
|
|
229
399
|
} else {
|
|
230
|
-
out.textContent = "
|
|
400
|
+
out.textContent = "regression.narrativeHtml missing in response.";
|
|
231
401
|
}
|
|
232
402
|
} catch (e) {
|
|
233
403
|
out.textContent = "";
|
|
@@ -236,10 +406,31 @@ document.getElementById("run-compare").addEventListener("click", async () => {
|
|
|
236
406
|
});
|
|
237
407
|
|
|
238
408
|
document.getElementById("close-detail").addEventListener("click", () => {
|
|
239
|
-
|
|
409
|
+
closeDetail();
|
|
240
410
|
});
|
|
241
411
|
|
|
242
|
-
|
|
243
|
-
|
|
412
|
+
window.addEventListener("popstate", () => {
|
|
413
|
+
void applyUrlToUi();
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
async function applyUrlToUi() {
|
|
417
|
+
const parsed = parseDebugConsoleUrl(new URLSearchParams(window.location.search));
|
|
418
|
+
applyFiltersToForm(parsed.filters);
|
|
419
|
+
state.filterParams = buildFilterParamsFromForm();
|
|
420
|
+
setActiveTab(parsed.tab);
|
|
421
|
+
try {
|
|
422
|
+
await loadRuns(false);
|
|
423
|
+
} catch (e) {
|
|
424
|
+
document.getElementById("runs-meta").textContent = `Failed to load: ${e.message}`;
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (parsed.run) {
|
|
428
|
+
await openDetail(parsed.run);
|
|
429
|
+
} else {
|
|
430
|
+
closeDetail();
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
void applyUrlToUi().catch((e) => {
|
|
244
435
|
document.getElementById("runs-meta").textContent = `Failed to load: ${e.message}`;
|
|
245
436
|
});
|
package/dist/debug-ui/index.html
CHANGED
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>
|
|
6
|
+
<title>agentskeptic — Debug Console</title>
|
|
7
7
|
<link rel="stylesheet" href="app.css" />
|
|
8
8
|
</head>
|
|
9
9
|
<body>
|
|
10
10
|
<header>
|
|
11
|
-
<h1>Debug Console</h1>
|
|
12
|
-
<p class="sub">
|
|
11
|
+
<h1>agentskeptic Debug Console</h1>
|
|
12
|
+
<p class="sub">
|
|
13
|
+
Local corpus triage (127.0.0.1 only). Focus targets come from the API; this UI links them to trace steps—no duplicated
|
|
14
|
+
linking rules in the browser.
|
|
15
|
+
</p>
|
|
16
|
+
<p class="cli-hint">
|
|
17
|
+
After running verification from the CLI, explore saved runs here:
|
|
18
|
+
<code>agentskeptic debug --corpus examples/debug-corpus</code>
|
|
19
|
+
</p>
|
|
13
20
|
</header>
|
|
14
21
|
|
|
15
22
|
<nav class="tabs">
|
|
@@ -74,6 +81,6 @@
|
|
|
74
81
|
<div id="detail-body"></div>
|
|
75
82
|
</section>
|
|
76
83
|
|
|
77
|
-
<script src="app.js"></script>
|
|
84
|
+
<script type="module" src="app.js"></script>
|
|
78
85
|
</body>
|
|
79
86
|
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type DebugConsoleUrlState = {
|
|
2
|
+
tab: string;
|
|
3
|
+
run: string | null;
|
|
4
|
+
filters: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const DEBUG_CONSOLE_DEFAULT_TAB: string;
|
|
8
|
+
|
|
9
|
+
export function parseDebugConsoleUrl(searchParams: URLSearchParams): DebugConsoleUrlState;
|
|
10
|
+
|
|
11
|
+
export function defaultFilterRecord(): Record<string, string>;
|
|
12
|
+
|
|
13
|
+
export function resolvedFilters(filters: Record<string, string>): Record<string, string>;
|
|
14
|
+
|
|
15
|
+
export function serializeDebugConsoleUrl(state: DebugConsoleUrlState): string;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** @typedef {{ tab: string, run: string | null, filters: Record<string, string> }} DebugConsoleUrlState */
|
|
2
|
+
|
|
3
|
+
export const DEBUG_CONSOLE_DEFAULT_TAB = "runs";
|
|
4
|
+
|
|
5
|
+
const VALID_TABS = new Set(["runs", "patterns", "compare"]);
|
|
6
|
+
|
|
7
|
+
const FILTER_TEXT_KEYS = [
|
|
8
|
+
"loadStatus",
|
|
9
|
+
"workflowId",
|
|
10
|
+
"status",
|
|
11
|
+
"failureCategory",
|
|
12
|
+
"reasonCode",
|
|
13
|
+
"toolId",
|
|
14
|
+
"customerId",
|
|
15
|
+
"timeFrom",
|
|
16
|
+
"timeTo",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {URLSearchParams} searchParams
|
|
21
|
+
* @returns {DebugConsoleUrlState}
|
|
22
|
+
*/
|
|
23
|
+
export function parseDebugConsoleUrl(searchParams) {
|
|
24
|
+
const rawTab = searchParams.get("tab") || DEBUG_CONSOLE_DEFAULT_TAB;
|
|
25
|
+
const tab = VALID_TABS.has(rawTab) ? rawTab : DEBUG_CONSOLE_DEFAULT_TAB;
|
|
26
|
+
const runRaw = searchParams.get("run");
|
|
27
|
+
const run = runRaw != null && runRaw !== "" ? runRaw : null;
|
|
28
|
+
|
|
29
|
+
/** @type {Record<string, string>} */
|
|
30
|
+
const filters = {};
|
|
31
|
+
for (const k of FILTER_TEXT_KEYS) {
|
|
32
|
+
const v = searchParams.get(k);
|
|
33
|
+
if (v != null && v !== "") {
|
|
34
|
+
filters[k] = v;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (searchParams.has("includeLoadErrors")) {
|
|
39
|
+
filters.includeLoadErrors = searchParams.get("includeLoadErrors") === "true" ? "true" : "false";
|
|
40
|
+
}
|
|
41
|
+
if (searchParams.has("hasPathFindings")) {
|
|
42
|
+
filters.hasPathFindings = searchParams.get("hasPathFindings") === "true" ? "true" : "false";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { tab, run, filters };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Default filter semantics aligned with debug-ui/app.js (includeLoadErrors checked by default).
|
|
50
|
+
* @returns {Record<string, string>}
|
|
51
|
+
*/
|
|
52
|
+
export function defaultFilterRecord() {
|
|
53
|
+
return { includeLoadErrors: "true" };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Merge URL-derived filters with defaults for form population.
|
|
58
|
+
* @param {Record<string, string>} filters
|
|
59
|
+
*/
|
|
60
|
+
export function resolvedFilters(filters) {
|
|
61
|
+
const out = { ...defaultFilterRecord(), ...filters };
|
|
62
|
+
if (!("hasPathFindings" in out)) {
|
|
63
|
+
out.hasPathFindings = "false";
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param {DebugConsoleUrlState} state
|
|
70
|
+
* @returns {string} query string without leading "?"
|
|
71
|
+
*/
|
|
72
|
+
export function serializeDebugConsoleUrl(state) {
|
|
73
|
+
const p = new URLSearchParams();
|
|
74
|
+
p.set("tab", state.tab || DEBUG_CONSOLE_DEFAULT_TAB);
|
|
75
|
+
if (state.run) {
|
|
76
|
+
p.set("run", state.run);
|
|
77
|
+
}
|
|
78
|
+
const f = state.filters || {};
|
|
79
|
+
for (const k of FILTER_TEXT_KEYS) {
|
|
80
|
+
const v = f[k];
|
|
81
|
+
if (v != null && v !== "") {
|
|
82
|
+
p.set(k, String(v));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (f.includeLoadErrors === "false") {
|
|
86
|
+
p.set("includeLoadErrors", "false");
|
|
87
|
+
}
|
|
88
|
+
if (f.hasPathFindings === "true") {
|
|
89
|
+
p.set("hasPathFindings", "true");
|
|
90
|
+
}
|
|
91
|
+
return p.toString();
|
|
92
|
+
}
|
package/dist/debugCorpus.test.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
2
3
|
import { copyFileSync, mkdirSync, readFileSync, writeFileSync, rmSync, mkdtempSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { tmpdir } from "node:os";
|
|
@@ -6,19 +7,44 @@ import { describe, expect, it } from "vitest";
|
|
|
6
7
|
import { CLI_OPERATIONAL_CODES } from "./cliOperationalCodes.js";
|
|
7
8
|
import { DEBUG_CORPUS_CODES, isPathUnderRoot, listCorpusRunIds, loadAllCorpusRuns, loadCorpusRun, resolveCorpusRootReal, } from "./debugCorpus.js";
|
|
8
9
|
import { WORKFLOW_RESULT_RUN_LEVEL_CODES_MISMATCH_MESSAGE } from "./runLevelDriftMessages.js";
|
|
9
|
-
import {
|
|
10
|
-
const root =
|
|
10
|
+
import { monorepoRootForVitest } from "./vitestMonorepoRoot.js";
|
|
11
|
+
const root = monorepoRootForVitest(import.meta.url);
|
|
11
12
|
const negativeRoot = join(root, "test", "fixtures", "corpus-negative");
|
|
12
13
|
const runOkDir = join(root, "examples", "debug-corpus", "run_ok");
|
|
13
14
|
describe("debugCorpus", () => {
|
|
14
|
-
it("examples/debug-corpus
|
|
15
|
+
it("examples/debug-corpus ships the curated demo library (5 sealed ok runs)", () => {
|
|
15
16
|
const corpus = join(root, "examples", "debug-corpus");
|
|
16
17
|
const outcomes = loadAllCorpusRuns(corpus);
|
|
17
|
-
|
|
18
|
+
const runIds = listCorpusRunIds(corpus);
|
|
19
|
+
assert.equal(outcomes.length, 5, `expected 5 runs under ${corpus}; listCorpusRunIds=[${runIds.join(", ")}] cwd=${process.cwd()}`);
|
|
20
|
+
const errLines = [];
|
|
21
|
+
for (const o of outcomes) {
|
|
22
|
+
if (o.loadStatus === "error") {
|
|
23
|
+
errLines.push(`${o.runId}: ${o.error.code} – ${o.error.message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
assert.equal(errLines.length, 0, `load failures (integrity/schema/path) under ${corpus}: ${errLines.join(" | ")}`);
|
|
18
27
|
const ok = outcomes.filter((o) => o.loadStatus === "ok");
|
|
19
|
-
expect(ok).toHaveLength(
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
expect(ok).toHaveLength(5);
|
|
29
|
+
const ids = new Set(ok.map((o) => o.runId));
|
|
30
|
+
for (const id of [
|
|
31
|
+
"run_ok",
|
|
32
|
+
"run_value_mismatch",
|
|
33
|
+
"run_row_absent",
|
|
34
|
+
"run_path_nonempty",
|
|
35
|
+
"run_complete_b",
|
|
36
|
+
]) {
|
|
37
|
+
expect(ids.has(id)).toBe(true);
|
|
38
|
+
}
|
|
39
|
+
const withFailureEvidence = ok.filter((o) => o.workflowResult.workflowTruthReport.failureAnalysis !== null &&
|
|
40
|
+
o.workflowResult.workflowTruthReport.failureAnalysis.evidence.length > 0);
|
|
41
|
+
expect(withFailureEvidence).toHaveLength(2);
|
|
42
|
+
expect(withFailureEvidence.map((o) => o.runId).sort()).toEqual(["run_row_absent", "run_value_mismatch"]);
|
|
43
|
+
const pathFindings = ok.filter((o) => o.workflowResult.workflowTruthReport.executionPathFindings.length > 0);
|
|
44
|
+
expect(pathFindings).toHaveLength(1);
|
|
45
|
+
expect(pathFindings[0].runId).toBe("run_path_nonempty");
|
|
46
|
+
const wfComplete = ok.filter((o) => o.workflowResult.workflowId === "wf_complete");
|
|
47
|
+
expect(wfComplete.length).toBeGreaterThanOrEqual(3);
|
|
22
48
|
});
|
|
23
49
|
it("corpus-negative fixtures produce expected error codes", () => {
|
|
24
50
|
const rootReal = resolveCorpusRootReal(negativeRoot);
|