fix: clarify pr preflight auth scopes
Host commander merge: clean commander-efficiency PR; clarifies scheduler-runner auth scope and bounded preflight actions for #20/#75.
This commit is contained in:
+118
-10
@@ -2968,25 +2968,74 @@ function activeRunnerDevContainerCapability(): Record<string, unknown> {
|
||||
function prPreflightScopeBoundary(tokenCoverage: Record<string, unknown> | null): Record<string, unknown> {
|
||||
const schedulerScope = typeof tokenCoverage?.scope === "string" ? tokenCoverage.scope : "scheduler-runner-env";
|
||||
return {
|
||||
headline: "scheduler-runner-env auth-missing is not active runner/dev container PR incapability",
|
||||
schedulerPreflightScope: schedulerScope,
|
||||
activeRunnerDevContainerScope: "current-cli-process",
|
||||
scopesAreIndependent: true,
|
||||
schedulerAuthMissingDoesNotMeanActiveRunnerCannotCreatePr: true,
|
||||
authMissingInterpretation: "auth-missing from codex pr-preflight --remote is scoped to the scheduler/runtime preflight surface; do not simplify it to 'the active runner cannot create PRs'",
|
||||
currentRunnerCheck: "use activeRunnerDevContainer plus bun scripts/cli.ts gh auth status --repo pikasTech/unidesk for the current dev container",
|
||||
currentRunnerCheck: "use activeRunnerDevContainer plus bun scripts/cli.ts gh auth status --repo pikasTech/unidesk and gh pr create --dry-run for the current dev container",
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightRecommendedActions(tokenCoverage: Record<string, unknown> | null): Record<string, unknown>[] {
|
||||
const schedulerReady = tokenCoverage?.ok === true;
|
||||
return [
|
||||
{
|
||||
scope: "active-runner-dev-container",
|
||||
priority: "first",
|
||||
action: "verify-current-runner-auth",
|
||||
command: "bun scripts/cli.ts gh auth status --repo pikasTech/unidesk",
|
||||
writesRemote: false,
|
||||
},
|
||||
{
|
||||
scope: "active-runner-dev-container",
|
||||
priority: "first",
|
||||
action: "verify-current-runner-pr-create-plan",
|
||||
command: "bun scripts/cli.ts gh pr create --repo pikasTech/unidesk --title <title> --body-file <file> --base master --head <head> --dry-run",
|
||||
writesRemote: false,
|
||||
},
|
||||
{
|
||||
scope: "scheduler-runtime",
|
||||
priority: schedulerReady ? "long-term" : "required-for-scheduler-preflight",
|
||||
action: "configure-scheduler-auth-source",
|
||||
command: "configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN via the scheduler runtime secret",
|
||||
writesRemote: false,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function prPreflightAuthScopeSummary(tokenCoverage: Record<string, unknown> | null, activeRunnerDevContainer: Record<string, unknown>): Record<string, unknown> {
|
||||
const schedulerReady = tokenCoverage?.ok === true;
|
||||
return {
|
||||
schedulerPreflightScope: typeof tokenCoverage?.scope === "string" ? tokenCoverage.scope : "scheduler-runner-env",
|
||||
schedulerAuthReady: schedulerReady,
|
||||
schedulerAuthSource: tokenCoverage?.source ?? null,
|
||||
schedulerAuthMissingIsScoped: !schedulerReady,
|
||||
activeRunnerDevContainerScope: activeRunnerDevContainer.scope ?? "current-cli-process",
|
||||
activeRunnerTokenCandidatePresent: activeRunnerDevContainer.ok === true,
|
||||
interpretation: schedulerReady
|
||||
? "scheduler preflight has GitHub auth coverage; active runner PR creation still needs repo-native dry-run verification before real writes"
|
||||
: "scheduler-runner-env auth-missing does not prove the active runner/dev container lacks PR create/comment capability",
|
||||
valuesPrinted: false,
|
||||
};
|
||||
}
|
||||
|
||||
function decoratePrPreflightScopeBoundary(record: Record<string, unknown>): Record<string, unknown> {
|
||||
const preflight = asRecord(record.preflight);
|
||||
const tokenCoverage = asRecord(preflight?.tokenCoverage ?? record.tokenCoverage);
|
||||
const tokenCoverage = asRecord(record.tokenCoverage) ?? asRecord(preflight?.tokenCoverage);
|
||||
const scopeBoundary = prPreflightScopeBoundary(tokenCoverage);
|
||||
const activeRunnerDevContainer = activeRunnerDevContainerCapability();
|
||||
const authScopeSummary = prPreflightAuthScopeSummary(tokenCoverage, activeRunnerDevContainer);
|
||||
const recommendedActions = prPreflightRecommendedActions(tokenCoverage);
|
||||
return {
|
||||
...record,
|
||||
authScopeSummary,
|
||||
scopeBoundary,
|
||||
activeRunnerDevContainer,
|
||||
...(preflight === null ? {} : { preflight: { ...preflight, scopeBoundary } }),
|
||||
recommendedActions,
|
||||
...(preflight === null ? {} : { preflight: { ...preflight, authScopeSummary, scopeBoundary, recommendedActions } }),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3014,6 +3063,53 @@ function prPreflightObservationGap(kind: Exclude<CodeQueueObservationGapKind, nu
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightObservationSummary(record: Record<string, unknown> | null): Record<string, unknown> | null {
|
||||
if (record === null) return null;
|
||||
const preflight = asRecord(record.preflight);
|
||||
const tokenCoverage = asRecord(record.tokenCoverage) ?? asRecord(preflight?.tokenCoverage);
|
||||
const controlPlane = asRecord(record.controlPlane);
|
||||
const targetStack = asRecord(record.targetStack);
|
||||
return {
|
||||
ok: record.ok ?? null,
|
||||
runnerDisposition: record.runnerDisposition ?? null,
|
||||
failureKind: record.failureKind ?? null,
|
||||
degradedReason: record.degradedReason ?? null,
|
||||
controlPlane: controlPlane === null ? null : {
|
||||
mode: controlPlane.mode ?? null,
|
||||
localBackendCoreMissing: controlPlane.localBackendCoreMissing ?? null,
|
||||
remoteFallbackUsed: controlPlane.remoteFallbackUsed ?? null,
|
||||
},
|
||||
targetStack: targetStack === null ? null : {
|
||||
missingContainers: Array.isArray(targetStack.missingContainers) ? targetStack.missingContainers.map(String) : [],
|
||||
verifyOnlyObserved: targetStack.verifyOnlyObserved ?? false,
|
||||
},
|
||||
tokenCoverage: tokenCoverage === null ? null : {
|
||||
ok: tokenCoverage.ok ?? null,
|
||||
source: tokenCoverage.source ?? null,
|
||||
credentialSource: tokenCoverage.credentialSource ?? null,
|
||||
scope: tokenCoverage.scope ?? null,
|
||||
missing: Array.isArray(tokenCoverage.missing) ? tokenCoverage.missing.map(String) : [],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function maybeFullPrPreflightObservations(options: CodexPrPreflightOptions, localRecord: Record<string, unknown>, remoteRecord: Record<string, unknown>): Record<string, unknown> {
|
||||
if (options.full) {
|
||||
return {
|
||||
localObservation: localRecord,
|
||||
remoteObservation: remoteRecord,
|
||||
};
|
||||
}
|
||||
return {
|
||||
localObservationSummary: prPreflightObservationSummary(localRecord),
|
||||
remoteObservationSummary: prPreflightObservationSummary(remoteRecord),
|
||||
disclosure: {
|
||||
fullObservationsOmitted: true,
|
||||
expandWith: "bun scripts/cli.ts codex pr-preflight --remote --full",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function compactPrRuntimePreflight(preflight: Record<string, unknown>, options: CodexPrPreflightOptions): Record<string, unknown> {
|
||||
const pull = asRecord(preflight.pullRequestDelivery) ?? {};
|
||||
const tools = asRecord(pull.tools) ?? {};
|
||||
@@ -3049,6 +3145,10 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
const pushDryRunRef = options.pushDryRunRef ?? defaultPushDryRunRef;
|
||||
const targetBranch = "master";
|
||||
const expectedHeadBranch = options.prCreateDryRunHead ?? (typeof git.branch === "string" && git.branch.length > 0 ? git.branch : "<head-branch>");
|
||||
const scopeBoundary = prPreflightScopeBoundary(tokenCoverage);
|
||||
const activeRunnerDevContainer = activeRunnerDevContainerCapability();
|
||||
const authScopeSummary = prPreflightAuthScopeSummary(tokenCoverage, activeRunnerDevContainer);
|
||||
const recommendedActions = prPreflightRecommendedActions(tokenCoverage);
|
||||
const result: Record<string, unknown> = {
|
||||
ok,
|
||||
failureKind,
|
||||
@@ -3063,7 +3163,9 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
},
|
||||
tokenCoverage,
|
||||
authBroker: authBrokerNeededStatus(tokenCoverage, authBrokerRuntime, systemGhBinary, unideskGhCli),
|
||||
scopeBoundary: prPreflightScopeBoundary(tokenCoverage),
|
||||
authScopeSummary,
|
||||
scopeBoundary,
|
||||
recommendedActions,
|
||||
prCapabilityContract: {
|
||||
targetBranch,
|
||||
tokenSource: tokenCoverage.source,
|
||||
@@ -3160,12 +3262,12 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
limitations,
|
||||
risks,
|
||||
runnerDisposition: ok ? "ready" : "infra-blocked",
|
||||
activeRunnerDevContainer: activeRunnerDevContainerCapability(),
|
||||
activeRunnerDevContainer,
|
||||
recoveryHint: ok
|
||||
? tokenCoverage.source === "auth-broker"
|
||||
? "Runner PR workflow has auth-broker coverage for GitHub REST preflight; real PR creation still requires commander authorization."
|
||||
: "Runner PR workflow has env-token coverage for the scheduler."
|
||||
: "Scheduler preflight lacks GitHub auth coverage. Configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN into the scheduler runtime secret for scheduler-scoped admission; separately check activeRunnerDevContainer and gh auth status before declaring the current runner unable to create/comment PRs.",
|
||||
: "Scheduler preflight lacks GitHub auth coverage for scheduler-scoped admission only. First verify the active task with repo-native gh auth status and PR create dry-run; long-term configure auth-broker or inject GH_TOKEN/GITHUB_TOKEN into the scheduler runtime secret.",
|
||||
commands: {
|
||||
local: "bun scripts/cli.ts gh auth status --repo pikasTech/unidesk",
|
||||
runner: "bun scripts/cli.ts codex pr-preflight --remote",
|
||||
@@ -3301,8 +3403,7 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
localBackendCoreMissing: true,
|
||||
remoteFallbackUsed: true,
|
||||
},
|
||||
localObservation: localRecord,
|
||||
remoteObservation: remoteRecord,
|
||||
...maybeFullPrPreflightObservations(options, localRecord, remoteRecord),
|
||||
});
|
||||
}
|
||||
return decoratePrPreflightScopeBoundary({
|
||||
@@ -3321,8 +3422,7 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
localBackendCoreMissing: true,
|
||||
remoteFallbackUsed: true,
|
||||
},
|
||||
localObservation: localRecord,
|
||||
remoteObservation: remoteRecord,
|
||||
...maybeFullPrPreflightObservations(options, localRecord, remoteRecord),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3418,6 +3518,10 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
runnerDisposition: compact.runnerDisposition,
|
||||
failureKind: compact.failureKind ?? null,
|
||||
degradedReason: compact.degradedReason ?? null,
|
||||
authScopeSummary: compact.authScopeSummary,
|
||||
scopeBoundary: compact.scopeBoundary,
|
||||
activeRunnerDevContainer: compact.activeRunnerDevContainer,
|
||||
recommendedActions: compact.recommendedActions,
|
||||
upstream: { ok: response.ok, status: response.status },
|
||||
controlPlane: {
|
||||
mode: "local-backend-core",
|
||||
@@ -3470,6 +3574,10 @@ export async function codexPrPreflightQueryAsync(optionArgs: string[], fetcher:
|
||||
runnerDisposition: compact.runnerDisposition,
|
||||
failureKind: compact.failureKind ?? null,
|
||||
degradedReason: compact.degradedReason ?? null,
|
||||
authScopeSummary: compact.authScopeSummary,
|
||||
scopeBoundary: compact.scopeBoundary,
|
||||
activeRunnerDevContainer: compact.activeRunnerDevContainer,
|
||||
recommendedActions: compact.recommendedActions,
|
||||
upstream: { ok: response.ok, status: response.status },
|
||||
controlPlane: {
|
||||
mode: "remote-frontend",
|
||||
|
||||
Reference in New Issue
Block a user