Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6b753bf
docs(onboard): document FSM migration target
cv May 27, 2026
fb1b32d
refactor(onboard): centralize machine state metadata
cv May 27, 2026
c3e4ad6
refactor(onboard): derive session step mapping from FSM metadata
cv May 27, 2026
603832c
refactor(onboard): derive progress labels from FSM metadata
cv May 27, 2026
4fad8e7
fix(onboard): emit lifecycle events for onboarding start
cv May 28, 2026
f99e9cb
fix(onboard): emit machine events for resume conflicts
cv May 28, 2026
2b60df4
refactor(onboard): introduce explicit state result types
cv May 28, 2026
30341b0
refactor(onboard): apply explicit state results through runtime
cv May 28, 2026
d4ad2d9
refactor(onboard): make finalization return FSM result
cv May 28, 2026
356c947
refactor(onboard): make agent setup return FSM result
cv May 28, 2026
2296519
refactor(onboard): make policy setup return FSM result
cv May 28, 2026
67a9a1e
refactor(onboard): make preflight and gateway return FSM results
cv May 28, 2026
46f4a49
refactor(onboard): make sandbox return branch FSM result
cv May 28, 2026
9cc15f5
refactor(onboard): return FSM results from provider inference
cv May 28, 2026
dbbb273
refactor(onboard): add FSM runner shell
cv May 28, 2026
6b27a0b
refactor(onboard): consume handler FSM results compatibly
cv May 28, 2026
44009ad
refactor(onboard): allow step recording without machine transitions
cv May 28, 2026
cd6e5f7
refactor(onboard): plumb step mutation options through runtime
cv May 28, 2026
e266e3b
refactor(onboard): add record-only FSM runner adapter
cv May 28, 2026
bf4da0b
refactor(onboard): return ordered provider FSM results
cv May 28, 2026
9e8b1f5
merge(main): resolve PR 4471 conflicts
cv Jun 5, 2026
b2b5e1c
Merge branch 'main' into stack/onboard-fsm-provider-result-sequence
cv Jun 5, 2026
287fbf4
fix(onboard): keep provider result merge net-neutral
cv Jun 5, 2026
5db7c65
Merge branch 'main' into stack/onboard-fsm-provider-result-sequence
cv Jun 7, 2026
ba670ec
Merge branch 'main' into stack/onboard-fsm-provider-result-sequence
cv Jun 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/lib/onboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6411,7 +6411,7 @@ async function onboard(opts: OnboardOptions = {}): Promise<void> {
},
},
});
session = (await onboardRuntimeBoundary.recordStateResultsWithStepCompatibility([...providerInferenceResult.retryStateResults, providerInferenceResult.stateResult]), providerInferenceResult.session);
await onboardRuntimeBoundary.recordStateResultsWithStepCompatibility(providerInferenceResult.stateResults);
sandboxName = providerInferenceResult.sandboxName;
const {
model,
Expand All @@ -6429,7 +6429,7 @@ async function onboard(opts: OnboardOptions = {}): Promise<void> {
resume,
fresh,
resumeAgentChanged,
session,
session: providerInferenceResult.session,
sandboxName,
model,
provider,
Expand Down
16 changes: 16 additions & 0 deletions src/lib/onboard/machine/handlers/provider-inference.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,16 @@ describe("handleProviderInferenceState", () => {
metadata: { state: "inference", provider: "nvidia-prod", model: "nvidia/test" },
});
expect(result.retryStateResults).toEqual([]);
expect(result.stateResults).toEqual([
{
type: "transition",
next: "inference",
transitionKind: "advance",
updates: undefined,
metadata: { state: "provider_selection", provider: "nvidia-prod", model: "nvidia/test" },
},
result.stateResult,
]);
});

it("clears non-NVIDIA provider credentials when inference setup fails", async () => {
Expand Down Expand Up @@ -435,6 +445,12 @@ describe("handleProviderInferenceState", () => {
},
]);
expect(result.stateResult).toMatchObject({ next: "sandbox", transitionKind: "advance" });
expect(result.stateResults.map((stateResult) => [stateResult.next, stateResult.transitionKind])).toEqual([
["inference", "advance"],
["provider_selection", "retry"],
["inference", "advance"],
["sandbox", "advance"],
]);
});

it("aborts before inference setup when the configuration summary is rejected", async () => {
Expand Down
39 changes: 25 additions & 14 deletions src/lib/onboard/machine/handlers/provider-inference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { WebSearchConfig } from "../../../inference/web-search";
import type { Session, SessionUpdates } from "../../../state/onboard-session";
import { withInferenceTrace, withProviderSelectionTrace } from "../../tracing";
import { advanceTo, retryTo, type OnboardStateTransitionResult } from "../result";
import { advanceTo, type OnboardStateTransitionResult, retryTo } from "../result";

export type ProviderInferenceRetry = { retry: "selection" } | { ok: true; retry?: undefined };

Expand Down Expand Up @@ -127,6 +127,7 @@ export interface ProviderInferenceStateResult {
webSearchConfig: WebSearchConfig | null;
session: Session | null;
stateResult: OnboardStateTransitionResult;
stateResults: OnboardStateTransitionResult[];
retryStateResults: OnboardStateTransitionResult[];
}

Expand Down Expand Up @@ -177,6 +178,7 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
const webSearchConfig = initial.webSearchConfig;
let forceProviderSelection = initialForceProviderSelection;
let allowToolsIncompatible = false;
const stateResults: OnboardStateTransitionResult[] = [];
const retryStateResults: OnboardStateTransitionResult[] = [];

while (true) {
Expand Down Expand Up @@ -261,6 +263,11 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
}),
);
}
stateResults.push(
advanceTo("inference", {
metadata: { state: "provider_selection", provider, model },
}),
);
env.NEMOCLAW_OPENSHELL_BIN = deps.getOpenshellBinary();
const needsBedrockRuntimeAdapter = deps.needsBedrockRuntimeAdapter(provider, endpointUrl);
const resumeInference =
Expand Down Expand Up @@ -297,11 +304,11 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
clearStagedCredentialEnv(deps, credentialEnv);
}
if (inferenceResult?.retry === "selection") {
retryStateResults.push(
retryTo("provider_selection", {
metadata: { state: "inference", provider, model, reason: "selection_retry" },
}),
);
const retryStateResult = retryTo("provider_selection", {
metadata: { state: "inference", provider, model, reason: "selection_retry" },
});
retryStateResults.push(retryStateResult);
stateResults.push(retryStateResult);
forceProviderSelection = true;
continue;
}
Expand Down Expand Up @@ -395,11 +402,11 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
clearStagedCredentialEnv(deps, credentialEnv);
}
if (inferenceResult?.retry === "selection") {
retryStateResults.push(
retryTo("provider_selection", {
metadata: { state: "inference", provider, model, reason: "selection_retry" },
}),
);
const retryStateResult = retryTo("provider_selection", {
metadata: { state: "inference", provider, model, reason: "selection_retry" },
});
retryStateResults.push(retryStateResult);
stateResults.push(retryStateResult);
forceProviderSelection = true;
continue;
}
Expand All @@ -411,6 +418,11 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
break;
}

const stateResult = advanceTo("sandbox", {
metadata: { state: "inference", provider, model },
});
stateResults.push(stateResult);

return {
sandboxName,
model,
Expand All @@ -423,9 +435,8 @@ export async function handleProviderInferenceState<Gpu, Agent, Host>({
nimContainer,
webSearchConfig,
session,
stateResult: advanceTo("sandbox", {
metadata: { state: "inference", provider, model },
}),
stateResult,
stateResults,
retryStateResults,
};
}