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
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ check(managedFrame?.kind === "pending" && managedFrame.executionState === "manag
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");
const startedManaged = typedActionProposalSchema.parse({...managedPending,
operation: {...managedPending.operation, host_start: {schema_version: "loopx_operation_host_start_v0", host_turn_id: "native-turn"}}});
const startedFrame = compileActionReviewPlan(startedManaged).operationFrame;
check(startedFrame?.kind === "pending" && startedFrame.executionState === "managed_turn_started",
"Native accepted start survives schema transport without claiming consumption or execution");
check(compileActionReviewPlan(startedManaged).canApply === false, "Accepted native start grants no apply 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}}});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ export function ChannelTimeline({
}
if (item.kind === "proposal") {
const appliedTeamPlan = item.proposal.actionKind === "team.plan" && item.proposal.status === "applied";
const pendingOperation = item.proposal.reviewPlan?.operationFrame?.kind === "pending";
return (
<Fragment key={item.id}><button className={`personal-proposal-row is-${item.proposal.status}`} data-action-kind={item.proposal.actionKind} onClick={() => onSelect({ item: item.proposal, kind: "proposal" })} type="button">
<span><Sparkles size={17} /></span>
<span><small>{appliedTeamPlan ? (locale === "zh-CN" ? "团队分配 · 已记录" : "Team assignment · Recorded")
<span><small>{pendingOperation ? t(`proposal.kind.${item.proposal.actionKind}`)
: appliedTeamPlan ? (locale === "zh-CN" ? "团队分配 · 已记录" : "Team assignment · Recorded")
: `${t(`proposal.kind.${item.proposal.actionKind}`)} · ${t(`proposal.status.${item.proposal.status}`)}`}</small><strong>{item.proposal.title}</strong>{item.proposal.impact ? <p>{item.proposal.impact}</p> : null}</span>
<b>{item.proposal.status === "gated" && item.proposal.actionKind !== "operation.execute" ? t("timeline.review") : item.proposal.primaryLabel ?? t("timeline.reviewAndConfirm")}</b>
</button>{showManagerTeamResults && onOpenGoalEvidence && appliedTeamPlan
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,9 @@ export function ContextDrawer({ agents, attentionHistory = [], onSelectAttention
{selection.kind === "proposal" ? (
<>
{selection.item.actionKind === "team.plan" && selection.item.status === "applied" ? <TeamPlanResult proposal={selection.item} t={t} /> : <section className="personal-proposal-card">
<small>{selection.item.actionKind} · {selection.item.status}</small>
<small>{selection.item.reviewPlan?.operationFrame?.kind === "pending"
? t(`proposal.kind.${selection.item.actionKind}`)
: `${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}>{operationUnknown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ const en = {
"proposal.field.operationState": "Operation state",
"proposal.operationState.host_authentication_required": "Confirmed; original-host authentication unavailable",
"proposal.operationState.managed_turn_pending": "Confirmed; waiting for the bound managed Turn",
"proposal.operationState.managed_turn_started": "Native continuation accepted; authorization not yet consumed",
"proposal.operationState.consumed_outcome_pending": "Authorization consumed; waiting for the real result",
"proposal.operationState.submission_unknown": "Result unknown; reconcile the original operation, do not resubmit",
"proposal.field.resultDelivery": "Result delivery",
Expand Down Expand Up @@ -730,6 +731,7 @@ const en = {
"proposal.impact.operation": "The exact terms are read-only here. Confirm or reject the same immutable request in the bound Feishu group; confirmation consumes one canonical claim.",
"proposal.impact.operationAuthorized": "Human confirmation is recorded, but the original host's authenticated tool transport is not connected. Thread flags or environment ids cannot authorize execution. No external result is recorded yet.",
"proposal.impact.operationManagedPending": "Confirmation is bound to the selected managed session and execution profile, not the source conversation. The admitted Turn must consume it once through its owned tool connection. No execution or external result is established yet.",
"proposal.impact.operationManagedStarted": "The bound native host accepted a continuation containing this confirmed operation. This first-start receipt is not proof that the Turn is still running, that authorization was consumed, or that an external effect occurred.",
"proposal.impact.operationConsumed": "The authorization has been consumed. Wait for original external evidence; a retry or lost response must not grant another submission.",
"proposal.impact.operationUnknown": "Submission may have had an external effect. Reconcile the original operation using its evidence; do not resubmit or treat card delivery as execution completion.",
"proposal.primary.apply": "Confirm and apply",
Expand Down Expand Up @@ -1882,6 +1884,7 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"proposal.field.operationState": "操作状态",
"proposal.operationState.host_authentication_required": "已确认,原宿主身份认证尚未接通",
"proposal.operationState.managed_turn_pending": "已确认,等待绑定的受管回合",
"proposal.operationState.managed_turn_started": "原生续接已接受,授权尚未消费",
"proposal.operationState.consumed_outcome_pending": "授权已消费,等待真实结果",
"proposal.operationState.submission_unknown": "结果未知;核对原操作,不可重复提交",
"proposal.field.resultDelivery": "结果回传",
Expand Down Expand Up @@ -1928,6 +1931,7 @@ const zhCN: Record<WorkspaceMessageKey, string> = {
"proposal.impact.operation": "这里仅展示同一份不可变条款。请在已绑定的飞书群确认或拒绝;确认只会消费一个规范 claim。",
"proposal.impact.operationAuthorized": "用户确认已记录,但原宿主的认证工具通道尚未接通。线程参数或环境变量不能授权执行;目前尚无外部执行结果。",
"proposal.impact.operationManagedPending": "批准绑定选定的受管会话和执行配置,不绑定来源对话。通过准入的回合须在自有工具通道上消费一次;目前不代表已执行,也没有外部结果。",
"proposal.impact.operationManagedStarted": "绑定的原生宿主已接受包含本确认请求的续接。首次启动回执不证明回合仍在运行、授权已消费或已有外部效果。",
"proposal.impact.operationConsumed": "授权已消费。等待原始外部证据;重试或响应丢失均不得重新授予提交许可。",
"proposal.impact.operationUnknown": "提交可能已产生外部副作用。须以原始证据核对原操作,不可重提,也不能把卡片投递当作执行完成。",
"proposal.primary.apply": "确认并应用",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,8 @@ function workspaceProposal(proposal: TypedActionProposal, t: WorkspaceTranslate)
? operationFrame?.kind === "pending" && operationFrame.executionState
? t(operationFrame.executionState === "consumed_outcome_pending"
? "proposal.impact.operationConsumed" : operationFrame.executionState === "managed_turn_pending"
? "proposal.impact.operationManagedPending" : "proposal.impact.operationAuthorized")
? "proposal.impact.operationManagedPending" : operationFrame.executionState === "managed_turn_started"
? "proposal.impact.operationManagedStarted" : "proposal.impact.operationAuthorized")
: operationFrame?.kind === "result" && operationFrame.resultKind === "unknown"
? t("proposal.impact.operationUnknown") : t("proposal.impact.operation")
: proposal.action_kind === "team.plan"
Expand Down
47 changes: 43 additions & 4 deletions docs/architecture/rfcs/human-confirmed-domain-operations-v0.md
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,11 @@ The existing Inbox projects canonical locators directly, with recovery first,
`loopx_operation pending` accepts its bound cursor; the CLI projection uses
`manager-inbox read --operation-cursor CURSOR`. New/changed work restarts
without a cursor. Reading or exhausting a page does not resolve obligations.
The owned native tool applies the same exact execution-subject filter as Turn
startup before pagination. Current approvals for another Todo/session/profile
of the same Agent cannot appear on that task's page or starve its continuations;
its cursor cannot be reused by another execution subject. The existing TS inbox
owner makes these decisions; this is not a separate host-owned inbox.

The shared TypeScript operation frame shows executor, pinned model/effort,
Goal/Agent/Todo scope, optional source context, and distinct states: confirmed
Expand Down Expand Up @@ -445,10 +450,44 @@ remain fail-closed before private reads or writes, even with matching
`CODEX_THREAD_ID`, route flags, self-signed proof or an older runtime's actor
success. No proof-import shortcut is exposed.

Immediate confirmation-triggered host wakeup is not implemented:
`host_delivery: "not_attempted"` remains truthful. Continue through the
existing admitted Turn/delegation route; later durable wakeup must reuse its
original scheduling/session owner, not start a parallel resumed executor.
An admitted operation-enabled Turn now automatically includes canonical
confirmed-operation locators for its exact Goal/Agent/Todo/session/profile,
filtered before inbox pagination. After the native `turn/start` response is
accepted, the existing action store records immutable first-start evidence:
confirmation event/time, claim, LoopX Turn key, native Turn and acceptance time.
`host_delivery: "native_start_accepted"` means that observation only; it grants
no consumption or effect authority and does not claim the Turn is still live.
Receipt failure aborts before operation-tool dispatch; later Turns preserve the
first observation. CLI/Inbox, Dashboard and Lark distinguish accepted native
continuation from consumed authorization and an actual outcome.

An authenticated confirmation callback may now request one continuation through
the existing delegation owner, **only with a separate, default-off operator
launch grant**. The grant selects one existing requester/binding, not a model,
workspace or executor supplied by the card. The operation owner checks exact
Goal/Agent/Todo/session/profile, confirmation lifetime and unconsumed state.
The ordinary Turn still owns quota, lease, validation and native startup; its
native adapter rechecks the complete effective profile before resuming the
original session. A new/replacement session is refused. Confirmation does not
grant launch configuration or domain execution authority.

The canonical operation id determines one durable delegation identity. Callback
replays read its locator without another spawn or artifact validation. A lost
launch acknowledgement remains an original-journal recovery case; callbacks
do not auto-resume an uncertain worker. Removing the operator grant is read at
the next callback boundary. Already started work is not retroactively cancelled.
`delegation_requested` does not prove native start, validated completion or
source delivery; `host_delivery` remains `"not_attempted"` until native acceptance.
See [operator activation](../../reference/local-delegation.md#confirmed-operation-callback-continuation).

File/SQLite qualification uses authenticated synthetic confirmation fixtures,
the real detached delegation worker and CLI/Turn path, and a synthetic native
transport. It proves original-session startup without consumption or a domain
effect; deliberate waiting is not accepted Todo completion. Genuine Lark/model
and financial probes have not been run for this increment. Frontend grant
editing and authenticated result return to the original source audience remain
separate, **partial-delivery** obligations; current grant activation is through
the operator-owned collector configuration, not a new UI authority.
Before claiming the investment minimum loop, still prove installation,
genuine human approval, bound native consumption, domain preflight and
original-system evidence, accepted result and original-card/audience readback.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,10 @@ executor revision、consumption ID、核验投影、`simulation: false`、
及独立 operation cursor。`loopx_operation pending` 接受绑定游标;CLI 投影用
`manager-inbox read --operation-cursor CURSOR`。新增/改变工作应无游标重读,
读完一页或遍历结束不代表义务已解决。
自有原生工具与 Turn 启动使用相同的精确执行主体过滤,并在分页前生效。
同一 Agent 另一 Todo/session/profile 的当前批准不能出现在本任务页面或挤占其
续接信息;游标也不能跨执行主体复用。判定仍由既有 TS Inbox owner 负责,
不新建宿主自有 Inbox。

共享 TS 操作 frame 展示执行者、固定模型/思考深度、Goal/Agent/Todo 范围、可选来源
上下文,并区分:已确认但外接认证不可用、已确认待绑定受管回合、已消费待证据、未知须
Expand All @@ -348,9 +352,33 @@ context 调用,结果均由既有 typed result validator 接受)、规范
私有读写前拒绝,即使 `CODEX_THREAD_ID`、路由、自签 proof 完全匹配或旧运行时
意外返回 actor 成功,也没有 proof-import 捷径。

本切片不实现确认后的即时宿主唤醒,`host_delivery: "not_attempted"` 保持真实。
沿既有已准入 Turn/delegation 续接;后续持久唤醒复用其调度/session owner,
不启动平行 resumed 执行者。宣称投研最小闭环前,仍须证明安装、真实用户批准、
启用 operation 的已准入 Turn 自动携带其精确 Goal/Agent/Todo/session/profile 的
规范确认请求定位信息,并在 Inbox 分页前过滤范围。仅在原生 `turn/start` 返回接受后,
既有 action store 才记录不可覆盖的首次启动证据:确认事件/时间、claim、LoopX Turn key、
原生 Turn 和接受时间。`host_delivery: "native_start_accepted"` 只证明该观察,
不授予消费或外部效果权限,也不声称回合仍在运行。回执失败时先停止、不分发 operation 工具;
后续回合保留首次观察。CLI/Inbox、Dashboard 和 Lark 区分原生续接接受、授权消费和真实结果。

认证确认 callback 现在可通过既有 delegation owner 请求一次续跑,前提是具有
**独立且默认关闭的 operator 启动 grant**。grant 指定已有 requester/binding,
不采用卡片提供的模型、工作树或执行者。操作 owner 核对精确
Goal/Agent/Todo/session/profile、确认期限和未消费状态;普通 Turn 仍负责 quota、
租约、验收及原生启动。原生适配器在恢复前重验完整生效配置,拒绝新建/替换会话。
用户确认不授予启动配置或垂域执行权限。

规范 operation id 固定唯一持久 delegation 身份。callback 重放只读原定位信息,
不再次 spawn 或运行产物验收;丢失启动 ACK 仍由原 journal 恢复,不在回调自动续跑
不确定的 worker。移除 operator grant 会在下一次 callback 边界读回生效,
不追溯取消已经开始的工作。`delegation_requested` 不证明原生启动、完成验收或
来源送达;原生接受前 `host_delivery: "not_attempted"` 保持真实。
启用方式见[原配置入口](../../reference/local-delegation.md#confirmed-operation-callback-continuation)。

File/SQLite 资格化使用合成认证确认夹具、真实 detached delegation worker 与
CLI/Turn 路径,以及合成原生传输;证明原会话启动,但未消费批准或执行垂域操作。
夹具故意等待,不冒充 Todo 完成。本增量未跑真实 Lark/模型或金融探针。
前端 grant 编辑及经认证的原来源受众结果回传仍为独立的**部分交付**义务;
目前只能通过 operator-owned collector 配置启用,不另建 UI 状态权威。
宣称投研最小闭环前,仍须证明安装、真实用户批准、
绑定原生消费、垂域提交前检查与原系统证据、结果验收及原卡/受众读回。
Core PR 仍须 owner review,不在合并前自行安装。

Expand Down
Loading
Loading