Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
dd23a62
feat(turn-driver): read Turn lane liveness without taking the lane
songoow Sep 29, 2026
0b1a93f
feat(delegation): add stopped observation and typed stop decision
songoow Sep 29, 2026
62d4c92
feat(delegation): stop delegated members with acknowledged, settled r…
songoow Sep 29, 2026
654c1fb
feat(delegation): expose stop through the CLI and MCP surfaces
songoow Sep 29, 2026
f9356e5
test(delegation): cover stop receipts, fencing and refused resume
songoow Sep 29, 2026
f255345
docs(delegation): document stopping a member and reading its receipt
songoow Sep 29, 2026
9a40596
fix(delegation): settle a stop from holder records, never by taking a…
songoow Sep 29, 2026
5e7b7bf
chore(census): follow registry reads moved on main
songoow Sep 29, 2026
5d67e47
fix(delegation): settle a stop only after the native Host and its gro…
songoow Sep 30, 2026
fd49df6
test(delegation): prove a stop settles only after the owned Host exits
songoow Sep 30, 2026
226a664
docs(delegation): state what a stop receipt proves about the native Host
songoow Sep 30, 2026
609530d
Merge remote-tracking branch 'upstream/main' into review/pr-5308
songoow Sep 30, 2026
796f688
Merge remote-tracking branch 'origin/main' into codex/delegation-stop
songoow Sep 30, 2026
01be96c
fix(delegation): give a stop a boundary against its effects, its leas…
songoow Sep 30, 2026
0044268
fix(delegation): take the lease obligation from the operation record
songoow Sep 30, 2026
8468544
Merge remote-tracking branch 'origin/main' into codex/delegation-stop
songoow Sep 30, 2026
4ad80a0
Merge origin/main into delegation stop repair
songoow Oct 1, 2026
26ccc3e
Merge branch 'codex/review-repair-5308' into codex/pr-repair-5308-final
songoow Oct 1, 2026
7f90c62
fix(delegation): fence recovered completion against concurrent stop
songoow Oct 1, 2026
9c64053
fix(workspace): report stopped delegation records without claiming drain
songoow Oct 1, 2026
91a1c86
Merge commit 'eced3985d7abc39ad93eb773f87ba0adaeb5b066' into codex/pr…
songoow Oct 1, 2026
fb553ce
Merge branch 'main' of https://github.com/loopx-project/loopx into co…
songoow Oct 2, 2026
0ec7c16
fix(dashboard): give the recorded stop its own pulse label
songoow Oct 2, 2026
ccd8d65
Merge branch 'main' of https://github.com/loopx-project/loopx into co…
songoow Oct 2, 2026
dfb508d
Merge remote-tracking branch 'origin/main' into codex/pr-5308-repair
songoow Oct 2, 2026
80f5490
fix(delegation): restore the dashboard build and the spawned-callback…
songoow Oct 2, 2026
8c10912
fix(delegation): release a stopped member's lease by its execution id…
songoow Oct 2, 2026
29fe0c9
Merge remote-tracking branch 'origin/main' into codex/pr-5308-repair
songoow Oct 2, 2026
95f55c1
refactor(delegation): move stop lease release into its own module
songoow Oct 2, 2026
cd1d3b1
fix(host): run the bridge on the caller's environment, not the ambien…
songoow Oct 2, 2026
626fd30
Merge remote-tracking branch 'origin/main' into codex/pr-5308-repair
songoow Oct 2, 2026
cd892c9
Merge latest main into delegation stop repair
songoow Oct 2, 2026
afb7616
fix(delegation): prove nested Host drain before releasing its lease
songoow Oct 2, 2026
0b78b3d
test(delegation): cover unavailable nested supervisors and drain attr…
songoow Oct 2, 2026
89dc8b9
docs(delegation): explain nested drain and explicit stop recovery
songoow Oct 2, 2026
229183d
Merge latest main and preserve delegation lease regressions
songoow Oct 3, 2026
2add900
fix(delegation): reject unsupported stop before cancellation effects
songoow Oct 3, 2026
0c7037e
docs(delegation): clarify side-effect-free platform refusal
songoow Oct 3, 2026
ddd1411
fix(delegation): refuse unsupported stop across the Host launch window
songoow Oct 3, 2026
071d2ab
docs(delegation): explain platform refusal before Host attribution
songoow Oct 3, 2026
c5ef416
refactor(delegation): isolate worker stop signal adaptation
songoow Oct 3, 2026
13f4c93
test(delegation): isolate cached and child Effect runtime routes
songoow Oct 3, 2026
5cb7424
fix(delegation): preserve the first lease supervision failure
songoow Oct 3, 2026
694866a
docs(delegation): explain lease failure readback boundaries
songoow Oct 3, 2026
368c78a
Merge branch 'main' into codex/delegation-stop
songoow Oct 3, 2026
1c1ce46
fix(delegation): retain the latest proved expiry through final readback
songoow Oct 3, 2026
ff883be
test(delegation): qualify deadlines at their actual lifecycle boundaries
songoow Oct 3, 2026
cac72ec
docs(delegation): clarify expiry supervision after Host return
songoow Oct 3, 2026
89af443
Merge commit '58574643c0717508ec7cb3e2c35415566bbf720c' into codex/pr…
songoow Oct 3, 2026
bdbd440
test(delegation): retire fixture-owned Effect runtimes
songoow Oct 3, 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
8 changes: 6 additions & 2 deletions apps/presentation/dashboard/src/data/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1108,14 +1108,17 @@ export function readManagedGoalResult(goalId: string, todoId: string) {
);
}
export type DelegationState = "unavailable" | "accepted" | "rejected" | "recovery_required"
| "executing" | "validating" | "dispatched" | "unknown";
| "stopped" | "executing" | "validating" | "dispatched" | "unknown";
type DelegationStateFacts = {status: string; worker_active?: boolean; recovery_required: boolean | null};
// Keep inventory and selected-operation labels consistent; unknown states stay unknown.
// "executing" and "validating" require an active worker observation, never the stored status alone.
export function delegationState(row: DelegationStateFacts): DelegationState {
if (row.status === "unavailable") return "unavailable";
if (row.status === "accepted") return "accepted";
if (row.status === "rejected") return "rejected";
// A recorded stop precedes recovery: only the separate stop receipt proves
// the original execution released its Host group, so the stored status alone
// must not be read as work still needing recovery.
if (row.status === "stopped") return "stopped";
if (row.recovery_required) return "recovery_required";
if (row.status === "running" && row.worker_active) return "executing";
if (row.status === "turn_returned" && row.worker_active) return "validating";
Expand All @@ -1126,6 +1129,7 @@ const DELEGATION_STATE_LABELS: Record<DelegationState, {zh: string; en: string}>
unavailable: {zh: "无法核验", en: "Unavailable"},
accepted: {zh: "已通过当前验收", en: "Currently accepted"},
rejected: {zh: "未通过验收", en: "Rejected"},
stopped: {zh: "停止已登记", en: "Stop recorded"},
recovery_required: {zh: "需要恢复原执行", en: "Original execution needs recovery"},
executing: {zh: "执行中", en: "Executing"},
validating: {zh: "正在验收", en: "Validating"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@ import {DelegationPreflightStatus} from "./delegation-preflight-status";

type Member = {id: string; agent_id: string; todo_id: string};
type DelegationRecord = DelegationInventory["items"][number];
type PulseBucket = "executing" | "validating" | "accepted" | "attention" | "dispatched" | "unknown";
type PulseBucket = "executing" | "validating" | "accepted" | "attention" | "stopped" | "dispatched" | "unknown";
type CheckTone = "unchecked" | "ready" | "unverified" | "blocked";

const PULSE_BUCKETS: Record<DelegationState, PulseBucket> = {
executing: "executing", validating: "validating", accepted: "accepted",
rejected: "attention", recovery_required: "attention", unavailable: "attention",
dispatched: "dispatched", unknown: "unknown",
// A recorded stop is not proof its Host group released; it is its own bucket.
stopped: "stopped", dispatched: "dispatched", unknown: "unknown",
};
const PULSE_LABELS: Record<PulseBucket, {zh: string; en: string}> = {
executing: {zh: "执行中", en: "Executing"},
validating: {zh: "正在验收", en: "Validating"},
accepted: {zh: "已通过", en: "Accepted"},
attention: {zh: "需要处理", en: "Needs attention"},
stopped: {zh: "已登记停止", en: "Stop on record"},
dispatched: {zh: "等待回读", en: "Awaiting readback"},
unknown: {zh: "状态未知", en: "Unknown"},
};
Expand All @@ -41,6 +43,8 @@ function StateIcon({state}: {state: DelegationState | PulseBucket | CheckTone})
if (state === "validating") return <Loader2 aria-hidden="true" size={14}/>;
if (state === "accepted" || state === "ready") return <CheckCircle2 aria-hidden="true" size={14}/>;
if (state === "dispatched") return <Clock3 aria-hidden="true" size={14}/>;
// A recorded stop is an explicit terminal marker, not an unknown to triage.
if (state === "stopped") return <CircleDashed aria-hidden="true" size={14}/>;
if (state === "unverified") return <ShieldCheck aria-hidden="true" size={14}/>;
if (state === "unchecked") return <CircleDashed aria-hidden="true" size={14}/>;
if (state === "unknown") return <CircleHelp aria-hidden="true" size={14}/>;
Expand Down Expand Up @@ -130,7 +134,7 @@ export function GoalTeamWork({sessionId, members, zh, canMessage, ingress}: {ses
else unboundRecords.push(row);
}
const pulse = items.reduce((counts, row) => {counts[PULSE_BUCKETS[delegationState(row)]] += 1; return counts;},
{executing: 0, validating: 0, accepted: 0, attention: 0, dispatched: 0, unknown: 0} as Record<PulseBucket, number>);
{executing: 0, validating: 0, accepted: 0, attention: 0, stopped: 0, dispatched: 0, unknown: 0} as Record<PulseBucket, number>);
const visibleBuckets = (Object.keys(PULSE_LABELS) as PulseBucket[]).filter(bucket => bucket !== "unknown" || pulse.unknown > 0);

function renderRecord(row: DelegationRecord, showAgent: boolean) {
Expand Down
9 changes: 7 additions & 2 deletions docs/reference/goal-chat-continuation.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,10 @@ messages; images use the ordinary conversation after pausing.
requires the Chat service to be running; stopping it leaves intents pending.
- To roll back, pause/close the Chat service before installing an older build.
Disabling mode or deleting a binding does not cancel already admitted children;
use their own execution/recovery controls and retain their evidence.
stop one with `loopx delegation stop --execute` (or `stop_delegation`), read
its receipt, and retain its evidence. Only `settled` proves the worker
acknowledged and released its locks and its native host exited; stopped work
needs a new operation id.

The ordinary native command path also remains available without delegation:

Expand Down Expand Up @@ -175,6 +178,8 @@ Turn 保持 `wake_dispatch_pending`;中断派发后仍处于 queued 的 Turn
协调员保留只读沙箱,成员权限来自各自执行绑定,不继承管家的扩大权限。
成员通过验收与协调员报告、整个 Goal 验收分别显示;本模式不直接完成报告 Todo
或整个 Goal。额度是含历史用量的总量,正在执行的请求可能超额,成员另行计量。
回滚旧版本前先暂停或关闭 Chat 服务;退出或撤销绑定不自动取消已启动的成员。
回滚旧版本前先暂停或关闭 Chat 服务;退出或撤销绑定不自动取消已启动的成员,
用 `loopx delegation stop --execute`(或 `stop_delegation`)停止单个成员并阅读回执:
只有 `settled` 证明 worker 已确认并释放锁且原生 host 已退出;已停止的工作需要新的 operation id。
此按钮目前限本机 managed Codex Goal 对话,不宣称 Lark、挂接会话或其他主力
驱动等价。可用下方示例准备一次隔离的本地 DSH+云端 Ark 协作。
Loading
Loading