feat(ql3): establish 3.0 incubation baseline

This commit is contained in:
whyour
2026-08-12 00:25:26 +08:00
parent 4bf92dcfeb
commit c699c32461
2817 changed files with 779642 additions and 653 deletions
@@ -0,0 +1,66 @@
import path from 'path';
import type { ExecutionOutputSink } from '../../domain/execution';
import { assertLocalExecutionArtifactId } from '../../domain/localExecutionArtifact';
const DURABLE_LOCAL_PROCESS_OUTPUT = Symbol('durable-local-process-output');
export interface DurableLocalProcessOutput {
outputFilePath: string;
completionReceiptRoot: string;
maximumBytes?: number;
logArtifactId?: string;
}
type CapableExecutionOutputSink = ExecutionOutputSink & {
[DURABLE_LOCAL_PROCESS_OUTPUT]?: DurableLocalProcessOutput;
};
function assertAbsolutePath(value: string, name: string): void {
if (!path.isAbsolute(value) || value.includes('\0')) {
throw new RangeError(`${name} must be an absolute path containing no NUL`);
}
}
/**
* Adds an adapter-local launch capability without widening ExecutionContext.
* The symbol is deliberately non-enumerable so paths cannot leak through
* routine context serialization or diagnostic logging.
*/
export function enableDurableLocalProcessOutput<T extends ExecutionOutputSink>(
output: T,
capability: DurableLocalProcessOutput,
): T {
assertAbsolutePath(capability.outputFilePath, 'outputFilePath');
assertAbsolutePath(capability.completionReceiptRoot, 'completionReceiptRoot');
if (
capability.maximumBytes !== undefined &&
(!Number.isSafeInteger(capability.maximumBytes) ||
capability.maximumBytes < 1)
) {
throw new RangeError('maximumBytes must be a positive safe integer');
}
if (
(capability.maximumBytes === undefined) !==
(capability.logArtifactId === undefined)
) {
throw new RangeError(
'maximumBytes and logArtifactId must be provided together',
);
}
if (capability.logArtifactId !== undefined) {
assertLocalExecutionArtifactId(capability.logArtifactId);
}
Object.defineProperty(output, DURABLE_LOCAL_PROCESS_OUTPUT, {
configurable: false,
enumerable: false,
writable: false,
value: Object.freeze({ ...capability }),
});
return output;
}
export function durableLocalProcessOutput(
output: ExecutionOutputSink,
): DurableLocalProcessOutput | undefined {
return (output as CapableExecutionOutputSink)[DURABLE_LOCAL_PROCESS_OUTPUT];
}