@jevitate/cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/ai-cli.js +40 -30
- package/dist/ai-cli.js.map +1 -1
- package/dist/author-journey-cli.d.ts +4 -0
- package/dist/author-journey-cli.js +109 -0
- package/dist/author-journey-cli.js.map +1 -0
- package/dist/bin.js +58077 -22454
- package/dist/bin.js.map +1 -1
- package/dist/browser-run-options.d.ts +58 -0
- package/dist/browser-run-options.js +106 -0
- package/dist/browser-run-options.js.map +1 -0
- package/dist/build-info.generated.d.ts +2 -0
- package/dist/build-info.generated.js +10 -0
- package/dist/build-info.generated.js.map +1 -0
- package/dist/check-api.d.ts +5 -0
- package/dist/check-api.js +233 -0
- package/dist/check-api.js.map +1 -0
- package/dist/check-budget.d.ts +26 -0
- package/dist/check-budget.js +89 -0
- package/dist/check-budget.js.map +1 -0
- package/dist/check-cli.d.ts +31 -0
- package/dist/check-cli.js +109 -0
- package/dist/check-cli.js.map +1 -0
- package/dist/check-execute.d.ts +25 -0
- package/dist/check-execute.js +385 -0
- package/dist/check-execute.js.map +1 -0
- package/dist/check-plan.d.ts +113 -0
- package/dist/check-plan.js +448 -0
- package/dist/check-plan.js.map +1 -0
- package/dist/check-suite.d.ts +171 -0
- package/dist/check-suite.js +515 -0
- package/dist/check-suite.js.map +1 -0
- package/dist/check-types.d.ts +181 -0
- package/dist/check-types.js +35 -0
- package/dist/check-types.js.map +1 -0
- package/dist/cli-args.d.ts +26 -0
- package/dist/cli-args.js +50 -0
- package/dist/cli-args.js.map +1 -0
- package/dist/cli-output.d.ts +102 -0
- package/dist/cli-output.js +516 -0
- package/dist/cli-output.js.map +1 -0
- package/dist/cli-reference.d.ts +3 -0
- package/dist/cli-reference.js +81 -0
- package/dist/cli-reference.js.map +1 -0
- package/dist/cli-refusal.d.ts +12 -0
- package/dist/cli-refusal.js +52 -0
- package/dist/cli-refusal.js.map +1 -0
- package/dist/cli-shared.d.ts +330 -0
- package/dist/cli-shared.js +492 -0
- package/dist/cli-shared.js.map +1 -0
- package/dist/cli-surface.d.ts +33 -0
- package/dist/cli-surface.js +48 -0
- package/dist/cli-surface.js.map +1 -0
- package/dist/conversation-options.d.ts +15 -0
- package/dist/conversation-options.js +10 -0
- package/dist/conversation-options.js.map +1 -0
- package/dist/credentials-file.d.ts +15 -0
- package/dist/credentials-file.js +56 -0
- package/dist/credentials-file.js.map +1 -0
- package/dist/data-dir.d.ts +1 -1
- package/dist/data-dir.js +1 -1
- package/dist/defect-evidence.d.ts +141 -0
- package/dist/defect-evidence.js +502 -0
- package/dist/defect-evidence.js.map +1 -0
- package/dist/demo-aspect-api.d.ts +209 -0
- package/dist/demo-aspect-api.js +397 -0
- package/dist/demo-aspect-api.js.map +1 -0
- package/dist/demo-aspect-cli.d.ts +3 -0
- package/dist/demo-aspect-cli.js +241 -0
- package/dist/demo-aspect-cli.js.map +1 -0
- package/dist/demo-capture.d.ts +108 -0
- package/dist/demo-capture.js +438 -0
- package/dist/demo-capture.js.map +1 -0
- package/dist/engine.d.ts +35 -0
- package/dist/engine.js +25 -0
- package/dist/engine.js.map +1 -0
- package/dist/environments.d.ts +155 -0
- package/dist/environments.js +364 -0
- package/dist/environments.js.map +1 -0
- package/dist/exit-codes.d.ts +46 -0
- package/dist/exit-codes.js +91 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/explore-adversarial.d.ts +137 -0
- package/dist/explore-adversarial.js +218 -0
- package/dist/explore-adversarial.js.map +1 -0
- package/dist/explore-api.d.ts +7 -187
- package/dist/explore-api.js +7 -301
- package/dist/explore-api.js.map +1 -1
- package/dist/explore-author.d.ts +79 -0
- package/dist/explore-author.js +86 -0
- package/dist/explore-author.js.map +1 -0
- package/dist/explore-cli.d.ts +7 -0
- package/dist/explore-cli.js +963 -0
- package/dist/explore-cli.js.map +1 -0
- package/dist/explore-coverage.d.ts +158 -0
- package/dist/explore-coverage.js +240 -0
- package/dist/explore-coverage.js.map +1 -0
- package/dist/explore-feature.d.ts +127 -0
- package/dist/explore-feature.js +220 -0
- package/dist/explore-feature.js.map +1 -0
- package/dist/explore-goal.d.ts +253 -0
- package/dist/explore-goal.js +374 -0
- package/dist/explore-goal.js.map +1 -0
- package/dist/explore-shared.d.ts +152 -0
- package/dist/explore-shared.js +129 -0
- package/dist/explore-shared.js.map +1 -0
- package/dist/explore-specs.d.ts +53 -0
- package/dist/explore-specs.js +333 -0
- package/dist/explore-specs.js.map +1 -0
- package/dist/findings-filing.d.ts +64 -0
- package/dist/findings-filing.js +108 -0
- package/dist/findings-filing.js.map +1 -0
- package/dist/fixture-auth.d.ts +52 -0
- package/dist/fixture-auth.js +82 -0
- package/dist/fixture-auth.js.map +1 -0
- package/dist/fixture-cli.d.ts +70 -0
- package/dist/fixture-cli.js +178 -0
- package/dist/fixture-cli.js.map +1 -0
- package/dist/github-issue-filer.d.ts +62 -0
- package/dist/github-issue-filer.js +188 -0
- package/dist/github-issue-filer.js.map +1 -0
- package/dist/host-health-run.d.ts +24 -0
- package/dist/host-health-run.js +27 -0
- package/dist/host-health-run.js.map +1 -0
- package/dist/http-5xx-outcome.d.ts +6 -0
- package/dist/http-5xx-outcome.js +39 -0
- package/dist/http-5xx-outcome.js.map +1 -0
- package/dist/inbox-cli.d.ts +7 -0
- package/dist/inbox-cli.js +197 -0
- package/dist/inbox-cli.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init-cli.d.ts +4 -0
- package/dist/init-cli.js +127 -0
- package/dist/init-cli.js.map +1 -0
- package/dist/init-keys.d.ts +19 -2
- package/dist/init-keys.js +15 -4
- package/dist/init-keys.js.map +1 -1
- package/dist/init-next-steps.d.ts +35 -0
- package/dist/init-next-steps.js +79 -0
- package/dist/init-next-steps.js.map +1 -0
- package/dist/invariants-file.d.ts +34 -0
- package/dist/invariants-file.js +68 -0
- package/dist/invariants-file.js.map +1 -0
- package/dist/invariants-validate.d.ts +30 -0
- package/dist/invariants-validate.js +105 -0
- package/dist/invariants-validate.js.map +1 -0
- package/dist/journey-annotate-api.d.ts +76 -0
- package/dist/journey-annotate-api.js +256 -0
- package/dist/journey-annotate-api.js.map +1 -0
- package/dist/journey-annotate-cli.d.ts +9 -0
- package/dist/journey-annotate-cli.js +179 -0
- package/dist/journey-annotate-cli.js.map +1 -0
- package/dist/journey-api.d.ts +79 -2
- package/dist/journey-api.js +136 -19
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.d.ts +4 -0
- package/dist/journey-cli.js +370 -0
- package/dist/journey-cli.js.map +1 -0
- package/dist/journey-demo-api.d.ts +112 -0
- package/dist/journey-demo-api.js +392 -0
- package/dist/journey-demo-api.js.map +1 -0
- package/dist/journey-demo-cli.d.ts +10 -0
- package/dist/journey-demo-cli.js +155 -0
- package/dist/journey-demo-cli.js.map +1 -0
- package/dist/kill-signal.d.ts +193 -0
- package/dist/kill-signal.js +284 -0
- package/dist/kill-signal.js.map +1 -0
- package/dist/launch-armed.d.ts +37 -0
- package/dist/launch-armed.js +31 -0
- package/dist/launch-armed.js.map +1 -0
- package/dist/ledger-api.d.ts +106 -0
- package/dist/ledger-api.js +237 -0
- package/dist/ledger-api.js.map +1 -0
- package/dist/ledger-cli.d.ts +18 -0
- package/dist/ledger-cli.js +107 -0
- package/dist/ledger-cli.js.map +1 -0
- package/dist/load-api.d.ts +29 -11
- package/dist/load-api.js +23 -15
- package/dist/load-api.js.map +1 -1
- package/dist/load-cli.d.ts +4 -0
- package/dist/load-cli.js +97 -0
- package/dist/load-cli.js.map +1 -0
- package/dist/log-correlation.d.ts +147 -0
- package/dist/log-correlation.js +325 -0
- package/dist/log-correlation.js.map +1 -0
- package/dist/log-lines.d.ts +131 -0
- package/dist/log-lines.js +389 -0
- package/dist/log-lines.js.map +1 -0
- package/dist/log-sources.d.ts +71 -0
- package/dist/log-sources.js +235 -0
- package/dist/log-sources.js.map +1 -0
- package/dist/logs-cli.d.ts +3 -0
- package/dist/logs-cli.js +51 -0
- package/dist/logs-cli.js.map +1 -0
- package/dist/logs-retention.d.ts +28 -0
- package/dist/logs-retention.js +84 -0
- package/dist/logs-retention.js.map +1 -0
- package/dist/mcp-api.d.ts +89 -1
- package/dist/mcp-api.js +472 -18
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-args.d.ts +38 -0
- package/dist/mcp-args.js +131 -0
- package/dist/mcp-args.js.map +1 -0
- package/dist/mcp-cli-bridge.d.ts +34 -0
- package/dist/mcp-cli-bridge.js +62 -0
- package/dist/mcp-cli-bridge.js.map +1 -0
- package/dist/mcp-cli-runner.d.ts +29 -0
- package/dist/mcp-cli-runner.js +44 -0
- package/dist/mcp-cli-runner.js.map +1 -0
- package/dist/mcp-cli-tools.d.ts +125 -0
- package/dist/mcp-cli-tools.js +680 -0
- package/dist/mcp-cli-tools.js.map +1 -0
- package/dist/mcp-paths.d.ts +28 -0
- package/dist/mcp-paths.js +76 -0
- package/dist/mcp-paths.js.map +1 -0
- package/dist/mission-actors.d.ts +40 -0
- package/dist/mission-actors.js +72 -0
- package/dist/mission-actors.js.map +1 -0
- package/dist/mission-api.d.ts +35 -0
- package/dist/mission-api.js +58 -2
- package/dist/mission-api.js.map +1 -1
- package/dist/mission-cli.d.ts +4 -0
- package/dist/mission-cli.js +247 -0
- package/dist/mission-cli.js.map +1 -0
- package/dist/mission-exit.d.ts +22 -0
- package/dist/mission-exit.js +26 -0
- package/dist/mission-exit.js.map +1 -0
- package/dist/mission-fixtures.d.ts +225 -0
- package/dist/mission-fixtures.js +828 -0
- package/dist/mission-fixtures.js.map +1 -0
- package/dist/mission-journal.d.ts +60 -0
- package/dist/mission-journal.js +115 -0
- package/dist/mission-journal.js.map +1 -0
- package/dist/mission-queue-cli.d.ts +10 -0
- package/dist/mission-queue-cli.js +198 -0
- package/dist/mission-queue-cli.js.map +1 -0
- package/dist/mission-queue-runner.d.ts +126 -0
- package/dist/mission-queue-runner.js +397 -0
- package/dist/mission-queue-runner.js.map +1 -0
- package/dist/multi-run-cli.d.ts +37 -0
- package/dist/multi-run-cli.js +110 -0
- package/dist/multi-run-cli.js.map +1 -0
- package/dist/multi-run.d.ts +339 -0
- package/dist/multi-run.js +619 -0
- package/dist/multi-run.js.map +1 -0
- package/dist/openrouter-call.d.ts +22 -0
- package/dist/openrouter-call.js +63 -0
- package/dist/openrouter-call.js.map +1 -0
- package/dist/profile-cli.d.ts +4 -0
- package/dist/profile-cli.js +57 -0
- package/dist/profile-cli.js.map +1 -0
- package/dist/program.d.ts +3 -75
- package/dist/program.js +119 -1921
- package/dist/program.js.map +1 -1
- package/dist/project-dir.d.ts +96 -0
- package/dist/project-dir.js +220 -0
- package/dist/project-dir.js.map +1 -0
- package/dist/record-api.d.ts +10 -6
- package/dist/record-api.js +39 -28
- package/dist/record-api.js.map +1 -1
- package/dist/record-cli.d.ts +4 -0
- package/dist/record-cli.js +64 -0
- package/dist/record-cli.js.map +1 -0
- package/dist/recording-cli.d.ts +4 -0
- package/dist/recording-cli.js +248 -0
- package/dist/recording-cli.js.map +1 -0
- package/dist/regression-api.d.ts +101 -0
- package/dist/regression-api.js +384 -5
- package/dist/regression-api.js.map +1 -1
- package/dist/regression-cli.d.ts +4 -0
- package/dist/regression-cli.js +232 -0
- package/dist/regression-cli.js.map +1 -0
- package/dist/report-api.d.ts +146 -0
- package/dist/report-api.js +430 -0
- package/dist/report-api.js.map +1 -0
- package/dist/report-cli.d.ts +12 -0
- package/dist/report-cli.js +147 -0
- package/dist/report-cli.js.map +1 -0
- package/dist/result-schema.d.ts +22 -0
- package/dist/result-schema.js +28 -0
- package/dist/result-schema.js.map +1 -0
- package/dist/run-index.d.ts +29 -0
- package/dist/run-index.js +70 -0
- package/dist/run-index.js.map +1 -0
- package/dist/run-screenshots.d.ts +123 -0
- package/dist/run-screenshots.js +229 -0
- package/dist/run-screenshots.js.map +1 -0
- package/dist/runtime-env.d.ts +8 -0
- package/dist/runtime-env.js +22 -0
- package/dist/runtime-env.js.map +1 -0
- package/dist/secret-args.d.ts +23 -0
- package/dist/secret-args.js +45 -0
- package/dist/secret-args.js.map +1 -0
- package/dist/serve-cli.d.ts +4 -0
- package/dist/serve-cli.js +95 -0
- package/dist/serve-cli.js.map +1 -0
- package/dist/server-log-verify.d.ts +34 -0
- package/dist/server-log-verify.js +115 -0
- package/dist/server-log-verify.js.map +1 -0
- package/dist/session-check.d.ts +14 -0
- package/dist/session-check.js +44 -0
- package/dist/session-check.js.map +1 -0
- package/dist/site-cli.d.ts +4 -0
- package/dist/site-cli.js +127 -0
- package/dist/site-cli.js.map +1 -0
- package/dist/site-gate-cli.d.ts +28 -0
- package/dist/site-gate-cli.js +58 -0
- package/dist/site-gate-cli.js.map +1 -0
- package/dist/source-api.js +18 -3
- package/dist/source-api.js.map +1 -1
- package/dist/source-cli.d.ts +4 -0
- package/dist/source-cli.js +284 -0
- package/dist/source-cli.js.map +1 -0
- package/dist/source-run-api.d.ts +27 -1
- package/dist/source-run-api.js +22 -11
- package/dist/source-run-api.js.map +1 -1
- package/dist/storage-state-snapshot.d.ts +50 -0
- package/dist/storage-state-snapshot.js +87 -0
- package/dist/storage-state-snapshot.js.map +1 -0
- package/dist/suite-explore-options.d.ts +289 -0
- package/dist/suite-explore-options.js +140 -0
- package/dist/suite-explore-options.js.map +1 -0
- package/dist/target-config.d.ts +109 -0
- package/dist/target-config.js +216 -0
- package/dist/target-config.js.map +1 -0
- package/dist/transcript-file.d.ts +12 -0
- package/dist/transcript-file.js +23 -0
- package/dist/transcript-file.js.map +1 -0
- package/dist/ui-api.d.ts +3 -0
- package/dist/ui-api.js +7 -1
- package/dist/ui-api.js.map +1 -1
- package/dist/usability-capture.d.ts +43 -0
- package/dist/usability-capture.js +326 -0
- package/dist/usability-capture.js.map +1 -0
- package/dist/usage-config.d.ts +36 -0
- package/dist/usage-config.js +114 -0
- package/dist/usage-config.js.map +1 -0
- package/dist/ux-api.d.ts +3 -75
- package/dist/ux-api.js +3 -220
- package/dist/ux-api.js.map +1 -1
- package/dist/ux-cli.d.ts +4 -0
- package/dist/ux-cli.js +102 -0
- package/dist/ux-cli.js.map +1 -0
- package/dist/ux-config.d.ts +29 -0
- package/dist/ux-config.js +103 -0
- package/dist/ux-config.js.map +1 -0
- package/dist/ux-evidence.d.ts +54 -0
- package/dist/ux-evidence.js +197 -0
- package/dist/ux-evidence.js.map +1 -0
- package/dist/ux-review.d.ts +112 -0
- package/dist/ux-review.js +151 -0
- package/dist/ux-review.js.map +1 -0
- package/dist/ux-usability.d.ts +238 -0
- package/dist/ux-usability.js +494 -0
- package/dist/ux-usability.js.map +1 -0
- package/dist/verify-fix-api.d.ts +173 -0
- package/dist/verify-fix-api.js +454 -0
- package/dist/verify-fix-api.js.map +1 -0
- package/dist/verify-fix-cli.d.ts +4 -0
- package/dist/verify-fix-cli.js +110 -0
- package/dist/verify-fix-cli.js.map +1 -0
- package/package.json +19 -14
- package/skills/jevitate-ci-check/SKILL.md +77 -0
- package/skills/jevitate-demo/SKILL.md +61 -0
- package/skills/jevitate-explore/SKILL.md +88 -87
- package/skills/jevitate-getting-started/SKILL.md +88 -0
- package/skills/jevitate-load-test/SKILL.md +11 -2
- package/skills/jevitate-mission-scope/SKILL.md +19 -11
- package/skills/jevitate-record/SKILL.md +23 -5
- package/skills/jevitate-run-journey/SKILL.md +61 -17
- package/skills/jevitate-sources/SKILL.md +57 -14
- package/skills/jevitate-ux-review/SKILL.md +106 -16
- package/skills/jevitate-verify-fix/SKILL.md +76 -0
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import { redactText } from "@jevitate/ai-core";
|
|
2
|
+
import { worstOutcome } from "@jevitate/domain";
|
|
3
|
+
import { normalizeRoute } from "@jevitate/explore";
|
|
4
|
+
import { closeLogSources, openLogSources, } from "./log-sources.js";
|
|
5
|
+
import { DotnetEntryGrouper, matchesLogDefect, matchesLogIgnore, normalizeLogMessage, parseLogDefectSpec, parseLogIgnoreSpec, parseLogLine, serverLogFingerprint, } from "./log-lines.js";
|
|
6
|
+
const UNATTRIBUTED_ROUTE = "(run)";
|
|
7
|
+
/** Only these levels are auto-attached as step evidence (a `--log-defect` match is ALWAYS attached,
|
|
8
|
+
* whatever its level, since it is now a candidate defect). */
|
|
9
|
+
const ATTACH_LEVELS = new Set(["warn", "error"]);
|
|
10
|
+
export const DEFAULT_SERVER_LOG_DRAIN_MS = 3_000;
|
|
11
|
+
function sleep(ms) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const t = setTimeout(resolve, ms);
|
|
14
|
+
t.unref?.();
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Opens every source and starts correlating (#142). Returns `undefined` when `sources` is empty —
|
|
19
|
+
* a complete no-op, so a run without `--log-source` pays nothing.
|
|
20
|
+
*/
|
|
21
|
+
export function openServerLogRuntime(opts) {
|
|
22
|
+
if (opts.sources.length === 0)
|
|
23
|
+
return undefined;
|
|
24
|
+
return new ServerLogRuntime(opts);
|
|
25
|
+
}
|
|
26
|
+
export class ServerLogRuntime {
|
|
27
|
+
#handles;
|
|
28
|
+
#groupers = [];
|
|
29
|
+
#lines = [];
|
|
30
|
+
#stepEpoch = new Map();
|
|
31
|
+
#missionStartEpochMs = Date.now();
|
|
32
|
+
#secrets;
|
|
33
|
+
#matchers;
|
|
34
|
+
#drainMs;
|
|
35
|
+
#quietOk;
|
|
36
|
+
#logIgnore;
|
|
37
|
+
#ignoredLines = 0;
|
|
38
|
+
#inner;
|
|
39
|
+
#maxTotalLines = 20_000;
|
|
40
|
+
#finished = false;
|
|
41
|
+
#exitHook = () => {
|
|
42
|
+
for (const h of this.#handles)
|
|
43
|
+
h.killSync();
|
|
44
|
+
};
|
|
45
|
+
constructor(opts) {
|
|
46
|
+
this.#secrets = opts.secrets;
|
|
47
|
+
this.#matchers = opts.logDefect;
|
|
48
|
+
this.#drainMs = opts.drainMs ?? DEFAULT_SERVER_LOG_DRAIN_MS;
|
|
49
|
+
this.#quietOk = new Set(opts.quietOk ?? []);
|
|
50
|
+
this.#logIgnore = opts.logIgnore ?? [];
|
|
51
|
+
this.#inner = opts.onTranscriptEntry;
|
|
52
|
+
// One `openLogSources` call per spec: each source's `onLine` must stamp ITS OWN spec onto every
|
|
53
|
+
// `LogLine` (a shared callback across sources could not tell them apart). Each source also gets
|
|
54
|
+
// its OWN `DotnetEntryGrouper` (#165) — a multi-line .NET entry must never straddle two sources.
|
|
55
|
+
this.#handles = opts.sources.map((spec, i) => {
|
|
56
|
+
this.#groupers[i] = new DotnetEntryGrouper();
|
|
57
|
+
return openLogSources([spec], {
|
|
58
|
+
onLine: (raw, arrivalEpochMs) => {
|
|
59
|
+
const grouper = this.#groupers[i];
|
|
60
|
+
for (const entry of grouper.feed(raw, arrivalEpochMs))
|
|
61
|
+
this.#pushLine(entry.raw, entry.epochMs, spec.raw);
|
|
62
|
+
},
|
|
63
|
+
})[0];
|
|
64
|
+
});
|
|
65
|
+
process.on("exit", this.#exitHook);
|
|
66
|
+
}
|
|
67
|
+
#pushLine(raw, epochMs, sourceRaw) {
|
|
68
|
+
if (this.#lines.length >= this.#maxTotalLines)
|
|
69
|
+
return;
|
|
70
|
+
const parsed = parseLogLine(raw, epochMs, sourceRaw);
|
|
71
|
+
// #169 item 3: a known-noise line is dropped here, BEFORE it can become step evidence, a
|
|
72
|
+
// `topMessages`/`byLevel` entry or a defect candidate — but it was still delivered by the
|
|
73
|
+
// source (already counted in `linesRead`), so it says nothing about the oracle's health.
|
|
74
|
+
if (this.#logIgnore.some((m) => matchesLogIgnore(parsed, m))) {
|
|
75
|
+
this.#ignoredLines += 1;
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.#lines.push(parsed);
|
|
79
|
+
}
|
|
80
|
+
/** Flushes any still-pending `DotnetEntryGrouper` entry per source — the last entry in a .NET log
|
|
81
|
+
* has no following header to trigger its own flush otherwise. */
|
|
82
|
+
#flushGroupers() {
|
|
83
|
+
this.#groupers.forEach((grouper, i) => {
|
|
84
|
+
const entry = grouper.flush();
|
|
85
|
+
const spec = this.#handles[i]?.spec.raw;
|
|
86
|
+
if (entry !== undefined && spec !== undefined)
|
|
87
|
+
this.#pushLine(entry.raw, entry.epochMs, spec);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
/** Wraps the journal's own `TranscriptListener`: unchanged persistence, plus this step's epoch. */
|
|
91
|
+
onTranscriptEntry = (entry, all) => {
|
|
92
|
+
this.#stepEpoch.set(entry.step, Date.now());
|
|
93
|
+
this.#inner?.(entry, all);
|
|
94
|
+
};
|
|
95
|
+
/** Call once the mission function has returned. Waits out the drain window, closes every source,
|
|
96
|
+
* and returns the correlated transcript/summary/defects. Idempotent (a second call is a no-op
|
|
97
|
+
* empty result) — never blocks the mission itself, only this post-processing step. */
|
|
98
|
+
async finish(transcript) {
|
|
99
|
+
if (this.#finished)
|
|
100
|
+
return { transcript, summary: this.#summary([]), defects: [] };
|
|
101
|
+
this.#finished = true;
|
|
102
|
+
await sleep(this.#drainMs);
|
|
103
|
+
this.#flushGroupers();
|
|
104
|
+
await closeLogSources(this.#handles);
|
|
105
|
+
process.off("exit", this.#exitHook);
|
|
106
|
+
return this.#correlate(transcript);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Safety net for the mission-threw-before-`finish` path: closes every source immediately, with NO
|
|
110
|
+
* drain wait and no correlation. A no-op once `finish` already ran. Never throws.
|
|
111
|
+
*/
|
|
112
|
+
async abort() {
|
|
113
|
+
if (this.#finished)
|
|
114
|
+
return;
|
|
115
|
+
this.#finished = true;
|
|
116
|
+
await closeLogSources(this.#handles);
|
|
117
|
+
process.off("exit", this.#exitHook);
|
|
118
|
+
}
|
|
119
|
+
#correlate(transcript) {
|
|
120
|
+
const windows = stepWindows(transcript, this.#stepEpoch, this.#missionStartEpochMs, this.#drainMs);
|
|
121
|
+
const perStep = new Map();
|
|
122
|
+
const perStepRaw = new Map();
|
|
123
|
+
const unattributed = [];
|
|
124
|
+
let attachedLines = 0;
|
|
125
|
+
for (const line of this.#lines) {
|
|
126
|
+
const win = windows.find((w) => line.epochMs >= w.startMs && line.epochMs <= w.endMs);
|
|
127
|
+
const isDefectCandidate = this.#matchers.some((m) => matchesLogDefect(line, m));
|
|
128
|
+
const attach = ATTACH_LEVELS.has(line.level) || isDefectCandidate;
|
|
129
|
+
if (win === undefined) {
|
|
130
|
+
if (attach)
|
|
131
|
+
unattributed.push(line);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (!attach)
|
|
135
|
+
continue;
|
|
136
|
+
attachedLines += 1;
|
|
137
|
+
const list = perStep.get(win.step) ?? [];
|
|
138
|
+
list.push({
|
|
139
|
+
level: line.level,
|
|
140
|
+
message: redactText(line.message, this.#secrets),
|
|
141
|
+
raw: redactText(line.raw, this.#secrets),
|
|
142
|
+
source: line.source,
|
|
143
|
+
epochMs: line.epochMs,
|
|
144
|
+
...(line.target === undefined ? {} : { target: redactText(line.target, this.#secrets) }),
|
|
145
|
+
});
|
|
146
|
+
perStep.set(win.step, list);
|
|
147
|
+
const rawList = perStepRaw.get(win.step) ?? [];
|
|
148
|
+
rawList.push(line);
|
|
149
|
+
perStepRaw.set(win.step, rawList);
|
|
150
|
+
}
|
|
151
|
+
const augmented = transcript.map((entry) => {
|
|
152
|
+
const logs = perStep.get(entry.step);
|
|
153
|
+
return logs === undefined || logs.length === 0 ? entry : { ...entry, serverLogs: logs };
|
|
154
|
+
});
|
|
155
|
+
const defects = this.#matchers.length === 0 ? [] : this.#buildDefects(transcript, perStepRaw, unattributed);
|
|
156
|
+
const summary = this.#summary(unattributed, attachedLines);
|
|
157
|
+
return { transcript: augmented, summary, defects };
|
|
158
|
+
}
|
|
159
|
+
#buildDefects(transcript, perStepRaw, unattributed) {
|
|
160
|
+
const grouped = new Map();
|
|
161
|
+
const lastStep = transcript.length > 0 ? transcript[transcript.length - 1].step : 0;
|
|
162
|
+
const consider = (line, route, atStep) => {
|
|
163
|
+
const matched = this.#matchers.find((m) => matchesLogDefect(line, m));
|
|
164
|
+
if (matched === undefined)
|
|
165
|
+
return;
|
|
166
|
+
const normalizedMessage = normalizeLogMessage(line.message);
|
|
167
|
+
const fp = serverLogFingerprint(route, normalizedMessage, line.target);
|
|
168
|
+
const existing = grouped.get(fp);
|
|
169
|
+
if (existing !== undefined) {
|
|
170
|
+
existing.count += 1;
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// #169 item 3: the STORED route is templated too (the shared #95/#127 templater, same as the
|
|
174
|
+
// fingerprint already used internally) — two occurrences that only differ by an id in the URL
|
|
175
|
+
// read as the same defect everywhere, not just in the hash.
|
|
176
|
+
const templatedRoute = route === UNATTRIBUTED_ROUTE ? route : normalizeRoute(route);
|
|
177
|
+
grouped.set(fp, {
|
|
178
|
+
count: 1,
|
|
179
|
+
defect: {
|
|
180
|
+
fingerprint: fp,
|
|
181
|
+
related: [fp],
|
|
182
|
+
kind: "server-log",
|
|
183
|
+
title: `Server log ${line.level} on ${templatedRoute === UNATTRIBUTED_ROUTE ? "(unattributed)" : templatedRoute}${line.target === undefined ? "" : ` (${line.target})`}: ${normalizedMessage.slice(0, 80)}`,
|
|
184
|
+
route: templatedRoute,
|
|
185
|
+
level: line.level,
|
|
186
|
+
message: redactText(line.message, this.#secrets),
|
|
187
|
+
occurrences: 1,
|
|
188
|
+
repro: { recordingStepIndex: recordingStepIndexFor(transcript, atStep) },
|
|
189
|
+
serverLog: {
|
|
190
|
+
sources: this.#handles.map((h) => h.spec.raw),
|
|
191
|
+
matcher: matched.raw,
|
|
192
|
+
normalizedMessage,
|
|
193
|
+
drainMs: this.#drainMs,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
for (const entry of transcript) {
|
|
199
|
+
const route = entry.url;
|
|
200
|
+
for (const line of perStepRaw.get(entry.step) ?? [])
|
|
201
|
+
consider(line, route, entry.step);
|
|
202
|
+
}
|
|
203
|
+
for (const line of unattributed)
|
|
204
|
+
consider(line, UNATTRIBUTED_ROUTE, lastStep);
|
|
205
|
+
return [...grouped.values()].map(({ defect, count }) => ({ ...defect, occurrences: count }));
|
|
206
|
+
}
|
|
207
|
+
#summary(unattributed, attachedLines = 0) {
|
|
208
|
+
const byLevel = {};
|
|
209
|
+
for (const line of this.#lines)
|
|
210
|
+
byLevel[line.level] = (byLevel[line.level] ?? 0) + 1;
|
|
211
|
+
const counts = new Map();
|
|
212
|
+
for (const line of this.#lines) {
|
|
213
|
+
const message = normalizeLogMessage(line.message);
|
|
214
|
+
const key = `${line.level}|${line.target ?? ""}|${message}`;
|
|
215
|
+
const e = counts.get(key);
|
|
216
|
+
if (e === undefined)
|
|
217
|
+
counts.set(key, { level: line.level, message, ...(line.target === undefined ? {} : { target: line.target }), count: 1 });
|
|
218
|
+
else
|
|
219
|
+
e.count += 1;
|
|
220
|
+
}
|
|
221
|
+
const topMessages = [...counts.values()].sort((a, b) => b.count - a.count).slice(0, 10);
|
|
222
|
+
const sources = this.#handles.map((h) => ({
|
|
223
|
+
spec: h.spec.raw,
|
|
224
|
+
opened: h.opened,
|
|
225
|
+
linesRead: h.linesRead,
|
|
226
|
+
truncated: h.truncated,
|
|
227
|
+
...(h.error === undefined ? {} : { error: h.error }),
|
|
228
|
+
...(this.#quietOk.has(h.spec.raw) ? { quietOk: true } : {}),
|
|
229
|
+
}));
|
|
230
|
+
// Per-source health (#169): a source is unhealthy when it never opened/errored, OR it opened and
|
|
231
|
+
// delivered not one line while NOT declared `--log-quiet-ok` — a source the operator KNOWS runs
|
|
232
|
+
// quiet. Every declared source must be healthy for the oracle to count as "held": one dead/silent
|
|
233
|
+
// source among several is still a hole in the evidence, not proof of anything.
|
|
234
|
+
const unhealthy = sources.filter((s) => {
|
|
235
|
+
if (!s.opened || s.error !== undefined)
|
|
236
|
+
return true;
|
|
237
|
+
return s.linesRead === 0 && s.quietOk !== true;
|
|
238
|
+
});
|
|
239
|
+
const oracleOk = this.#matchers.length === 0 || unhealthy.length === 0;
|
|
240
|
+
const failedSpecs = unhealthy.filter((s) => !s.opened || s.error !== undefined).map((s) => s.spec);
|
|
241
|
+
const quietSpecs = unhealthy.filter((s) => s.opened && s.error === undefined).map((s) => s.spec);
|
|
242
|
+
let oracleReason;
|
|
243
|
+
if (oracleOk) {
|
|
244
|
+
oracleReason = undefined;
|
|
245
|
+
}
|
|
246
|
+
else if (quietSpecs.length === 0) {
|
|
247
|
+
oracleReason =
|
|
248
|
+
"the --log-defect oracle could not run: every declared --log-source failed to open or read a line — an absence of server-log defects proves nothing";
|
|
249
|
+
}
|
|
250
|
+
else if (failedSpecs.length === 0) {
|
|
251
|
+
oracleReason = "log source produced no lines";
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
oracleReason = `the --log-defect oracle could not run: ${failedSpecs.join(", ")} failed to open or read a line; ${quietSpecs.join(", ")} produced no lines`;
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
sources,
|
|
258
|
+
byLevel,
|
|
259
|
+
topMessages,
|
|
260
|
+
attachedLines,
|
|
261
|
+
unattributedLines: unattributed.length,
|
|
262
|
+
ignoredLines: this.#ignoredLines,
|
|
263
|
+
oracleOk,
|
|
264
|
+
...(oracleReason === undefined ? {} : { oracleReason }),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/** Contiguous per-step correlation windows: `[previous settle, this settle]`, the LAST one extended
|
|
269
|
+
* by `drainMs` so async backend work that lands after the mission's own bounds still attaches. */
|
|
270
|
+
function stepWindows(transcript, stepEpoch, missionStartEpochMs, drainMs) {
|
|
271
|
+
const windows = [];
|
|
272
|
+
let prevEnd = missionStartEpochMs;
|
|
273
|
+
for (let i = 0; i < transcript.length; i++) {
|
|
274
|
+
const entry = transcript[i];
|
|
275
|
+
const settle = stepEpoch.get(entry.step) ?? prevEnd;
|
|
276
|
+
const isLast = i === transcript.length - 1;
|
|
277
|
+
const endMs = isLast ? settle + drainMs : settle;
|
|
278
|
+
windows.push({ step: entry.step, startMs: prevEnd, endMs });
|
|
279
|
+
prevEnd = settle;
|
|
280
|
+
}
|
|
281
|
+
return windows;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* The flat `Recording` step index for a transcript step (#142's best-effort mapping): a failed
|
|
285
|
+
* action (`actOk: false`) never becomes a Recording step (`transcript.ts`'s own invariant), so this
|
|
286
|
+
* counts only the successful ones up to and including `uptoStep`. Clamped to 0 when none yet ran —
|
|
287
|
+
* `verify-fix` then replays from the start, which is always a safe (if wide) anchor.
|
|
288
|
+
*/
|
|
289
|
+
function recordingStepIndexFor(transcript, uptoStep) {
|
|
290
|
+
let idx = -1;
|
|
291
|
+
for (const e of transcript) {
|
|
292
|
+
if (e.step > uptoStep)
|
|
293
|
+
break;
|
|
294
|
+
if (e.actOk)
|
|
295
|
+
idx += 1;
|
|
296
|
+
}
|
|
297
|
+
return Math.max(0, idx);
|
|
298
|
+
}
|
|
299
|
+
/** Parses `--log-defect` values, failing closed on the first bad one. */
|
|
300
|
+
export function parseLogDefectSpecs(raw) {
|
|
301
|
+
return raw.map(parseLogDefectSpec);
|
|
302
|
+
}
|
|
303
|
+
/** Parses `--log-ignore` values, failing closed on the first bad one (#169 item 3). */
|
|
304
|
+
export function parseLogIgnoreSpecs(raw) {
|
|
305
|
+
return raw.map(parseLogIgnoreSpec);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Folds a server-log correlation result into an already-computed `MissionOutcome` (#142, follow-up
|
|
309
|
+
* on the exit-code requirement): a found `server-log` defect is at least `defects-found` — via
|
|
310
|
+
* `worstOutcome`, so it never DOWNGRADES a worse outcome (hang/crashed/inconclusive already proves
|
|
311
|
+
* more, or the same, than a defect). An unreadable `--log-defect` oracle (`oracleOk: false`) turns
|
|
312
|
+
* an otherwise-`clean` run `inconclusive` — its absence of defects proves nothing when the source
|
|
313
|
+
* that would have caught them was never demonstrably read. `undefined` (no `--log-source`) is a
|
|
314
|
+
* complete no-op.
|
|
315
|
+
*/
|
|
316
|
+
export function applyServerLogOutcome(outcome, run) {
|
|
317
|
+
if (run === undefined)
|
|
318
|
+
return outcome;
|
|
319
|
+
if (run.defects.length > 0)
|
|
320
|
+
return worstOutcome(outcome, "defects-found");
|
|
321
|
+
if (!run.summary.oracleOk && outcome === "clean")
|
|
322
|
+
return "inconclusive";
|
|
323
|
+
return outcome;
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=log-correlation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-correlation.js","sourceRoot":"","sources":["../src/log-correlation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend log line parsing, normalization and fingerprinting (#142). Pure and mechanical — never
|
|
3
|
+
* `eval`ed, never a model call. A parsed line is ONE of the run's evidence sources: it is
|
|
4
|
+
* correlated to the step it landed during (`log-correlation.ts`) and, with `--log-defect`,
|
|
5
|
+
* optionally promoted to a `server-log` defect.
|
|
6
|
+
*/
|
|
7
|
+
export type LogLevel = "error" | "warn" | "info" | "debug" | "unknown";
|
|
8
|
+
/** True when `a` is at least as severe as `b`. `unknown` is never >= a NAMED level (fail closed). */
|
|
9
|
+
export declare function levelAtLeast(a: LogLevel, b: LogLevel): boolean;
|
|
10
|
+
/** A parsed backend log line. `raw`/`message` are UNREDACTED — callers redact before persisting. */
|
|
11
|
+
export interface LogLine {
|
|
12
|
+
readonly level: LogLevel;
|
|
13
|
+
/** The human message: a JSON/logfmt log's `message`/`msg`/`error` field, else the whole line. */
|
|
14
|
+
readonly message: string;
|
|
15
|
+
/** The raw line exactly as read (for a multi-line entry — .NET console, #165 — every joined line). */
|
|
16
|
+
readonly raw: string;
|
|
17
|
+
/** The line's own timestamp (ms since epoch) when one parsed; else the arrival time. */
|
|
18
|
+
readonly epochMs: number;
|
|
19
|
+
/** True when `epochMs` came from the line itself, not from arrival order. */
|
|
20
|
+
readonly ownTimestamp: boolean;
|
|
21
|
+
/** The `--log-source` spec this line came from (its raw form, e.g. `file:/var/log/app.log`). */
|
|
22
|
+
readonly source: string;
|
|
23
|
+
/**
|
|
24
|
+
* The structured logger's own module/category (#169): a JSON log's `target`/`logger` field (Rust
|
|
25
|
+
* `tracing`'s `target`), so a `server-log` defect's fingerprint tells apart two distinct errors
|
|
26
|
+
* that happen to normalize to the same message class.
|
|
27
|
+
*/
|
|
28
|
+
readonly target?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Parses one raw log line — or, for the .NET console format (#165), one already-grouped multi-line
|
|
32
|
+
* entry (see `DotnetEntryGrouper`): JSON (`level`/`severity` + `time`/`timestamp`/`ts`), then logfmt
|
|
33
|
+
* (`level=error msg="…" time=…`), then the .NET default console formatter (`lvl: Category[id]` +
|
|
34
|
+
* indented continuation lines), then Serilog's bracketed console theme (`[HH:mm:ss ERR] …`), then a
|
|
35
|
+
* generic bracketed/bare level with an optional leading ISO timestamp, else falls back to the line
|
|
36
|
+
* verbatim with an `unknown` level and the arrival time. Never throws.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseLogLine(raw: string, arrivalEpochMs: number, source: string): LogLine;
|
|
39
|
+
/** One raw (possibly multi-line, `\n`-joined) entry, ready for `parseLogLine`. */
|
|
40
|
+
export interface RawLogEntry {
|
|
41
|
+
readonly raw: string;
|
|
42
|
+
readonly epochMs: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Groups the .NET default console formatter's multi-line entries (#165) — a `lvl: Category[id]`
|
|
46
|
+
* header followed by one or more indented message/exception-stack-trace lines — into ONE logical
|
|
47
|
+
* entry before it reaches `parseLogLine`. Stateful and meant for ONE `--log-source` (`log-
|
|
48
|
+
* correlation.ts` keeps one instance per source): lines arrive one at a time, in order, from `log-
|
|
49
|
+
* sources.ts`'s line splitter.
|
|
50
|
+
*
|
|
51
|
+
* A header line always starts a NEW pending entry (flushing whatever was pending first); an
|
|
52
|
+
* indented, non-blank line — while an entry is pending — extends it instead of starting its own;
|
|
53
|
+
* anything else (not indented, not itself a header) is its own one-line entry. Every other log
|
|
54
|
+
* format (JSON, logfmt, bracketed/bare) never triggers buffering: `feed` only holds a line back
|
|
55
|
+
* when it is itself a header or it is indented AND a header is already pending, so a single
|
|
56
|
+
* already-indented stray line with no pending entry passes straight through unchanged.
|
|
57
|
+
*/
|
|
58
|
+
export declare class DotnetEntryGrouper {
|
|
59
|
+
#private;
|
|
60
|
+
/** Feed one raw line. Returns the entries this line completed — usually 0 or 1, occasionally 2
|
|
61
|
+
* (a pending entry flushed by, immediately followed by, this line's own one-line entry). */
|
|
62
|
+
feed(raw: string, epochMs: number): RawLogEntry[];
|
|
63
|
+
/** Flushes a still-pending entry (call when the source is closing: the log's last entry has no
|
|
64
|
+
* following header/non-continuation line to trigger its own flush). `undefined` when idle. */
|
|
65
|
+
flush(): RawLogEntry | undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The CLASS of a log message, for correlation-noise dedup and the `server-log` defect fingerprint:
|
|
69
|
+
* an ISO timestamp, then a uuid, are replaced by placeholders first (so a timestamp's own digits
|
|
70
|
+
* don't collide with the generic number-stripping below), then `@jevitate/explore`'s `messageClass`
|
|
71
|
+
* strips URLs, quoted values, long hex ids and remaining numbers. Two occurrences of one bug that
|
|
72
|
+
* differ only in an id, a count or a timestamp share a class.
|
|
73
|
+
*/
|
|
74
|
+
export declare function normalizeLogMessage(message: string): string;
|
|
75
|
+
/**
|
|
76
|
+
* A `server-log` defect's fingerprint (#142): the templated route the line correlated to, plus the
|
|
77
|
+
* normalized message class, plus — when known (#169) — the logger's own `target`/`logger`/category
|
|
78
|
+
* (Rust `tracing`'s `target`, a JSON log's `logger`, a .NET entry's category). Two lines whose
|
|
79
|
+
* message happens to normalize the same, from two different loggers/modules, are DISTINCT defects:
|
|
80
|
+
* without `target` they would collapse into one fingerprint, hiding one of the two real bugs.
|
|
81
|
+
* Unattributed lines (outside every step window) are fingerprinted with `route = "(run)"` — still
|
|
82
|
+
* stable across repeated occurrences of the same line.
|
|
83
|
+
*/
|
|
84
|
+
export declare function serverLogFingerprint(route: string, normalizedMessage: string, target?: string): string;
|
|
85
|
+
export declare class LogSpecError extends Error {
|
|
86
|
+
readonly code: "E_LOG_SPEC";
|
|
87
|
+
constructor(message: string);
|
|
88
|
+
}
|
|
89
|
+
/** A `--log-defect` matcher: a minimum level, or a `/regex/flags` pattern over the raw line. */
|
|
90
|
+
export type LogDefectMatcher = {
|
|
91
|
+
readonly kind: "level";
|
|
92
|
+
readonly level: LogLevel;
|
|
93
|
+
readonly raw: string;
|
|
94
|
+
} | {
|
|
95
|
+
readonly kind: "pattern";
|
|
96
|
+
readonly re: RegExp;
|
|
97
|
+
readonly raw: string;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Parses one `--log-defect` value: `/pattern/flags` (bounded length, compiled once via `new
|
|
101
|
+
* RegExp` — never `eval`ed) or a level name (`error`, `warn`, `info`, `debug`), matched as
|
|
102
|
+
* `level >= this`. Throws `LogSpecError` on anything else, so a bad spec is refused before any
|
|
103
|
+
* browser opens (the same fail-closed discipline as `--invariants`).
|
|
104
|
+
*/
|
|
105
|
+
export declare function parseLogDefectSpec(raw: string): LogDefectMatcher;
|
|
106
|
+
/** Whether a parsed line matches a `--log-defect` matcher. */
|
|
107
|
+
export declare function matchesLogDefect(line: Pick<LogLine, "level" | "raw">, matcher: LogDefectMatcher): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* A `--log-ignore` matcher (#169 item 3): known-noise lines (a periodic background job's own
|
|
110
|
+
* expected error, say) excluded from BOTH correlation (never attached as step evidence) and the
|
|
111
|
+
* `--log-defect` oracle (never a candidate defect, never counted in `topMessages`/`byLevel`) — but
|
|
112
|
+
* still counted toward the source's `linesRead` (the oracle demonstrably tailed something) and
|
|
113
|
+
* reported separately as `serverLogs.ignoredLines`, so an operator can see what was filtered.
|
|
114
|
+
*/
|
|
115
|
+
export type LogIgnoreMatcher = {
|
|
116
|
+
readonly kind: "pattern";
|
|
117
|
+
readonly re: RegExp;
|
|
118
|
+
readonly raw: string;
|
|
119
|
+
} | {
|
|
120
|
+
readonly kind: "substring";
|
|
121
|
+
readonly value: string;
|
|
122
|
+
readonly raw: string;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Parses one `--log-ignore` value: `/pattern/flags` (bounded length, compiled once via `new RegExp`
|
|
126
|
+
* — never `eval`ed) or a plain substring, matched against the line's RAW text. Throws `LogSpecError`
|
|
127
|
+
* on anything empty/invalid/too long, failing closed before any browser opens.
|
|
128
|
+
*/
|
|
129
|
+
export declare function parseLogIgnoreSpec(raw: string): LogIgnoreMatcher;
|
|
130
|
+
/** Whether a parsed line matches a `--log-ignore` matcher (substring/regex over the RAW line). */
|
|
131
|
+
export declare function matchesLogIgnore(line: Pick<LogLine, "raw">, matcher: LogIgnoreMatcher): boolean;
|