Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 32 additions & 0 deletions apps/presentation/dashboard/smoke/action-review-plan-smoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,35 @@ check(operationPlan.interaction === "gated", "Operation execution keeps its auth
check(operationPlan.operationFrame?.kind === "confirmation", "Dashboard consumes the shared confirmation frame");
check(operationPlan.operationFrame?.interactionMode === "confirm_reject", "The shared frame preserves confirm/reject interaction");
check(operationPlan.operationFrame?.content.fields[0]?.value === "Limit · GTC", "The shared frame preserves bounded projection fields");

const agentPending = typedActionProposalSchema.parse({...operationProposal, status: "applying",
normalized_parameters: {...operationProposal.normalized_parameters, executor: {kind: "agent_session"}},
operation: {...operationProposal.operation, lifecycle_state: "claimed", agent_handoff: {consumption_id: "attempt-1"}}});
const agentPendingFrame = compileActionReviewPlan(agentPending).operationFrame;
check(agentPendingFrame?.kind === "pending" && agentPendingFrame.executionState === "consumed_outcome_pending",
"Transport retains the original consumption; it does not imply an external result");
const unauthenticatedFrame = compileActionReviewPlan({...agentPending,
operation: {...agentPending.operation, agent_handoff: null}}).operationFrame;
check(unauthenticatedFrame?.kind === "pending" && unauthenticatedFrame.executionState === "host_authentication_required",
"Human confirmation alone cannot qualify original-host authentication");
const unknownAgentResult = typedActionProposalSchema.parse({...agentPending, status: "applied",
receipt: {projection_verified: true}, operation: {...agentPending.operation, lifecycle_state: "outcome_observed",
outcome: {outcome: "submission_unknown", simulation: false}, result_delivery: {outcome_stage: "initial"}}});
const managedPending = typedActionProposalSchema.parse({...agentPending,
normalized_parameters: {...agentPending.normalized_parameters, agent_id: "managed-worker", executor: {
kind: "managed_turn", todo_id: "todo-managed", session_id: "owned-thread", profile_digest: "a".repeat(64),
model: "test-model", reasoning_effort: "xhigh", revision: "managed-turn-handoff-v0"}},
operation: {...agentPending.operation, agent_handoff: null}});
const managedFrame = compileActionReviewPlan(managedPending).operationFrame;
check(managedFrame?.kind === "pending" && managedFrame.executionState === "managed_turn_pending",
"Managed confirmation waits for its exact admitted executor rather than Desktop authentication");
check(managedFrame?.content.fields.some(field => field.value.includes("test-model@xhigh")) === true,
"The shared managed profile survives the frontend schema transport");
check(compileActionReviewPlan(managedPending).canApply === false, "Managed approval exposes no local execute control");
check(compileActionReviewPlan(unknownAgentResult).interaction === "repair", "Delivered unknown submission is not completion");
const reconciledAgentResult = typedActionProposalSchema.parse({...unknownAgentResult,
operation: {...unknownAgentResult.operation, reconciliation: {outcome: "not_executed", simulation: false}}});
check(compileActionReviewPlan(reconciledAgentResult).interaction === "repair", "Old card delivery cannot certify a new reconciliation");
check(compileActionReviewPlan({...reconciledAgentResult, operation: {...reconciledAgentResult.operation,
result_delivery: {outcome_stage: "reconciled"}}}).interaction === "completed", "Only reconciled card readback completes presentation");
console.log("PASS: original-Agent handoff and append-only reconciliation survive the frontend transport");
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import assert from "node:assert/strict";
import {mkdir} from "node:fs/promises";
import {resolve} from "node:path";
import {delegationPreflight} from "../../../../loopx/control_plane/collaboration/delegation.ts";
import {projectManagedOperationTransport} from "../../../../loopx/control_plane/work_items/operation_agent_handoff.ts";
import {launchBrowser, loadPlaywright, waitForHttp} from "../../../../examples/dashboard-browser-smoke-support.mjs";
import {outputDir, packaged, port, startServer} from "../../../../examples/personal-workspace-browser/fixture.mjs";
import {openWorkspacePage} from "../../../../examples/personal-workspace-browser/scenario-context.mjs";
Expand Down Expand Up @@ -35,7 +36,16 @@ try {
acceptance_declaration_mismatch: "completion_validation_declaration_mismatch",
acceptance_unknown: "/private/validator PRIVATE_VALUE",
};
const check = state.startsWith("acceptance_")
const operation = projectManagedOperationTransport({host: "codex-cli", sandbox: "read-only",
model: state === "operation_invalid" ? null : "test-model", reasoning_effort: "xhigh"});
const check = state.startsWith("operation_")
? delegationPreflight({binding, acceptance: {todo_id: binding.todo_id, state: "ready"},
validation_files_current: true, preview: {dry_run: true, status: "preview",
effects: {host_invoked: false, state_written: false, quota_spent: false, scheduler_acknowledged: false},
route: {kind: "ready_for_host", would_invoke_host: true, selected_todo_id: binding.todo_id},
managed_executor: {executor: "codex-cli", available: operation.reason ? false : null,
unavailable_reason: operation.reason, execution_profile: "test-model@xhigh", operation_transport: operation.transport}}})
: state.startsWith("acceptance_")
? delegationPreflight({binding,
acceptance: {todo_id: binding.todo_id, state: state === "acceptance_files" ? "ready" : "unbound",
reason: acceptanceReasons[state]}, validation_files_current: false,
Expand Down Expand Up @@ -113,6 +123,19 @@ try {
}
}
}
for (const valid of [true, false]) {
state = valid ? "operation_valid" : "operation_invalid";
await team.getByRole("button", {name: zh ? "检查整个团队" : "Check whole team", exact: true}).click();
const observations = team.locator(".goal-team-bindings > li > p[role=status]");
const expected = valid ? (zh ? "运行未核验" : "runtime unqualified")
: (zh ? "操作传输配置未获准" : "Operation transport configuration not admitted");
await observations.filter({hasText: expected}).nth(2).waitFor();
for (const [size, viewport] of [["desktop", {width: 1512, height: 982}], ["mobile", {width: 390, height: 844}]]) {
await page.setViewportSize(viewport);
assert(await dialog.evaluate(el => el.scrollWidth <= el.clientWidth), "Operation transport readback must not overflow");
if (valid) await page.screenshot({path: resolve(outputDir, `operation-preflight-${zh ? "zh" : "en"}-${size}.png`), animations: "disabled"});
}
}
const member = team.locator(".goal-team-bindings > li").filter({hasText: "local-analyst"});
await member.locator("summary").click();
state = "available";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,20 @@ for (const zh of [true, false]) {
}

console.log("delegation authority/workspace/validation preflight smoke passed");

for (const valid of [true, false]) {
const check = {...unavailable, state: "runtime_unverified", authority_ready: true,
authority_reason: null, authority_state: "promoted", authority_next_action: "none",
executor: {host: "codex-cli", available: valid, reason: valid ? null : "operation_transport_profile_required",
profile: "test-model@xhigh", operation_transport: {schema_version: "loopx_operation_transport_v0",
configuration_valid: valid, runtime_qualified: false}}} as DelegationPreflight;
for (const zh of [false, true]) {
const html = renderToStaticMarkup(<DelegationPreflightStatus check={check} zh={zh}/>);
if (!html.includes(valid ? (zh ? "运行未核验" : "runtime unqualified")
: (zh ? "操作传输配置未获准" : "Operation transport configuration not admitted"))) {
throw new Error("Shared transport projection lost truthful configuration readback");
}
if (/Runtime qualified|运行已核验/.test(html)) throw new Error("Preflight invented transport qualification");
}
}
console.log("managed operation transport remains configuration-only in delegation preflight");
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export type DelegationPreflight = {
authority_state: "promotion_required" | "unavailable" | "promoted" | "uninspected";
authority_next_action: "preview_reviewed_goal_authority_promotion" | "repair_canonical_authority" | "none";
promotion_from_surface_allowed: false;
executor: {host: string; available: boolean | null; reason: string | null; profile: string | null} | null;
executor: {host: string; available: boolean | null; reason: string | null; profile: string | null;
operation_transport?: {schema_version: "loopx_operation_transport_v0";
configuration_valid: boolean; runtime_qualified: false}} | null;
effects: {host_invoked: boolean; state_written: boolean; quota_spent: boolean; scheduler_acknowledged: boolean};
};
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,16 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention
};
}, [closeDrawer, selection.kind]);

const operationUnknown = selection.kind === "proposal"
&& selection.item.reviewPlan?.operationFrame?.kind === "result"
&& selection.item.reviewPlan.operationFrame.resultKind === "unknown";
const title = selection.kind === "attention" ? t("drawer.titleAttention")
: selection.kind === "todo" ? t("drawer.taskDetails")
: selection.kind === "run" ? t("drawer.runDetails")
: selection.kind === "output" ? t("drawer.titleOutput")
: selection.kind === "proposal" && selection.item.actionKind === "team.plan" && selection.item.status === "applied" ? t("proposal.teamPlan.resultTitle")
: selection.kind === "proposal" && selection.item.actionKind === "operation.execute"
&& selection.item.reviewPlan?.operationFrame?.kind !== "confirmation" ? t("drawer.operationReadOnly")
: selection.kind === "proposal" ? t(selection.item.reviewPlan?.retryOriginal ? "drawer.recoverEditResult" : selection.item.status === "applied" ? "drawer.titleProposalApplied" : "drawer.titleProposalConfirm")
: selection.kind === "schedule" ? (selection.item.scheduleKind === "heartbeat" ? "Heartbeat" : t("drawer.titleSchedule"))
: t("drawer.goalDetails");
Expand All @@ -300,6 +305,7 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention
: selection.kind === "goal" ? selection.item.title
: selection.kind === "schedule" ? t("drawer.goalAutoRun")
: selection.kind === "proposal" && selection.item.status === "applied" && selection.item.actionKind === "team.plan" ? selection.item.goalId ?? t("drawer.currentGoal")
: selection.kind === "proposal" && selection.item.actionKind === "operation.execute" ? t("drawer.operationCanonicalStatus")
: selection.item.goalId ? t("drawer.goalChanges") : t("drawer.managerChanges");
const selectedGoalRun = selection.kind === "goal"
? runs.find((run) => run.goalId === selection.item.goalId && Boolean(run.sessionId))
Expand Down Expand Up @@ -1109,7 +1115,9 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention
<small>{selection.item.actionKind} · {selection.item.status}</small>
<h3>{selection.item.title}</h3>
{selection.item.impact ? <p>{selection.item.impact}</p> : null}
{selection.item.reviewPlan && !selection.item.reviewPlan.retryOriginal && selection.item.actionKind !== "team.plan" ? <p className="personal-proposal-explainer" data-action-review={selection.item.reviewPlan.interaction}>{selection.item.actionKind === "operation.execute" && selection.item.status === "gated"
{selection.item.reviewPlan && !selection.item.reviewPlan.retryOriginal && selection.item.actionKind !== "team.plan" ? <p className="personal-proposal-explainer" data-action-review={selection.item.reviewPlan.interaction}>{operationUnknown
? t("actionReview.operation_reconcile_original")
: selection.item.actionKind === "operation.execute" && selection.item.status === "gated"
? t("actionReview.operation_group_confirmation")
: selection.item.actionKind === "operation.execute" && selection.item.reviewPlan.reason === "readback_unverified"
? t("actionReview.operation_result_delivery_pending")
Expand All @@ -1120,7 +1128,7 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention
{selection.item.status === "applied" && selection.item.actionKind !== "team.plan" ? <p className={`personal-proposal-state ${selection.item.actionKind === "operation.execute" && selection.item.reviewPlan?.reason === "readback_unverified" ? "is-gated" : "is-applied"}`}><Check size={16} />{selection.item.actionKind === "operation.execute" ? selection.item.primaryLabel : t("drawer.proposalApplied")}</p> : null}
{selection.item.status === "applied" && selection.item.actionKind !== "operation.execute" && selection.item.goalId ? <button className="personal-primary-action" onClick={() => { const goalId = selection.item.goalId!; onClose(); void callbacks.onOpenGoal?.(goalId); }} type="button"><ExternalLink size={16} />{selection.item.actionKind === "goal.create" ? t("drawer.proposalEnterGoal") : t(selection.item.actionKind === "team.plan" ? "proposal.teamPlan.openGoal" : "drawer.proposalViewGoal")}</button> : null}
{selection.item.status === "stale" ? <p className="personal-proposal-state is-stale">{t("drawer.proposalStale")}</p> : null}
{selection.item.status === "error" && !selection.item.reviewPlan?.retryOriginal ? <div className="personal-proposal-state is-error"><span>{selection.item.reviewPlan?.reason === "readback_unverified" ? t("actionReview.readback_unverified") : t("drawer.proposalApplyFailed")}</span>{selection.item.errorMessage ? <small>{selection.item.errorMessage}</small> : null}<small>{t(selection.item.actionKind === "team.plan" ? "proposal.teamPlan.retryHint" : "drawer.proposalApplyFailedHint")}</small></div> : null}
{selection.item.status === "error" && !selection.item.reviewPlan?.retryOriginal ? <div className="personal-proposal-state is-error"><span>{operationUnknown ? t("proposal.operationState.submission_unknown") : selection.item.reviewPlan?.reason === "readback_unverified" ? t("actionReview.readback_unverified") : t("drawer.proposalApplyFailed")}</span>{selection.item.errorMessage ? <small>{selection.item.errorMessage}</small> : null}<small>{t(operationUnknown ? "actionReview.operation_reconcile_original" : selection.item.actionKind === "team.plan" ? "proposal.teamPlan.retryHint" : "drawer.proposalApplyFailedHint")}</small></div> : null}
{selection.item.status === "rejected" ? <p className="personal-proposal-state is-error">{t("drawer.proposalRejected")}</p> : null}
{selection.item.status === "deferred" ? <p className="personal-proposal-state is-gated">{t("drawer.proposalDeferred")}</p> : null}
{selection.item.status === "gated" ? <div className="personal-proposal-state is-gated"><span><strong>{selection.item.actionKind === "operation.execute" ? selection.item.primaryLabel : selection.item.workspaceCandidates?.length ? selection.item.title : t("drawer.gateRequiresHost")}</strong>{selection.item.actionKind === "operation.execute" || selection.item.workspaceCandidates?.length ? selection.item.impact : t("drawer.gateRequiresHostDescription")}</span>{selection.item.gate?.nextAction ? <small>{selection.item.gate.nextAction}</small> : null}</div> : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ export function DelegationPreflightStatus({check, zh}: {check: DelegationPreflig
? acceptanceActions[check.acceptance_next_action] : null;
const executorDetail = check.executor
? [check.executor.host, check.executor.reason].filter(Boolean).join(" · ") : check.authority_reason;
const operationTransport = check.executor?.operation_transport;
const operationDetail = operationTransport?.schema_version === "loopx_operation_transport_v0"
? operationTransport.configuration_valid === true && operationTransport.runtime_qualified === false
? (zh ? "自有原生工具传输已配置,运行未核验;执行仍需精确批准与首次消费"
: "Owned native tool transport configured, runtime unqualified; exact approval and first consumption still required")
: (zh ? "操作传输配置未获准;请原配置责任人核对宿主、固定模型/思考深度和 sandbox"
: "Operation transport configuration not admitted; ask its original owner to review host, pinned model/effort and sandbox")
: null;
const detail = check.state === "workspace_unavailable"
? (workspaceDetail ? (zh ? workspaceDetail.zh : workspaceDetail.en) : null)
: [acceptanceDetail ? (zh ? acceptanceDetail.zh : acceptanceDetail.en) : null, executorDetail].filter(Boolean).join(" · ");
Expand All @@ -66,6 +74,7 @@ export function DelegationPreflightStatus({check, zh}: {check: DelegationPreflig
return <p role="status">
{zh ? labels[check.state].zh : labels[check.state].en}
{detail ? ` · ${detail}` : ""}
{operationDetail ? ` · ${operationDetail}` : ""}
{nextAction ? ` · ${nextAction}` : ""}
{` · ${disclaimer}`}
</p>;
Expand Down
Loading
Loading