@codyswann/lisa 4.21.5 → 4.22.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/all/copy-overwrite/scripts/lisa-environment-prepare.mjs +28 -12
- package/dist/cli/doctor-nightly-e2e-guard-command-files.d.ts +19 -0
- package/dist/cli/doctor-nightly-e2e-guard-command-files.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-command-files.js +221 -0
- package/dist/cli/doctor-nightly-e2e-guard-command-files.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-contract.d.ts +113 -0
- package/dist/cli/doctor-nightly-e2e-guard-contract.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-contract.js +87 -0
- package/dist/cli/doctor-nightly-e2e-guard-contract.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-deadline.d.ts +61 -0
- package/dist/cli/doctor-nightly-e2e-guard-deadline.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-deadline.js +97 -0
- package/dist/cli/doctor-nightly-e2e-guard-deadline.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-evidence.d.ts +52 -0
- package/dist/cli/doctor-nightly-e2e-guard-evidence.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-evidence.js +68 -0
- package/dist/cli/doctor-nightly-e2e-guard-evidence.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-graph.d.ts +14 -0
- package/dist/cli/doctor-nightly-e2e-guard-graph.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-graph.js +130 -0
- package/dist/cli/doctor-nightly-e2e-guard-graph.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-io.d.ts +41 -0
- package/dist/cli/doctor-nightly-e2e-guard-io.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-io.js +239 -0
- package/dist/cli/doctor-nightly-e2e-guard-io.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-job.d.ts +31 -0
- package/dist/cli/doctor-nightly-e2e-guard-job.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-job.js +156 -0
- package/dist/cli/doctor-nightly-e2e-guard-job.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-proof.d.ts +42 -0
- package/dist/cli/doctor-nightly-e2e-guard-proof.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-proof.js +57 -0
- package/dist/cli/doctor-nightly-e2e-guard-proof.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-remediation.d.ts +32 -0
- package/dist/cli/doctor-nightly-e2e-guard-remediation.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-remediation.js +55 -0
- package/dist/cli/doctor-nightly-e2e-guard-remediation.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-runtime.d.ts +34 -0
- package/dist/cli/doctor-nightly-e2e-guard-runtime.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-runtime.js +93 -0
- package/dist/cli/doctor-nightly-e2e-guard-runtime.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-scan.d.ts +17 -0
- package/dist/cli/doctor-nightly-e2e-guard-scan.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-scan.js +86 -0
- package/dist/cli/doctor-nightly-e2e-guard-scan.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell-lexer.d.ts +38 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell-lexer.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell-lexer.js +160 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell-lexer.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell.d.ts +40 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell.js +201 -0
- package/dist/cli/doctor-nightly-e2e-guard-shell.js.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard.d.ts +36 -0
- package/dist/cli/doctor-nightly-e2e-guard.d.ts.map +1 -0
- package/dist/cli/doctor-nightly-e2e-guard.js +186 -0
- package/dist/cli/doctor-nightly-e2e-guard.js.map +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +7 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +2 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts +25 -0
- package/dist/core/nightly-e2e-guard-behavior-certificate.d.ts.map +1 -0
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +30 -0
- package/dist/core/nightly-e2e-guard-behavior-certificate.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +32 -5
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/migrations/ensure-playwright-dedicated-caller.d.ts +0 -2
- package/dist/migrations/ensure-playwright-dedicated-caller.d.ts.map +1 -1
- package/dist/migrations/ensure-playwright-dedicated-caller.js +12 -40
- package/dist/migrations/ensure-playwright-dedicated-caller.js.map +1 -1
- package/expo/create-only/.github/workflows/maestro-e2e.yml +6 -0
- package/expo/create-only/.github/workflows/playwright-e2e.yml +5 -5
- package/package.json +5 -3
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/scripts/check-derived-artifacts.mjs +32 -5
- package/scripts/generate-nightly-e2e-guard-certificate.mjs +370 -0
- package/scripts/two-channel-couplings.json +16 -4
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file doctor-nightly-e2e-guard-deadline.ts
|
|
3
|
+
* @description One monotonic deadline shared by guard discovery and proof
|
|
4
|
+
* @module cli/doctor-nightly-e2e-guard-deadline
|
|
5
|
+
*/
|
|
6
|
+
import { performance } from "node:perf_hooks";
|
|
7
|
+
import { NIGHTLY_GUARD_OPERATION_TIMEOUT_MS } from "./doctor-nightly-e2e-guard-contract.js";
|
|
8
|
+
/** Explicit error used to convert every deadline exhaustion into one finding. */
|
|
9
|
+
export class NightlyGuardDeadlineError extends Error {
|
|
10
|
+
/** Distinguishes a bounded refusal from arbitrary IO failures. */
|
|
11
|
+
code = "NIGHTLY_GUARD_DEADLINE";
|
|
12
|
+
/**
|
|
13
|
+
* Create the stable operator-facing deadline refusal.
|
|
14
|
+
* @param reason - Budget whose expiration caused the refusal
|
|
15
|
+
*/
|
|
16
|
+
constructor(reason = "15 seconds whole-operation deadline exhausted") {
|
|
17
|
+
super(reason);
|
|
18
|
+
this.name = "NightlyGuardDeadlineError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Start the deadline before discovery so an expensive scan consumes proof time.
|
|
23
|
+
* @param now - Injected monotonic clock
|
|
24
|
+
* @param timeoutMs - Whole-operation budget
|
|
25
|
+
* @param reason - Exact budget named on expiry
|
|
26
|
+
* @returns Shared absolute deadline
|
|
27
|
+
*/
|
|
28
|
+
export function createNightlyGuardDeadline(now = () => performance.now(), timeoutMs = NIGHTLY_GUARD_OPERATION_TIMEOUT_MS, reason = "15 seconds whole-operation deadline exhausted") {
|
|
29
|
+
return { expiresAt: now() + timeoutMs, now, reason };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Return the non-negative time left in the shared budget.
|
|
33
|
+
* @param deadline - Shared absolute deadline
|
|
34
|
+
* @returns Remaining milliseconds, clamped at zero
|
|
35
|
+
*/
|
|
36
|
+
export const nightlyGuardRemaining = (deadline) => Math.max(0, deadline.expiresAt - deadline.now());
|
|
37
|
+
/**
|
|
38
|
+
* Describe the exact target ceiling without hard-coding the default budget.
|
|
39
|
+
* @param timeoutMs - Target-specific ceiling in milliseconds
|
|
40
|
+
* @returns Stable operator-facing deadline reason
|
|
41
|
+
*/
|
|
42
|
+
export function nightlyGuardTargetDeadlineReason(timeoutMs) {
|
|
43
|
+
const seconds = timeoutMs / 1000;
|
|
44
|
+
const duration = Number.isInteger(seconds)
|
|
45
|
+
? `${seconds} ${seconds === 1 ? "second" : "seconds"}`
|
|
46
|
+
: `${timeoutMs} milliseconds`;
|
|
47
|
+
return `${duration} target proof deadline exhausted`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Refuse work immediately once the shared deadline has elapsed.
|
|
51
|
+
* @param deadline - Shared absolute deadline
|
|
52
|
+
*/
|
|
53
|
+
export function assertNightlyGuardDeadline(deadline) {
|
|
54
|
+
if (nightlyGuardRemaining(deadline) <= 0) {
|
|
55
|
+
throw new NightlyGuardDeadlineError(deadline.reason);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Enforce the remaining wall-clock budget even when an injected collaborator
|
|
60
|
+
* never resolves. The abandoned operation is read-only and cannot alter the
|
|
61
|
+
* inspected project after the refusal is returned.
|
|
62
|
+
* @param deadline - Shared operation deadline
|
|
63
|
+
* @param operation - Lazy read-only asynchronous work
|
|
64
|
+
* @returns The operation result before expiry
|
|
65
|
+
*/
|
|
66
|
+
export async function withinNightlyGuardDeadline(deadline, operation) {
|
|
67
|
+
const remaining = nightlyGuardRemaining(deadline);
|
|
68
|
+
if (remaining <= 0)
|
|
69
|
+
throw new NightlyGuardDeadlineError(deadline.reason);
|
|
70
|
+
return await new Promise((resolve, reject) => {
|
|
71
|
+
const timer = setTimeout(() => reject(new NightlyGuardDeadlineError(deadline.reason)), remaining);
|
|
72
|
+
operation().then(value => {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
resolve(value);
|
|
75
|
+
}, error => {
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
reject(error);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Give one target a smaller ceiling without extending the outer deadline.
|
|
83
|
+
* @param outer - Whole-operation deadline
|
|
84
|
+
* @param timeoutMs - Target-specific ceiling
|
|
85
|
+
* @returns Deadline ending at the earlier ceiling
|
|
86
|
+
*/
|
|
87
|
+
export function limitNightlyGuardDeadline(outer, timeoutMs) {
|
|
88
|
+
const targetExpiresAt = outer.now() + timeoutMs;
|
|
89
|
+
return {
|
|
90
|
+
expiresAt: Math.min(outer.expiresAt, targetExpiresAt),
|
|
91
|
+
now: outer.now,
|
|
92
|
+
reason: targetExpiresAt < outer.expiresAt
|
|
93
|
+
? nightlyGuardTargetDeadlineReason(timeoutMs)
|
|
94
|
+
: outer.reason,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-deadline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-deadline.js","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-deadline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file doctor-nightly-e2e-guard-evidence.ts
|
|
3
|
+
* @description Preclassification evidence pass for one reachable workflow job
|
|
4
|
+
* @module cli/doctor-nightly-e2e-guard-evidence
|
|
5
|
+
*/
|
|
6
|
+
import { type NightlyGuardWorkflowRecord } from "./doctor-nightly-e2e-guard-contract.js";
|
|
7
|
+
import { type NightlyGuardRunInspection } from "./doctor-nightly-e2e-guard-shell.js";
|
|
8
|
+
/** Evidence gathered before deciding which supported job grammar applies. */
|
|
9
|
+
export interface NightlyGuardJobEvidence {
|
|
10
|
+
/** YAML-decoded steps retained for per-step environment attribution. */
|
|
11
|
+
readonly steps: readonly Readonly<Record<string, unknown>>[];
|
|
12
|
+
/** Comment-stripped POSIX run interpretations for those steps. */
|
|
13
|
+
readonly analyses: readonly NightlyGuardRunInspection[];
|
|
14
|
+
/** Workflow/job environment carries recognized bypass semantics. */
|
|
15
|
+
readonly inheritedEnvironment: boolean;
|
|
16
|
+
/** At least one step environment carries recognized bypass semantics. */
|
|
17
|
+
readonly stepEnvironment: boolean;
|
|
18
|
+
/** Job or step condition carries recognized bypass semantics. */
|
|
19
|
+
readonly condition: boolean;
|
|
20
|
+
/** Reusable input mapping carries recognized bypass semantics. */
|
|
21
|
+
readonly withMapping: boolean;
|
|
22
|
+
/** Comment-stripped run tokens construct recognized bypass state. */
|
|
23
|
+
readonly run: boolean;
|
|
24
|
+
/** At least one supported or refused run contains a Node command. */
|
|
25
|
+
readonly hasNode: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Recognize only operational bypass keys or values with nightly-E2E semantics.
|
|
29
|
+
* @param levels - YAML mappings at increasing precedence
|
|
30
|
+
* @returns Whether a mapping participates in this guard's bypass contract
|
|
31
|
+
*/
|
|
32
|
+
export declare const bypassBearingMapping: (...levels: readonly unknown[]) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Conditions are executable evidence only when their value has guard semantics.
|
|
35
|
+
* @param value - Parsed job/step `if` value
|
|
36
|
+
* @returns Whether the condition can participate in nightly bypass behavior
|
|
37
|
+
*/
|
|
38
|
+
export declare const conditionalBypass: (value: unknown) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Inspect all executable fields before official/local/direct classification.
|
|
41
|
+
* @param workflow - Parsed owner of the job and workflow defaults
|
|
42
|
+
* @param job - Parsed job mapping with runner and step metadata
|
|
43
|
+
* @returns Evidence shared by every classification branch
|
|
44
|
+
*/
|
|
45
|
+
export declare const inspectNightlyGuardJobEvidence: (workflow: NightlyGuardWorkflowRecord, job: Readonly<Record<string, unknown>>) => NightlyGuardJobEvidence;
|
|
46
|
+
/**
|
|
47
|
+
* Collapse evidence only after every executable field has been inspected.
|
|
48
|
+
* @param evidence - Complete preclassification evidence record
|
|
49
|
+
* @returns Whether any field places the job in the nightly bypass contract
|
|
50
|
+
*/
|
|
51
|
+
export declare const hasAnyNightlyGuardBypassEvidence: (evidence: NightlyGuardJobEvidence) => boolean;
|
|
52
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-evidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-evidence.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-evidence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,KAAK,0BAA0B,EAGhC,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAIL,KAAK,yBAAyB,EAC/B,MAAM,qCAAqC,CAAC;AAE7C,6EAA6E;AAC7E,MAAM,WAAW,uBAAuB;IACtC,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC;IAC7D,kEAAkE;IAClE,QAAQ,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAC;IACxD,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAmBD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAI,GAAG,QAAQ,SAAS,OAAO,EAAE,KAAG,OAOlE,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAO,OAAO,KAAG,OACY,CAAC;AAYhE;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,GACzC,UAAU,0BAA0B,EACpC,KAAK,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,KACrC,uBAmCF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,GAC3C,UAAU,uBAAuB,KAChC,OAKW,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file doctor-nightly-e2e-guard-evidence.ts
|
|
3
|
+
* @description Preclassification evidence pass for one reachable workflow job
|
|
4
|
+
* @module cli/doctor-nightly-e2e-guard-evidence
|
|
5
|
+
*/
|
|
6
|
+
import { nightlyGuardObject, nightlyGuardText, } from "./doctor-nightly-e2e-guard-contract.js";
|
|
7
|
+
import { hasNightlyBypassReference, inspectNightlyGuardRun, isNightlyBypassEnvironmentName, } from "./doctor-nightly-e2e-guard-shell.js";
|
|
8
|
+
const mergedEnvironment = (...levels) => Object.assign({}, ...levels.map(level => nightlyGuardObject(level) ?? {}));
|
|
9
|
+
const literalEnvironment = (environment) => Object.fromEntries(Object.entries(environment).filter((entry) => typeof entry[1] === "string"));
|
|
10
|
+
const bypassKey = (key) => isNightlyBypassEnvironmentName(key) || hasNightlyBypassReference(key);
|
|
11
|
+
/**
|
|
12
|
+
* Recognize only operational bypass keys or values with nightly-E2E semantics.
|
|
13
|
+
* @param levels - YAML mappings at increasing precedence
|
|
14
|
+
* @returns Whether a mapping participates in this guard's bypass contract
|
|
15
|
+
*/
|
|
16
|
+
export const bypassBearingMapping = (...levels) => levels.some(level => Object.entries(nightlyGuardObject(level) ?? {}).some(([key, value]) => bypassKey(key) ||
|
|
17
|
+
(typeof value === "string" && hasNightlyBypassReference(value))));
|
|
18
|
+
/**
|
|
19
|
+
* Conditions are executable evidence only when their value has guard semantics.
|
|
20
|
+
* @param value - Parsed job/step `if` value
|
|
21
|
+
* @returns Whether the condition can participate in nightly bypass behavior
|
|
22
|
+
*/
|
|
23
|
+
export const conditionalBypass = (value) => typeof value === "string" && hasNightlyBypassReference(value);
|
|
24
|
+
const workflowShell = (workflow) => nightlyGuardObject(nightlyGuardObject(workflow.document.defaults)?.run)
|
|
25
|
+
?.shell;
|
|
26
|
+
const jobShell = (job) => nightlyGuardObject(nightlyGuardObject(job.defaults)?.run)?.shell;
|
|
27
|
+
const firstDefined = (...values) => values.find(value => value !== undefined);
|
|
28
|
+
/**
|
|
29
|
+
* Inspect all executable fields before official/local/direct classification.
|
|
30
|
+
* @param workflow - Parsed owner of the job and workflow defaults
|
|
31
|
+
* @param job - Parsed job mapping with runner and step metadata
|
|
32
|
+
* @returns Evidence shared by every classification branch
|
|
33
|
+
*/
|
|
34
|
+
export const inspectNightlyGuardJobEvidence = (workflow, job) => {
|
|
35
|
+
const rawSteps = Array.isArray(job.steps) ? job.steps : [];
|
|
36
|
+
const steps = rawSteps.map(step => nightlyGuardObject(step) ?? {});
|
|
37
|
+
const inheritedEnvironment = bypassBearingMapping(workflow.document.env, job.env);
|
|
38
|
+
const analyses = steps.map(step => {
|
|
39
|
+
const environment = mergedEnvironment(workflow.document.env, job.env, step.env);
|
|
40
|
+
return inspectNightlyGuardRun(nightlyGuardText(step.run), literalEnvironment(environment), {
|
|
41
|
+
shell: firstDefined(step.shell, jobShell(job), workflowShell(workflow)),
|
|
42
|
+
runsOn: job["runs-on"],
|
|
43
|
+
environment,
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
return {
|
|
47
|
+
steps,
|
|
48
|
+
analyses,
|
|
49
|
+
inheritedEnvironment,
|
|
50
|
+
stepEnvironment: steps.some(step => bypassBearingMapping(step.env)),
|
|
51
|
+
condition: conditionalBypass(job.if) ||
|
|
52
|
+
steps.some(step => conditionalBypass(step.if)),
|
|
53
|
+
withMapping: bypassBearingMapping(job.with),
|
|
54
|
+
run: analyses.some(analysis => analysis.bypassEvidence),
|
|
55
|
+
hasNode: analyses.some(analysis => analysis.containsNode),
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Collapse evidence only after every executable field has been inspected.
|
|
60
|
+
* @param evidence - Complete preclassification evidence record
|
|
61
|
+
* @returns Whether any field places the job in the nightly bypass contract
|
|
62
|
+
*/
|
|
63
|
+
export const hasAnyNightlyGuardBypassEvidence = (evidence) => evidence.inheritedEnvironment ||
|
|
64
|
+
evidence.stepEnvironment ||
|
|
65
|
+
evidence.condition ||
|
|
66
|
+
evidence.withMapping ||
|
|
67
|
+
evidence.run;
|
|
68
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-evidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-evidence.js","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-evidence.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAEL,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,yBAAyB,EACzB,sBAAsB,EACtB,8BAA8B,GAE/B,MAAM,qCAAqC,CAAC;AAsB7C,MAAM,iBAAiB,GAAG,CACxB,GAAG,MAA0B,EACM,EAAE,CACrC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAE7E,MAAM,kBAAkB,GAAG,CACzB,WAA8C,EACZ,EAAE,CACpC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAChC,CAAC,KAAK,EAA6B,EAAE,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,QAAQ,CACnE,CACF,CAAC;AAEJ,MAAM,SAAS,GAAG,CAAC,GAAW,EAAW,EAAE,CACzC,8BAA8B,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC,GAAG,CAAC,CAAC;AAExE;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,GAAG,MAA0B,EAAW,EAAE,CAC7E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAClB,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAClD,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CACf,SAAS,CAAC,GAAG,CAAC;IACd,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAC,CAClE,CACF,CAAC;AAEJ;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAc,EAAW,EAAE,CAC3D,OAAO,KAAK,KAAK,QAAQ,IAAI,yBAAyB,CAAC,KAAK,CAAC,CAAC;AAEhE,MAAM,aAAa,GAAG,CAAC,QAAoC,EAAW,EAAE,CACtE,kBAAkB,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC;IACrE,EAAE,KAAK,CAAC;AAEZ,MAAM,QAAQ,GAAG,CAAC,GAAsC,EAAW,EAAE,CACnE,kBAAkB,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC;AAEnE,MAAM,YAAY,GAAG,CAAC,GAAG,MAA0B,EAAW,EAAE,CAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAC5C,QAAoC,EACpC,GAAsC,EACb,EAAE;IAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,oBAAoB,GAAG,oBAAoB,CAC/C,QAAQ,CAAC,QAAQ,CAAC,GAAG,EACrB,GAAG,CAAC,GAAG,CACR,CAAC;IACF,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;QAChC,MAAM,WAAW,GAAG,iBAAiB,CACnC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EACrB,GAAG,CAAC,GAAG,EACP,IAAI,CAAC,GAAG,CACT,CAAC;QACF,OAAO,sBAAsB,CAC3B,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAC1B,kBAAkB,CAAC,WAAW,CAAC,EAC/B;YACE,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;YACvE,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC;YACtB,WAAW;SACZ,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO;QACL,KAAK;QACL,QAAQ;QACR,oBAAoB;QACpB,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnE,SAAS,EACP,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,WAAW,EAAE,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC;QAC3C,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;QACvD,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;KAC1D,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAC9C,QAAiC,EACxB,EAAE,CACX,QAAQ,CAAC,oBAAoB;IAC7B,QAAQ,CAAC,eAAe;IACxB,QAAQ,CAAC,SAAS;IAClB,QAAQ,CAAC,WAAW;IACpB,QAAQ,CAAC,GAAG,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file doctor-nightly-e2e-guard-graph.ts
|
|
3
|
+
* @description Root-preserving traversal of reachable local reusable workflows
|
|
4
|
+
* @module cli/doctor-nightly-e2e-guard-graph
|
|
5
|
+
*/
|
|
6
|
+
import { type NightlyGuardScanResult, type NightlyGuardWorkflowRecord } from "./doctor-nightly-e2e-guard-contract.js";
|
|
7
|
+
/**
|
|
8
|
+
* Traverse each root independently so shared reusables retain every active
|
|
9
|
+
* root-to-job attribution while static target proof remains deduplicated.
|
|
10
|
+
* @param records - Parsed bounded workflow inventory
|
|
11
|
+
* @returns Deterministic active callers or the first graph refusal
|
|
12
|
+
*/
|
|
13
|
+
export declare function traceNightlyGuardCallers(records: readonly NightlyGuardWorkflowRecord[]): NightlyGuardScanResult;
|
|
14
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-graph.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-graph.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EASL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAKhC,MAAM,wCAAwC,CAAC;AA2KhD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,SAAS,0BAA0B,EAAE,GAC7C,sBAAsB,CA2BxB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file doctor-nightly-e2e-guard-graph.ts
|
|
3
|
+
* @description Root-preserving traversal of reachable local reusable workflows
|
|
4
|
+
* @module cli/doctor-nightly-e2e-guard-graph
|
|
5
|
+
*/
|
|
6
|
+
import { MAX_NIGHTLY_GUARD_ATTRIBUTION_BYTES, MAX_NIGHTLY_GUARD_CALLERS, MAX_NIGHTLY_GUARD_JOB_ID_BYTES, MAX_NIGHTLY_GUARD_LOCAL_DEPTH, MAX_NIGHTLY_GUARD_TARGETS, NIGHTLY_GUARD_WORKFLOWS, isNightlyGuardJobId, nightlyGuardCallerAttributionBytes, nightlyGuardObject, orderNightlyGuardStrings, } from "./doctor-nightly-e2e-guard-contract.js";
|
|
7
|
+
import { inspectNightlyGuardJob } from "./doctor-nightly-e2e-guard-job.js";
|
|
8
|
+
const failure = (workflow, reason) => ({ failure: { workflow: workflow.file, reason } });
|
|
9
|
+
const isFailure = (result) => "failure" in result;
|
|
10
|
+
const triggerNames = (value) => {
|
|
11
|
+
if (typeof value === "string")
|
|
12
|
+
return [value];
|
|
13
|
+
if (Array.isArray(value)) {
|
|
14
|
+
return value.filter(item => typeof item === "string");
|
|
15
|
+
}
|
|
16
|
+
return Object.keys(nightlyGuardObject(value) ?? {});
|
|
17
|
+
};
|
|
18
|
+
const isRoot = (record) => triggerNames(record.document.on).some(event => event !== "workflow_call");
|
|
19
|
+
const pathPart = (workflow, jobId) => `${workflow.file}#${jobId}`;
|
|
20
|
+
const validateBounds = (workflow, callers) => {
|
|
21
|
+
if (callers.length > MAX_NIGHTLY_GUARD_CALLERS) {
|
|
22
|
+
return failure(workflow, `bypass caller limit ${MAX_NIGHTLY_GUARD_CALLERS} exceeded`);
|
|
23
|
+
}
|
|
24
|
+
const targets = new Set(callers.map(caller => caller.target));
|
|
25
|
+
if (targets.size > MAX_NIGHTLY_GUARD_TARGETS) {
|
|
26
|
+
return failure(workflow, `guard target limit ${MAX_NIGHTLY_GUARD_TARGETS} exceeded`);
|
|
27
|
+
}
|
|
28
|
+
const attributionBytes = callers.reduce((total, caller) => total + nightlyGuardCallerAttributionBytes(caller), 0);
|
|
29
|
+
return attributionBytes > MAX_NIGHTLY_GUARD_ATTRIBUTION_BYTES
|
|
30
|
+
? {
|
|
31
|
+
failure: {
|
|
32
|
+
workflow: NIGHTLY_GUARD_WORKFLOWS,
|
|
33
|
+
reason: `caller attribution exceeds the ${MAX_NIGHTLY_GUARD_ATTRIBUTION_BYTES}-byte limit`,
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
: { callers };
|
|
37
|
+
};
|
|
38
|
+
const callerFor = (workflow, jobId, context, caller) => ({
|
|
39
|
+
workflow: workflow.file,
|
|
40
|
+
job: jobId,
|
|
41
|
+
callPath: [...context.parents, pathPart(workflow, jobId)].join(" -> "),
|
|
42
|
+
kind: caller.kind,
|
|
43
|
+
target: caller.target,
|
|
44
|
+
});
|
|
45
|
+
const childContext = (workflow, jobId, context) => ({
|
|
46
|
+
depth: context.depth + 1,
|
|
47
|
+
stack: [...context.stack, workflow.name],
|
|
48
|
+
parents: [...context.parents, pathPart(workflow, jobId)],
|
|
49
|
+
});
|
|
50
|
+
/**
|
|
51
|
+
* Traverse one workflow and every local edge below it.
|
|
52
|
+
* @param workflow - Current parsed workflow
|
|
53
|
+
* @param byName - Bounded inventory keyed by basename
|
|
54
|
+
* @param context - Root-path recursion state
|
|
55
|
+
* @returns Callers below this workflow or an explicit graph refusal
|
|
56
|
+
*/
|
|
57
|
+
const walkWorkflow = (workflow, byName, context) => {
|
|
58
|
+
if (context.stack.includes(workflow.name)) {
|
|
59
|
+
return failure(workflow, `reachable local workflow cycle: ${[...context.stack, workflow.name].join(" -> ")}`);
|
|
60
|
+
}
|
|
61
|
+
const jobs = nightlyGuardObject(workflow.document.jobs) ?? {};
|
|
62
|
+
const jobIds = orderNightlyGuardStrings(Object.keys(jobs));
|
|
63
|
+
const walkJobs = (index, accumulated) => {
|
|
64
|
+
const jobId = jobIds[index];
|
|
65
|
+
if (jobId === undefined)
|
|
66
|
+
return validateBounds(workflow, accumulated);
|
|
67
|
+
if (!isNightlyGuardJobId(jobId)) {
|
|
68
|
+
return failure(workflow, `job identifier exceeds the ${MAX_NIGHTLY_GUARD_JOB_ID_BYTES}-byte GitHub identifier limit or uses unsupported characters`);
|
|
69
|
+
}
|
|
70
|
+
const job = nightlyGuardObject(jobs[jobId]);
|
|
71
|
+
if (!job)
|
|
72
|
+
return walkJobs(index + 1, accumulated);
|
|
73
|
+
const inspection = inspectNightlyGuardJob(workflow, jobId, job);
|
|
74
|
+
if (inspection.failure)
|
|
75
|
+
return { failure: inspection.failure };
|
|
76
|
+
const own = inspection.caller
|
|
77
|
+
? [callerFor(workflow, jobId, context, inspection.caller)]
|
|
78
|
+
: [];
|
|
79
|
+
if (!inspection.local)
|
|
80
|
+
return walkJobs(index + 1, [...accumulated, ...own]);
|
|
81
|
+
const child = byName.get(inspection.local);
|
|
82
|
+
if (!child) {
|
|
83
|
+
return failure(workflow, `${jobId}: local reusable ${inspection.local} is missing or unresolved`);
|
|
84
|
+
}
|
|
85
|
+
if (context.depth >= MAX_NIGHTLY_GUARD_LOCAL_DEPTH) {
|
|
86
|
+
return failure(workflow, `reachable local workflow depth exceeds ${MAX_NIGHTLY_GUARD_LOCAL_DEPTH}`);
|
|
87
|
+
}
|
|
88
|
+
const nested = walkWorkflow(child, byName, childContext(workflow, jobId, context));
|
|
89
|
+
return isFailure(nested)
|
|
90
|
+
? nested
|
|
91
|
+
: walkJobs(index + 1, [...accumulated, ...own, ...nested.callers]);
|
|
92
|
+
};
|
|
93
|
+
return walkJobs(0, []);
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Traverse each root independently so shared reusables retain every active
|
|
97
|
+
* root-to-job attribution while static target proof remains deduplicated.
|
|
98
|
+
* @param records - Parsed bounded workflow inventory
|
|
99
|
+
* @returns Deterministic active callers or the first graph refusal
|
|
100
|
+
*/
|
|
101
|
+
export function traceNightlyGuardCallers(records) {
|
|
102
|
+
const byName = new Map(records.map(record => [record.name, record]));
|
|
103
|
+
const roots = records.filter(isRoot);
|
|
104
|
+
const walkRoots = (index, accumulated) => {
|
|
105
|
+
const root = roots[index];
|
|
106
|
+
if (root === undefined)
|
|
107
|
+
return validateBounds(records[0] ?? emptyRecord, accumulated);
|
|
108
|
+
const result = walkWorkflow(root, byName, {
|
|
109
|
+
depth: 0,
|
|
110
|
+
stack: [],
|
|
111
|
+
parents: [],
|
|
112
|
+
});
|
|
113
|
+
return isFailure(result)
|
|
114
|
+
? result
|
|
115
|
+
: walkRoots(index + 1, [...accumulated, ...result.callers]);
|
|
116
|
+
};
|
|
117
|
+
const result = walkRoots(0, []);
|
|
118
|
+
if (isFailure(result)) {
|
|
119
|
+
return { state: "unavailable", failures: [result.failure] };
|
|
120
|
+
}
|
|
121
|
+
const callers = [...result.callers].sort((left, right) => left.callPath < right.callPath ? -1 : left.callPath > right.callPath ? 1 : 0);
|
|
122
|
+
return { state: "ok", callers };
|
|
123
|
+
}
|
|
124
|
+
/** Synthetic owner for bounds when an inventory contains no records. */
|
|
125
|
+
const emptyRecord = {
|
|
126
|
+
file: ".github/workflows",
|
|
127
|
+
name: "",
|
|
128
|
+
document: {},
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-graph.js","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type NightlyGuardDeadline } from "./doctor-nightly-e2e-guard-deadline.js";
|
|
2
|
+
/** Successful bytes or the precise availability class of a safe read. */
|
|
3
|
+
export type NightlyGuardReadResult = {
|
|
4
|
+
readonly state: "ok";
|
|
5
|
+
readonly bytes: Buffer;
|
|
6
|
+
} | {
|
|
7
|
+
readonly state: "missing";
|
|
8
|
+
readonly reason: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly state: "unavailable";
|
|
11
|
+
readonly reason: string;
|
|
12
|
+
};
|
|
13
|
+
/** Deterministic directory entries or an explicit availability refusal. */
|
|
14
|
+
export type NightlyGuardDirectoryResult = {
|
|
15
|
+
readonly state: "ok";
|
|
16
|
+
readonly names: readonly string[];
|
|
17
|
+
} | {
|
|
18
|
+
readonly state: "missing";
|
|
19
|
+
readonly reason: string;
|
|
20
|
+
} | {
|
|
21
|
+
readonly state: "unavailable";
|
|
22
|
+
readonly reason: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Read one regular file without following any path component.
|
|
26
|
+
* @param projectRoot - Containment root
|
|
27
|
+
* @param relativePath - Project-relative path
|
|
28
|
+
* @param maxBytes - Hard byte ceiling
|
|
29
|
+
* @param deadline - Shared deadline
|
|
30
|
+
* @returns Bounded bytes or a precise availability class
|
|
31
|
+
*/
|
|
32
|
+
export declare function readNightlyGuardFile(projectRoot: string, relativePath: string, maxBytes: number, deadline: NightlyGuardDeadline): Promise<NightlyGuardReadResult>;
|
|
33
|
+
/**
|
|
34
|
+
* List a directory only when every component and its identity remain safe.
|
|
35
|
+
* @param projectRoot - Containment root
|
|
36
|
+
* @param relativePath - Project-relative directory
|
|
37
|
+
* @param deadline - Shared deadline
|
|
38
|
+
* @returns Directory entries or an availability refusal
|
|
39
|
+
*/
|
|
40
|
+
export declare function readNightlyGuardDirectory(projectRoot: string, relativePath: string, deadline: NightlyGuardDeadline): Promise<NightlyGuardDirectoryResult>;
|
|
41
|
+
//# sourceMappingURL=doctor-nightly-e2e-guard-io.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor-nightly-e2e-guard-io.d.ts","sourceRoot":"","sources":["../../src/cli/doctor-nightly-e2e-guard-io.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,KAAK,oBAAoB,EAE1B,MAAM,wCAAwC,CAAC;AAEhD,yEAAyE;AACzE,MAAM,MAAM,sBAAsB,GAC9B;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE/D,2EAA2E;AAC3E,MAAM,MAAM,2BAA2B,GACnC;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAwM/D;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,sBAAsB,CAAC,CA6DjC;AAED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,oBAAoB,GAC7B,OAAO,CAAC,2BAA2B,CAAC,CA+BtC"}
|