feat: consolidate agent execution stack
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { Button } from "@code/ui/components/button";
|
||||
import {
|
||||
AlertTriangle,
|
||||
Check,
|
||||
ChevronRight,
|
||||
FileCode2,
|
||||
Hammer,
|
||||
@@ -32,16 +31,13 @@ const starterDefinition = (work: WorkRecord) => ({
|
||||
outOfScope: ["Unrelated product changes"],
|
||||
problem: work.objective,
|
||||
questions: [],
|
||||
requiredArtifacts: ["Simulation activity and terminal outcome"],
|
||||
requiredArtifacts: ["Implementation diff and terminal outcome"],
|
||||
risk: "medium",
|
||||
});
|
||||
|
||||
const starterDesign = (work: WorkRecord) => ({
|
||||
architectureSummary:
|
||||
"Validate the approved Definition, then exercise one deterministic fake slice.",
|
||||
callFlowDelta: [
|
||||
"Work -> Run -> Attempt -> normalized events -> terminal outcome",
|
||||
],
|
||||
architectureSummary: "Implement the requested outcome in focused changes.",
|
||||
callFlowDelta: ["Work -> Run -> Attempt -> AgentOS -> candidate revision"],
|
||||
concerns: [],
|
||||
evidenceRequirements: ["Terminal Run classification"],
|
||||
fileTreeDelta: [],
|
||||
@@ -49,30 +45,30 @@ const starterDesign = (work: WorkRecord) => ({
|
||||
files: [],
|
||||
modules: [],
|
||||
risks: [],
|
||||
summary: "Compact vertical-slice simulation",
|
||||
summary: "Focused implementation",
|
||||
},
|
||||
invariants: [
|
||||
"Simulation never claims implementation",
|
||||
"A successful AgentOS response alone never marks Work complete",
|
||||
"Every Attempt reaches a terminal classification",
|
||||
],
|
||||
keyInterfaces: ["HarnessRuntime", "AttemptOutcome"],
|
||||
keyInterfaces: ["WorkExecution", "AttemptResult"],
|
||||
slices: [
|
||||
{
|
||||
codeBoundaries: ["workExecution"],
|
||||
dependsOn: [],
|
||||
evidenceRequirements: ["Normalized activity events"],
|
||||
id: "deterministic-simulation",
|
||||
id: "implementation",
|
||||
objective: work.objective,
|
||||
observableBehavior: "A terminal fake Run is visible",
|
||||
observableBehavior: "Implementation changes are visible in the diff",
|
||||
reviewRequired: false,
|
||||
title: "Deterministic simulation",
|
||||
title: "Implementation",
|
||||
verification: ["Run completes with a terminal classification"],
|
||||
},
|
||||
],
|
||||
tradeoffs: ["Fake runtime proves contract before sandbox integration"],
|
||||
tradeoffs: [],
|
||||
});
|
||||
|
||||
// oxlint-disable-next-line complexity -- this card intentionally coordinates review actions and run evidence.
|
||||
// oxlint-disable-next-line complexity -- this card coordinates planning and run evidence.
|
||||
export const WorkCard = ({
|
||||
onSourceSelect,
|
||||
work,
|
||||
@@ -95,7 +91,7 @@ export const WorkCard = ({
|
||||
</span>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-[10px] font-semibold uppercase text-[#65713a]">
|
||||
Proposed Work
|
||||
{work.status === "proposed" ? "Proposed Work" : "Work"}
|
||||
</p>
|
||||
<h2 className="mt-1 text-[15px] font-semibold leading-5">
|
||||
{work.title}
|
||||
@@ -149,7 +145,8 @@ export const WorkCard = ({
|
||||
Outcome
|
||||
</p>
|
||||
<p className="mt-1 leading-5 text-[#626057]">{work.objective}</p>
|
||||
<p className="mt-2 text-[#747168]">
|
||||
<p className="mt-2 text-[#747168]">Status: {work.status}</p>
|
||||
<p className="mt-1 text-[#747168]">
|
||||
Risk: {work.definition?.risk ?? "not defined"}
|
||||
</p>
|
||||
{openQuestions > 0 ? (
|
||||
@@ -180,20 +177,6 @@ export const WorkCard = ({
|
||||
<Hammer className="size-3.5" /> Save definition
|
||||
</Button>
|
||||
) : null}
|
||||
{work.status === "awaiting-definition-approval" &&
|
||||
work.definitionVersion ? (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
void workspace.approveDefinition(
|
||||
work._id,
|
||||
work.definitionVersion as number
|
||||
)
|
||||
}
|
||||
>
|
||||
<Check className="size-3.5" /> Approve
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
@@ -220,22 +203,6 @@ export const WorkCard = ({
|
||||
<Hammer className="size-3.5" /> Save design
|
||||
</Button>
|
||||
) : null}
|
||||
{work.status === "awaiting-design-approval" &&
|
||||
work.definitionApprovalVersion &&
|
||||
work.designVersion ? (
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={() =>
|
||||
void workspace.approveDesign(
|
||||
work._id,
|
||||
work.definitionApprovalVersion as number,
|
||||
work.designVersion as number
|
||||
)
|
||||
}
|
||||
>
|
||||
<Check className="size-3.5" /> Approve design
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
@@ -261,10 +228,7 @@ export const WorkCard = ({
|
||||
{latestRun ? (
|
||||
<div className="mt-1 space-y-2 text-[#626057]">
|
||||
<p className="leading-5">
|
||||
{latestRun.executionKind === "real"
|
||||
? "AgentOS"
|
||||
: "Simulation"}{" "}
|
||||
run {latestRun.status}:{" "}
|
||||
Run {latestRun.status}:{" "}
|
||||
{latestRun.terminalSummary ??
|
||||
latestRun.terminalClassification ??
|
||||
"activity is still arriving"}
|
||||
@@ -343,45 +307,29 @@ export const WorkCard = ({
|
||||
)}
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
{work.status === "ready" ? (
|
||||
<>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={!workspace.projectGitConnection}
|
||||
onClick={() => void workspace.startExecution(work._id)}
|
||||
>
|
||||
<Play className="size-3.5" /> Run
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
void workspace.startSimulation(work._id, "success")
|
||||
}
|
||||
>
|
||||
<Play className="size-3.5" /> Simulate
|
||||
</Button>
|
||||
</>
|
||||
<Button
|
||||
size="sm"
|
||||
disabled={!workspace.projectGitConnection}
|
||||
onClick={() => void workspace.startExecution(work._id)}
|
||||
>
|
||||
<Play className="size-3.5" /> Run
|
||||
</Button>
|
||||
) : null}
|
||||
{latestRun?.status === "running" ? (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
void (latestRun.executionKind === "real"
|
||||
? workspace.cancelExecution(latestRun._id)
|
||||
: workspace.cancelSimulation(latestRun._id))
|
||||
}
|
||||
onClick={() => void workspace.cancelExecution(latestRun._id)}
|
||||
>
|
||||
<X className="size-3.5" /> Cancel
|
||||
</Button>
|
||||
) : null}
|
||||
{latestRun?.executionKind !== "real" &&
|
||||
latestRun?.status === "terminal" &&
|
||||
{latestRun?.status === "terminal" &&
|
||||
latestRun.terminalClassification === "RetryableFailure" ? (
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => void workspace.retrySimulation(latestRun._id)}
|
||||
onClick={() => void workspace.retryExecution(latestRun._id)}
|
||||
>
|
||||
<RotateCcw className="size-3.5" /> Retry
|
||||
</Button>
|
||||
|
||||
@@ -13,13 +13,6 @@ import type { WorkRecord, WorkspaceState } from "@/lib/workspace/types";
|
||||
const toError = (error: unknown) =>
|
||||
error instanceof Error ? error : new Error(String(error));
|
||||
|
||||
type ExecutionScenario =
|
||||
| "success"
|
||||
| "transient-failure-then-success"
|
||||
| "needs-input"
|
||||
| "permanent-failure"
|
||||
| "cancelled";
|
||||
|
||||
const workListRef = makeFunctionReference<
|
||||
"query",
|
||||
{ projectId: Id<"projects"> },
|
||||
@@ -35,46 +28,26 @@ const saveDefinitionRef = makeFunctionReference<
|
||||
{ workId: Id<"works">; payloadJson: string },
|
||||
unknown
|
||||
>("workPlanning:saveDefinitionProposal");
|
||||
const approveDefinitionRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ workId: Id<"works">; version: number },
|
||||
unknown
|
||||
>("workPlanning:approveDefinition");
|
||||
const saveDesignRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ workId: Id<"works">; payloadJson: string },
|
||||
unknown
|
||||
>("workPlanning:saveDesignProposal");
|
||||
const approveDesignRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ workId: Id<"works">; definitionVersion: number; designVersion: number },
|
||||
unknown
|
||||
>("workPlanning:approveDesign");
|
||||
const startSimulationRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ workId: Id<"works">; scenario: ExecutionScenario; sliceId?: string },
|
||||
unknown
|
||||
>("workExecution:startSimulatedExecution");
|
||||
const cancelSimulationRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ runId: Id<"workRuns"> },
|
||||
unknown
|
||||
>("workExecution:cancelSimulatedExecution");
|
||||
const retrySimulationRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ runId: Id<"workRuns"> },
|
||||
unknown
|
||||
>("workExecution:retrySimulatedExecution");
|
||||
const startExecutionRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ workId: Id<"works">; sliceId?: string },
|
||||
{ sliceId?: string; workId: Id<"works"> },
|
||||
unknown
|
||||
>("workExecutionWorkflow:startExecution");
|
||||
>("workExecution:start");
|
||||
const cancelExecutionRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ runId: Id<"workRuns"> },
|
||||
unknown
|
||||
>("workExecutionWorkflow:cancelExecution");
|
||||
>("workExecution:cancel");
|
||||
const retryExecutionRef = makeFunctionReference<
|
||||
"mutation",
|
||||
{ runId: Id<"workRuns"> },
|
||||
unknown
|
||||
>("workExecution:retry");
|
||||
const listGitConnectionsRef = makeFunctionReference<
|
||||
"query",
|
||||
Record<string, never>,
|
||||
@@ -153,14 +126,10 @@ export const useProjectWorkspace = (): WorkspaceState => {
|
||||
);
|
||||
const requestDefinitionMutation = useMutation(requestDefinitionRef);
|
||||
const saveDefinitionMutation = useMutation(saveDefinitionRef);
|
||||
const approveDefinitionMutation = useMutation(approveDefinitionRef);
|
||||
const saveDesignMutation = useMutation(saveDesignRef);
|
||||
const approveDesignMutation = useMutation(approveDesignRef);
|
||||
const startSimulationMutation = useMutation(startSimulationRef);
|
||||
const cancelSimulationMutation = useMutation(cancelSimulationRef);
|
||||
const retrySimulationMutation = useMutation(retrySimulationRef);
|
||||
const startExecutionMutation = useMutation(startExecutionRef);
|
||||
const cancelExecutionMutation = useMutation(cancelExecutionRef);
|
||||
const retryExecutionMutation = useMutation(retryExecutionRef);
|
||||
const attachGitConnectionMutation = useMutation(attachGitConnectionRef);
|
||||
const connectGiteaAction = useAction(connectGiteaRef);
|
||||
const connectGithubAction = useAction(connectGithubRef);
|
||||
@@ -224,13 +193,6 @@ export const useProjectWorkspace = (): WorkspaceState => {
|
||||
|
||||
return {
|
||||
agent,
|
||||
approveDefinition: (workId: Id<"works">, version: number) =>
|
||||
approveDefinitionMutation({ version, workId }),
|
||||
approveDesign: (
|
||||
workId: Id<"works">,
|
||||
definitionVersion: number,
|
||||
designVersion: number
|
||||
) => approveDesignMutation({ definitionVersion, designVersion, workId }),
|
||||
authorizeGithub: () =>
|
||||
authClient.linkSocial({
|
||||
callbackURL: `${window.location.origin}/projects?resume=github`,
|
||||
@@ -238,8 +200,6 @@ export const useProjectWorkspace = (): WorkspaceState => {
|
||||
}),
|
||||
cancelExecution: (runId: Id<"workRuns">) =>
|
||||
runOperation(() => cancelExecutionMutation({ runId })),
|
||||
cancelSimulation: (runId: Id<"workRuns">) =>
|
||||
runOperation(() => cancelSimulationMutation({ runId })),
|
||||
clearOperationError: () => setOperationError(undefined),
|
||||
connectGitea,
|
||||
connectLinkedGithub,
|
||||
@@ -253,8 +213,8 @@ export const useProjectWorkspace = (): WorkspaceState => {
|
||||
repository,
|
||||
requestDefinition: (workId: Id<"works">) =>
|
||||
requestDefinitionMutation({ workId }),
|
||||
retrySimulation: (runId: Id<"workRuns">) =>
|
||||
runOperation(() => retrySimulationMutation({ runId })),
|
||||
retryExecution: (runId: Id<"workRuns">) =>
|
||||
runOperation(() => retryExecutionMutation({ runId })),
|
||||
saveDefinition: (workId: Id<"works">, payload: unknown) =>
|
||||
saveDefinitionMutation({ payloadJson: JSON.stringify(payload), workId }),
|
||||
saveDesign: (workId: Id<"works">, payload: unknown) =>
|
||||
@@ -267,14 +227,6 @@ export const useProjectWorkspace = (): WorkspaceState => {
|
||||
setRepository,
|
||||
startExecution: (workId: Id<"works">, sliceId?: string) =>
|
||||
runOperation(() => startExecutionMutation({ sliceId, workId })),
|
||||
startSimulation: (
|
||||
workId: Id<"works">,
|
||||
scenario: ExecutionScenario,
|
||||
sliceId?: string
|
||||
) =>
|
||||
runOperation(() =>
|
||||
startSimulationMutation({ scenario, sliceId, workId })
|
||||
),
|
||||
works,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,7 +9,6 @@ export interface WorkRecord {
|
||||
readonly objective: string;
|
||||
readonly status: string;
|
||||
readonly definitionVersion?: number;
|
||||
readonly definitionApprovalVersion?: number;
|
||||
readonly designVersion?: number;
|
||||
readonly signals: readonly {
|
||||
readonly sources: readonly { messageId: string; rawText: string }[];
|
||||
@@ -34,7 +33,6 @@ export interface WorkRun {
|
||||
readonly attemptEvents?: readonly WorkAttemptEvent[];
|
||||
readonly baseRevision?: string;
|
||||
readonly candidateRevision?: string;
|
||||
readonly executionKind?: string;
|
||||
readonly _id: Id<"workRuns">;
|
||||
readonly status: string;
|
||||
readonly terminalClassification?: string;
|
||||
@@ -81,18 +79,8 @@ export interface WorkspaceState {
|
||||
| "streaming"
|
||||
| "submitted";
|
||||
};
|
||||
readonly approveDefinition: (
|
||||
workId: Id<"works">,
|
||||
version: number
|
||||
) => Promise<unknown>;
|
||||
readonly approveDesign: (
|
||||
workId: Id<"works">,
|
||||
definitionVersion: number,
|
||||
designVersion: number
|
||||
) => Promise<unknown>;
|
||||
readonly authorizeGithub: () => Promise<unknown>;
|
||||
readonly cancelExecution: (runId: Id<"workRuns">) => Promise<unknown>;
|
||||
readonly cancelSimulation: (runId: Id<"workRuns">) => Promise<unknown>;
|
||||
readonly clearOperationError: () => void;
|
||||
readonly connectGitea: (input: {
|
||||
readonly token: string;
|
||||
@@ -108,7 +96,7 @@ export interface WorkspaceState {
|
||||
readonly projects: readonly ProjectListItem[] | undefined;
|
||||
readonly repository: string;
|
||||
readonly requestDefinition: (workId: Id<"works">) => Promise<unknown>;
|
||||
readonly retrySimulation: (runId: Id<"workRuns">) => Promise<unknown>;
|
||||
readonly retryExecution: (runId: Id<"workRuns">) => Promise<unknown>;
|
||||
readonly saveDefinition: (
|
||||
workId: Id<"works">,
|
||||
payload: unknown
|
||||
@@ -124,16 +112,6 @@ export interface WorkspaceState {
|
||||
workId: Id<"works">,
|
||||
sliceId?: string
|
||||
) => Promise<unknown>;
|
||||
readonly startSimulation: (
|
||||
workId: Id<"works">,
|
||||
scenario:
|
||||
| "success"
|
||||
| "transient-failure-then-success"
|
||||
| "needs-input"
|
||||
| "permanent-failure"
|
||||
| "cancelled",
|
||||
sliceId?: string
|
||||
) => Promise<unknown>;
|
||||
readonly works: readonly WorkRecord[] | undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user