mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-07 09:23:50 +01:00
fix(cso): count remainingSeconds to the investigation deadline; bound and validate the tool timeline
remainingSeconds now measures to deadline - 60s, the point where scan, verify and record-review refuse with DEADLINE, and inspect carries it. The post-command clock lookup can only omit the field, never fail a command whose state change is already saved. The stream timeline records end times from tool_result, indexes only recorded calls so it stays at the 4096 cap, and receipts reject malformed timeline entries.
This commit is contained in:
1 parent
6a432f00a0
commit
d804fbb2fc
11 files changed
+90
-34
No files matched your search
+29
-17
@@ -57,6 +57,7 @@ import {
|
||||
readJson,
|
||||
reclaimDeadAttemptScratch,
|
||||
repoId,
|
||||
executionDeadline,
|
||||
requireTime,
|
||||
retention,
|
||||
runDirectory,
|
||||
@@ -1609,6 +1610,7 @@ async function inspect(args: string[]) {
|
||||
? readJson(join(dir, 'preparation.json'))
|
||||
: undefined,
|
||||
recovery: recoveryEvents(dir),
|
||||
remainingSeconds: remainingSeconds(report.deadline),
|
||||
});
|
||||
}
|
||||
async function read(args: string[]) {
|
||||
@@ -2796,6 +2798,24 @@ async function replay(args: string[], dependencies: CsoCliDependencies) {
|
||||
});
|
||||
}
|
||||
|
||||
/** In-run replies that report the investigation time left; every one but `start` takes the run ID first. */
|
||||
const RUN_CLOCK_COMMANDS = new Set([
|
||||
'start',
|
||||
'resume',
|
||||
'submit',
|
||||
'scan',
|
||||
'scanner-outcome',
|
||||
'import-sarif',
|
||||
'record-review',
|
||||
'test-plan',
|
||||
'runtime-plan',
|
||||
'verify',
|
||||
]);
|
||||
/** Whole seconds until the investigation deadline (the final reporting minute excluded), or undefined if unknown. */
|
||||
function remainingSeconds(deadline: string): number | undefined {
|
||||
const ends = executionDeadline({ deadline });
|
||||
return Number.isFinite(ends) ? Math.max(0, Math.floor((ends - Date.now()) / 1000)) : undefined;
|
||||
}
|
||||
export async function dispatchCsoCommand(
|
||||
command: string,
|
||||
args: string[],
|
||||
@@ -2877,27 +2897,19 @@ export async function dispatchCsoCommand(
|
||||
default:
|
||||
throw new CsoError('INVALID_ARGUMENT', `Unknown command: ${command}`);
|
||||
}
|
||||
if (RUN_CLOCK_COMMANDS.has(command) && result && typeof result === 'object' && !Array.isArray(result)) {
|
||||
const deadline = (result as { deadline?: unknown }).deadline;
|
||||
const ends = Date.parse(
|
||||
if (!RUN_CLOCK_COMMANDS.has(command) || !result || typeof result !== 'object' || Array.isArray(result))
|
||||
return result;
|
||||
const deadline = (result as { deadline?: unknown }).deadline;
|
||||
let seconds: number | undefined;
|
||||
try {
|
||||
seconds = remainingSeconds(
|
||||
typeof deadline === 'string' ? deadline : loadReport(runDirectory(runId)).deadline,
|
||||
);
|
||||
result = { ...result, remainingSeconds: Math.max(0, Math.floor((ends - Date.now()) / 1000)) };
|
||||
} catch {
|
||||
seconds = undefined;
|
||||
}
|
||||
return result;
|
||||
return seconds === undefined ? result : { ...result, remainingSeconds: seconds };
|
||||
}
|
||||
const RUN_CLOCK_COMMANDS = new Set([
|
||||
'start',
|
||||
'resume',
|
||||
'submit',
|
||||
'scan',
|
||||
'scanner-outcome',
|
||||
'import-sarif',
|
||||
'record-review',
|
||||
'test-plan',
|
||||
'runtime-plan',
|
||||
'verify',
|
||||
]);
|
||||
const PRODUCTION_CLI_DEPENDENCIES: CsoCliDependencies = Object.freeze({
|
||||
runtimeCatalog: RUNTIME_CATALOG,
|
||||
scannerCatalog: SCANNER_CATALOG,
|
||||
|
||||
+1
-1
@@ -944,7 +944,7 @@ export function loadReport(dir: string): RunReportV3 {
|
||||
export function event(report: RunReportV3, kind: string, message: string): void {
|
||||
report.events.push({ at: new Date().toISOString(), kind, message: redact(message) });
|
||||
}
|
||||
export function executionDeadline(report: RunReportV3): number {
|
||||
export function executionDeadline(report: Pick<RunReportV3, 'deadline'>): number {
|
||||
return Date.parse(report.deadline) - 60_000;
|
||||
}
|
||||
export function requireTime(report: RunReportV3): void {
|
||||
|
||||
Reference in new issue
Block a user