mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-20 12:13:38 +08:00
Refine course progression and runtime safety
This commit is contained in:
@@ -12,7 +12,7 @@ const visualizations: Record<
|
||||
s03: lazy(() => import("./s03-permission")),
|
||||
s04: lazy(() => import("./s04-hooks")),
|
||||
s05: lazy(() => import("./s03-todo-write")),
|
||||
s06: lazy(() => import("./s04-subagent")),
|
||||
s06: lazy(() => import("./s06-subagent")),
|
||||
s07: lazy(() => import("./s05-skill-loading")),
|
||||
s08: lazy(() => import("./s06-context-compact")),
|
||||
s09: lazy(() => import("./s09-memory")),
|
||||
|
||||
@@ -29,7 +29,7 @@ const CHILD_WORK_MESSAGES: MessageBlock[] = [
|
||||
|
||||
const SUMMARY_BLOCK: MessageBlock = {
|
||||
id: "summary",
|
||||
label: "summary: 3 tests written, all passing",
|
||||
label: "final: 3 tests written, all passing",
|
||||
color: "bg-teal-500",
|
||||
};
|
||||
|
||||
@@ -40,9 +40,9 @@ const STEPS = [
|
||||
"The parent agent has accumulated messages from the conversation.",
|
||||
},
|
||||
{
|
||||
title: "Spawn Subagent",
|
||||
title: "Run Subagent",
|
||||
description:
|
||||
"Task tool creates a child with fresh messages[]. Only the task description is passed.",
|
||||
"Task runs a nested agent loop with fresh messages[]. Only the task prompt is passed.",
|
||||
},
|
||||
{
|
||||
title: "Independent Work",
|
||||
@@ -50,19 +50,19 @@ const STEPS = [
|
||||
"The child has its own context. It doesn't see the parent's history.",
|
||||
},
|
||||
{
|
||||
title: "Compress Result",
|
||||
title: "Final Response",
|
||||
description:
|
||||
"The child's full conversation compresses into one summary.",
|
||||
"The subagent finishes with a text response.",
|
||||
},
|
||||
{
|
||||
title: "Return Summary",
|
||||
title: "Return Final Text",
|
||||
description:
|
||||
"Only the summary returns. The child's full context is discarded.",
|
||||
"The final text becomes the task tool result in the parent conversation.",
|
||||
},
|
||||
{
|
||||
title: "Clean Context",
|
||||
title: "Parent Continues",
|
||||
description:
|
||||
"The parent gets a clean summary without context bloat. This is fresh-context isolation via messages[].",
|
||||
"The parent continues without copying the subagent's intermediate messages.",
|
||||
},
|
||||
];
|
||||
|
||||
@@ -112,12 +112,12 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
>
|
||||
{/* Main layout: two containers side by side */}
|
||||
<div className="relative flex gap-4" style={{ minHeight: 340 }}>
|
||||
{/* Parent Process Container */}
|
||||
{/* Parent agent loop */}
|
||||
<div className="flex-1 rounded-xl border-2 border-blue-300 bg-blue-50/50 p-4 dark:border-blue-700 dark:bg-blue-950/20">
|
||||
<div className="mb-3 flex items-center gap-2">
|
||||
<div className="h-3 w-3 rounded-full bg-blue-500" />
|
||||
<span className="text-sm font-bold text-blue-700 dark:text-blue-300">
|
||||
Parent Process
|
||||
Parent agent loop
|
||||
</span>
|
||||
</div>
|
||||
<div className="mb-2 font-mono text-xs text-zinc-400">
|
||||
@@ -146,7 +146,7 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
transition={{ delay: 0.5 }}
|
||||
className="mt-3 rounded border border-blue-200 bg-white/60 px-2 py-1 text-center text-xs text-blue-600 dark:border-blue-700 dark:bg-blue-950/30 dark:text-blue-300"
|
||||
>
|
||||
3 original + 1 summary = clean context
|
||||
parent receives one task result
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
@@ -161,12 +161,12 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
className="rounded bg-zinc-200 px-2 py-1 text-center font-mono text-[10px] text-zinc-500 dark:bg-zinc-700 dark:text-zinc-400"
|
||||
style={{ writingMode: "vertical-rl", textOrientation: "mixed" }}
|
||||
>
|
||||
ISOLATION
|
||||
MESSAGE BOUNDARY
|
||||
</motion.div>
|
||||
<div className="h-full w-px border-l-2 border-dashed border-zinc-300 dark:border-zinc-600" />
|
||||
</div>
|
||||
|
||||
{/* Child Process Container */}
|
||||
{/* Nested subagent loop */}
|
||||
<div
|
||||
className={`flex-1 rounded-xl border-2 p-4 transition-colors duration-300 ${
|
||||
showChildEmpty
|
||||
@@ -195,7 +195,7 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
: "text-purple-700 dark:text-purple-300"
|
||||
}`}
|
||||
>
|
||||
Child Process
|
||||
Subagent loop
|
||||
</span>
|
||||
</div>
|
||||
<div className="mb-2 font-mono text-xs text-zinc-400">
|
||||
@@ -209,7 +209,7 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
className="flex h-24 items-center justify-center rounded-lg border border-dashed border-zinc-200 dark:border-zinc-700"
|
||||
>
|
||||
<span className="text-xs text-zinc-400">
|
||||
not yet spawned
|
||||
not yet started
|
||||
</span>
|
||||
</motion.div>
|
||||
)}
|
||||
@@ -237,7 +237,7 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
className="mt-3 rounded border border-amber-300 bg-amber-50 px-2 py-1 text-center text-xs text-amber-700 dark:border-amber-600 dark:bg-amber-900/20 dark:text-amber-300"
|
||||
>
|
||||
Compressing full context into summary...
|
||||
Preparing final response...
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
@@ -247,7 +247,7 @@ export default function SubagentIsolation({ title }: { title?: string }) {
|
||||
animate={{ opacity: 1 }}
|
||||
className="mt-3 rounded border border-red-200 bg-red-50 px-2 py-1 text-center text-xs text-red-500 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400"
|
||||
>
|
||||
context discarded
|
||||
local messages released
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
@@ -19,32 +19,32 @@ const STEPS = [
|
||||
{
|
||||
title: "Confirm a Small Team",
|
||||
desc: "The Lead proposes focused roles and waits for the user before starting persistent teammates.",
|
||||
event: "user confirmed: backend + tests",
|
||||
event: "lead proposes: backend + tests",
|
||||
},
|
||||
{
|
||||
title: "Deliver a Typed Assignment",
|
||||
desc: "The runtime writes the assignment to a mailbox and correlates plan approval with a request id.",
|
||||
event: "plan_response(req_7, approved=true)",
|
||||
title: "Claim Atomically",
|
||||
desc: "A ready task moves to one owner while the task-store file lock protects the persisted transition.",
|
||||
event: "task_store_lock: task_...0042 -> backend",
|
||||
},
|
||||
{
|
||||
title: "Idle Teammates Scan the Board",
|
||||
desc: "A teammate with no direct message looks only for pending, unowned work whose dependencies are complete.",
|
||||
event: "scan_ready_tasks(backend) -> task_auth",
|
||||
},
|
||||
{
|
||||
title: "Claim Under One Lock",
|
||||
desc: "Ownership and status change atomically, so another teammate cannot take the same task.",
|
||||
event: "task_lock: task_auth -> backend",
|
||||
title: "Require and Review a Plan",
|
||||
desc: "The gate is active before the teammate starts; the Lead reviews the typed request for this task and work version.",
|
||||
event: "review_plan(req_000007, approve=true)",
|
||||
},
|
||||
{
|
||||
title: "Route Tools to the Task Directory",
|
||||
desc: "The claimed task carries its worktree binding; bash, read, and write derive their cwd from that record.",
|
||||
event: "cwd -> .worktrees/auth-refactor",
|
||||
},
|
||||
{
|
||||
title: "Execute the Approved Work",
|
||||
desc: "Mutating tools run only after the current assignment's plan is approved.",
|
||||
event: "bash / write: allowed",
|
||||
},
|
||||
{
|
||||
title: "Return the Result, Keep the Teammate",
|
||||
desc: "The runtime delivers the result to the Lead and moves the teammate back to IDLE for newly ready work.",
|
||||
event: "result(auth complete) -> idle_notification",
|
||||
desc: "Completion keeps the task cwd through the turn; IDLE releases the assignment and keeps the teammate available.",
|
||||
event: "complete -> result -> IDLE",
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -98,7 +98,7 @@ function RuntimePanel({ step }: { step: number }) {
|
||||
</span>
|
||||
<span className="text-zinc-500 dark:text-zinc-400">Protocol</span>
|
||||
<span className="break-all font-mono text-zinc-700 dark:text-zinc-300">
|
||||
{step < 1 ? "-" : "request_id=req_7"}
|
||||
{step < 2 ? "-" : "request_id=req_000007"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -107,10 +107,10 @@ function RuntimePanel({ step }: { step: number }) {
|
||||
<span className="break-words leading-relaxed">
|
||||
{step === 0
|
||||
? "No mailbox is created before confirmation."
|
||||
: step === 1
|
||||
? "Assignment and plan approval travel through typed messages."
|
||||
: step === 2
|
||||
? "The approval is tied to the claimed task and work version."
|
||||
: step === 5
|
||||
? "The result wakes the Lead; IDLE is a reusable state."
|
||||
? "The result wakes the Lead; IDLE releases the cwd lease."
|
||||
: "The runtime owns delivery while the teammate works."}
|
||||
</span>
|
||||
</div>
|
||||
@@ -119,8 +119,8 @@ function RuntimePanel({ step }: { step: number }) {
|
||||
}
|
||||
|
||||
function TaskPanel({ step }: { step: number }) {
|
||||
const status = step < 3 ? "pending" : step < 5 ? "in_progress" : "completed";
|
||||
const owner = step < 3 ? "-" : "backend";
|
||||
const status = step < 1 ? "pending" : step < 5 ? "in_progress" : "completed";
|
||||
const owner = step < 1 ? "-" : "backend";
|
||||
const tone = status === "pending" ? "zinc" : status === "in_progress" ? "amber" : "emerald";
|
||||
|
||||
return (
|
||||
@@ -135,7 +135,7 @@ function TaskPanel({ step }: { step: number }) {
|
||||
|
||||
<div className="mt-4 rounded-md border border-zinc-200 p-3 dark:border-zinc-700">
|
||||
<div className="font-mono text-[11px] text-zinc-500 dark:text-zinc-400">
|
||||
task_auth
|
||||
task_1712345678_0042
|
||||
</div>
|
||||
<div className="mt-1 text-sm font-semibold text-zinc-900 dark:text-zinc-100">
|
||||
Refactor authentication
|
||||
@@ -151,18 +151,18 @@ function TaskPanel({ step }: { step: number }) {
|
||||
<div
|
||||
className={cn(
|
||||
"mt-3 flex min-h-[56px] items-center gap-2 rounded-md border px-3 py-2 text-xs",
|
||||
step === 2 || step === 3
|
||||
step === 1
|
||||
? "border-amber-300 bg-amber-50 text-amber-800 dark:border-amber-800 dark:bg-amber-950/30 dark:text-amber-200"
|
||||
: "border-zinc-200 bg-zinc-50 text-zinc-600 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-300"
|
||||
)}
|
||||
>
|
||||
{step < 3 ? <Search size={15} className="shrink-0" /> : <LockKeyhole size={15} className="shrink-0" />}
|
||||
{step < 1 ? <Search size={15} className="shrink-0" /> : <LockKeyhole size={15} className="shrink-0" />}
|
||||
<span className="break-words">
|
||||
{step < 2
|
||||
{step < 1
|
||||
? "Waiting for the teammate loop."
|
||||
: step === 2
|
||||
? "Ready filter: pending + unowned + dependencies complete."
|
||||
: "The claim check and update share one lock."}
|
||||
: step === 1
|
||||
? "The claim check and update share one lock."
|
||||
: "The claimed task remains owned through the work turn."}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -170,7 +170,8 @@ function TaskPanel({ step }: { step: number }) {
|
||||
}
|
||||
|
||||
function WorkspacePanel({ step }: { step: number }) {
|
||||
const bound = step >= 4;
|
||||
const routed = step >= 3 && step < 5;
|
||||
const retained = step >= 5;
|
||||
|
||||
return (
|
||||
<div className="min-h-[250px] rounded-lg border border-zinc-200 bg-white p-3 dark:border-zinc-700 dark:bg-zinc-900">
|
||||
@@ -179,14 +180,17 @@ function WorkspacePanel({ step }: { step: number }) {
|
||||
<GitBranch size={16} className="shrink-0 text-emerald-500" />
|
||||
<span>Task directory</span>
|
||||
</div>
|
||||
<StateBadge label={bound ? "bound" : "reserved"} tone={bound ? "emerald" : "zinc"} />
|
||||
<StateBadge
|
||||
label={routed ? "active cwd" : retained ? "binding retained" : "reserved"}
|
||||
tone={routed ? "emerald" : "zinc"}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 space-y-2">
|
||||
<div
|
||||
className={cn(
|
||||
"rounded-md border p-3 transition-colors",
|
||||
!bound
|
||||
!routed
|
||||
? "border-blue-300 bg-blue-50 dark:border-blue-800 dark:bg-blue-950/30"
|
||||
: "border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-800"
|
||||
)}
|
||||
@@ -199,11 +203,11 @@ function WorkspacePanel({ step }: { step: number }) {
|
||||
</div>
|
||||
</div>
|
||||
<motion.div
|
||||
animate={bound ? { y: [0, -2, 0] } : { y: 0 }}
|
||||
transition={{ duration: 0.8, repeat: bound ? Infinity : 0 }}
|
||||
animate={routed ? { y: [0, -2, 0] } : { y: 0 }}
|
||||
transition={{ duration: 0.8, repeat: routed ? Infinity : 0 }}
|
||||
className={cn(
|
||||
"rounded-md border p-3 transition-colors",
|
||||
bound
|
||||
routed
|
||||
? "border-emerald-300 bg-emerald-50 dark:border-emerald-800 dark:bg-emerald-950/30"
|
||||
: "border-dashed border-zinc-300 bg-white dark:border-zinc-700 dark:bg-zinc-900"
|
||||
)}
|
||||
@@ -212,14 +216,24 @@ function WorkspacePanel({ step }: { step: number }) {
|
||||
.worktrees/auth-refactor
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] text-zinc-500 dark:text-zinc-400">
|
||||
{bound ? "bash / read / write cwd" : "task.worktree binding"}
|
||||
{routed
|
||||
? "bash / read / write cwd"
|
||||
: retained
|
||||
? "task binding remains after IDLE"
|
||||
: "task.worktree binding"}
|
||||
</div>
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 flex items-center gap-2 text-xs text-zinc-600 dark:text-zinc-300">
|
||||
{bound ? <Terminal size={15} /> : <GitBranch size={15} />}
|
||||
<span>{bound ? "Tools follow the claimed task." : "No implicit directory switching."}</span>
|
||||
{routed ? <Terminal size={15} /> : <GitBranch size={15} />}
|
||||
<span>
|
||||
{routed
|
||||
? "Tools follow the claimed task."
|
||||
: retained
|
||||
? "IDLE released active tool routing."
|
||||
: "No implicit directory switching."}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,43 +4,43 @@
|
||||
{
|
||||
"id": "fresh-subagent-context",
|
||||
"title": "Subagents Start with Fresh Messages",
|
||||
"description": "The child agent receives only the delegated prompt. This isolates exploratory work and prevents the parent context from filling with every intermediate tool result.",
|
||||
"alternatives": "Sharing the full parent history gives more context, but it defeats the purpose of delegation as context isolation.",
|
||||
"description": "The subagent receives only the delegated prompt. Its intermediate tool calls stay in a separate message list instead of being copied into the parent conversation.",
|
||||
"alternatives": "Passing the parent history would give the subagent more context, but would no longer demonstrate a fresh-message boundary.",
|
||||
"zh": {
|
||||
"title": "子代理从全新 Messages 开始",
|
||||
"description": "子代理只收到被委派的 prompt。这样探索性工作被隔离,父上下文不会塞满每个中间工具结果。"
|
||||
"description": "子 Agent 只收到被委派的 prompt。中间工具调用留在另一份消息列表中,不复制到父对话。"
|
||||
},
|
||||
"ja": {
|
||||
"title": "サブエージェントは新しい messages で始まる",
|
||||
"description": "子エージェントは委任された prompt だけを受け取ります。探索作業を隔離し、親コンテキストが中間 tool result で膨らむのを防ぎます。"
|
||||
"description": "サブエージェントは委任された prompt だけを受け取る。中間ツール呼び出しは別のメッセージリストに残り、親会話へコピーされない。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "summary-only-return",
|
||||
"title": "Only the Summary Returns to the Parent",
|
||||
"description": "The parent receives a compact final answer, not the child's full transcript. That gives delegation a predictable context cost.",
|
||||
"alternatives": "Returning the full transcript can help debugging, but it makes large subagent runs expensive to continue.",
|
||||
"title": "Only the Final Text Returns to the Parent",
|
||||
"description": "The parent receives the subagent's final text as the task result, not the subagent's full message list.",
|
||||
"alternatives": "Returning the full message list would expose more detail, but it would remove the boundary shown in this lesson.",
|
||||
"zh": {
|
||||
"title": "只有摘要返回父循环",
|
||||
"description": "父循环收到的是压缩后的最终答案,而不是子代理的完整 transcript。这样委派的上下文成本可预测。"
|
||||
"title": "只有最终文本返回父循环",
|
||||
"description": "父循环收到的是作为 task 结果返回的最终文本,而不是子 Agent 的完整消息列表。"
|
||||
},
|
||||
"ja": {
|
||||
"title": "親に戻るのは要約だけ",
|
||||
"description": "親が受け取るのは子の完全な transcript ではなく、圧縮された最終回答です。委任のコンテキストコストを予測可能にします。"
|
||||
"title": "親に戻るのは最終テキストだけ",
|
||||
"description": "親が受け取るのは task result となる最終テキストであり、サブエージェントの完全なメッセージリストではない。"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "no-recursive-task-tool",
|
||||
"title": "Subagents Cannot Spawn Subagents",
|
||||
"description": "The child tool set omits task, preventing recursive delegation from exploding. The lesson keeps isolation visible before adding richer team behavior later.",
|
||||
"alternatives": "Allowing recursion is powerful, but much harder to bound and explain.",
|
||||
"title": "The Subagent Has No Task Tool",
|
||||
"description": "The subagent tool set omits task, so this lesson has one delegation level.",
|
||||
"alternatives": "Recursive delegation is possible, but requires additional lifecycle and limit controls not introduced here.",
|
||||
"zh": {
|
||||
"title": "子代理不能再创建子代理",
|
||||
"description": "子代理工具集中不包含 task,避免递归委派失控。课程先把隔离讲清楚,再在后续章节加入更复杂团队行为。"
|
||||
"title": "子 Agent 没有 task 工具",
|
||||
"description": "子 Agent 的工具集中不包含 task,因此本章只有一层委派。"
|
||||
},
|
||||
"ja": {
|
||||
"title": "サブエージェントはさらにサブエージェントを作れない",
|
||||
"description": "子のツールセットから task を外し、再帰的委任の爆発を防ぎます。まず隔離を明確にし、後の章でより豊かなチーム動作を扱います。"
|
||||
"title": "サブエージェントに task ツールはない",
|
||||
"description": "サブエージェントのツールセットに task はなく、本章の委任は 1 階層となる。"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -578,7 +578,7 @@ const CURRENT_FLOW_OVERRIDES: Record<string, FlowDefinition> = {
|
||||
{ id: "llm", label: "LLM Call", type: "process", x: COL_CENTER, y: 120 },
|
||||
{ id: "tool", label: "tool_use?", type: "decision", x: COL_CENTER, y: 210 },
|
||||
{ id: "todo", label: "todo_write?", type: "decision", x: COL_LEFT, y: 310 },
|
||||
{ id: "update", label: "Update\ncurrent_todos", type: "process", x: COL_LEFT, y: 410 },
|
||||
{ id: "update", label: "TodoManager\n.update()", type: "process", x: COL_LEFT, y: 410 },
|
||||
{ id: "other", label: "Run Tool", type: "subprocess", x: COL_CENTER, y: 410 },
|
||||
{ id: "reminder", label: "3 rounds?\nInject Reminder", type: "process", x: COL_RIGHT, y: 500 },
|
||||
{ id: "append", label: "Append Result", type: "process", x: COL_CENTER, y: 590 },
|
||||
@@ -602,9 +602,9 @@ const CURRENT_FLOW_OVERRIDES: Record<string, FlowDefinition> = {
|
||||
{ id: "start", label: "User Input", type: "start", x: COL_CENTER, y: 30 },
|
||||
{ id: "parent", label: "Parent LLM", type: "process", x: COL_CENTER, y: 120 },
|
||||
{ id: "task_check", label: "task tool?", type: "decision", x: COL_CENTER, y: 220 },
|
||||
{ id: "spawn", label: "Spawn Subagent\nfresh messages[]", type: "subprocess", x: COL_LEFT, y: 330 },
|
||||
{ id: "run", label: "Run Subagent\nfresh messages[]", type: "subprocess", x: COL_LEFT, y: 330 },
|
||||
{ id: "subloop", label: "Subagent Loop\nmax 30 turns", type: "process", x: COL_LEFT, y: 430 },
|
||||
{ id: "summary", label: "Return Summary\nOnly", type: "process", x: COL_LEFT, y: 530 },
|
||||
{ id: "final_text", label: "Return Final\nText", type: "process", x: COL_LEFT, y: 530 },
|
||||
{ id: "tool", label: "Run Parent Tool", type: "subprocess", x: COL_RIGHT, y: 330 },
|
||||
{ id: "append", label: "Append Result", type: "process", x: COL_CENTER, y: 630 },
|
||||
{ id: "end", label: "Output", type: "end", x: COL_RIGHT, y: 220 },
|
||||
@@ -612,12 +612,12 @@ const CURRENT_FLOW_OVERRIDES: Record<string, FlowDefinition> = {
|
||||
edges: [
|
||||
{ from: "start", to: "parent" },
|
||||
{ from: "parent", to: "task_check" },
|
||||
{ from: "task_check", to: "spawn", label: "task" },
|
||||
{ from: "task_check", to: "run", label: "task" },
|
||||
{ from: "task_check", to: "tool", label: "other" },
|
||||
{ from: "task_check", to: "end", label: "done" },
|
||||
{ from: "spawn", to: "subloop" },
|
||||
{ from: "subloop", to: "summary" },
|
||||
{ from: "summary", to: "append" },
|
||||
{ from: "run", to: "subloop" },
|
||||
{ from: "subloop", to: "final_text" },
|
||||
{ from: "final_text", to: "append" },
|
||||
{ from: "tool", to: "append" },
|
||||
{ from: "append", to: "parent" },
|
||||
],
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -17,8 +17,8 @@
|
||||
{
|
||||
"type": "tool_result",
|
||||
"toolName": "todo_write",
|
||||
"content": "Todos updated.",
|
||||
"annotation": "The current todo list is kept by the harness."
|
||||
"content": "[>] Inspect parser\n[ ] Refactor parsing branch\n[ ] Add regression test\n\n(0/3 completed)",
|
||||
"annotation": "The harness returns the current list to the model."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
@@ -28,8 +28,8 @@
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "<reminder>Update todo status after 3 rounds without todo_write.</reminder>",
|
||||
"annotation": "The nag reminder keeps the plan fresh during long work."
|
||||
"content": "<reminder>Update your todos.</reminder>",
|
||||
"annotation": "After three rounds without todo_write, the harness appends a reminder."
|
||||
},
|
||||
{
|
||||
"type": "assistant_text",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "s06",
|
||||
"title": "Subagent",
|
||||
"description": "The task tool spawns a fresh subagent context and returns only a final summary to the parent.",
|
||||
"description": "The task tool runs a nested agent loop with fresh messages and returns its final text to the parent.",
|
||||
"steps": [
|
||||
{
|
||||
"type": "user_message",
|
||||
@@ -16,20 +16,20 @@
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "spawn_subagent: messages=[{role:\"user\", content: prompt}], tools=bash/read/write/edit/glob",
|
||||
"annotation": "The child receives a fresh message history and no recursive task tool."
|
||||
"content": "run_subagent: messages=[{role:\"user\", content: prompt}], tools=bash/read/write/edit/glob",
|
||||
"annotation": "The subagent receives fresh messages and no task tool."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "read_file",
|
||||
"content": "{\"path\":\"cli.py\"}",
|
||||
"annotation": "Inside the child loop, intermediate tool calls stay private."
|
||||
"annotation": "The tool call stays in the subagent's local message list."
|
||||
},
|
||||
{
|
||||
"type": "tool_result",
|
||||
"toolName": "task",
|
||||
"content": "Summary: cli.py parses args, selects a command handler, then dispatches.",
|
||||
"annotation": "Only the subagent's final summary returns to the parent."
|
||||
"annotation": "The subagent's final text becomes the parent's task result."
|
||||
},
|
||||
{
|
||||
"type": "assistant_text",
|
||||
|
||||
@@ -51,8 +51,8 @@
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "spawn_teammate",
|
||||
"content": "{\"name\":\"backend\",\"role\":\"backend engineer\",\"prompt\":\"Claim the authentication task and propose a plan.\"}",
|
||||
"annotation": "A persistent teammate receives focused work through the team runtime."
|
||||
"content": "{\"name\":\"backend\",\"role\":\"backend engineer\",\"prompt\":\"Claim the authentication task and propose a plan.\",\"require_plan\":true}",
|
||||
"annotation": "The plan gate is active before the teammate thread starts, so claim and mutation cannot race ahead of approval."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
@@ -62,13 +62,30 @@
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "plan_request(req_plan_7) -> plan_response(req_plan_7, approved=true)",
|
||||
"annotation": "Typed correlation and an approval gate protect mutating tools."
|
||||
"content": "claim_next_task(backend) -> task_1712345678_0042; task_store_lock commits owner=backend",
|
||||
"annotation": "The ownership check and persisted state transition share the cross-process task-store lock."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "request_plan",
|
||||
"content": "{\"teammate\":\"backend\",\"task\":\"Inspect the claimed authentication task and submit a plan before changing files.\"}",
|
||||
"annotation": "The Lead delivers the plan request for the current assignment; the gate was already active before the teammate thread started."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "claim_next_task(backend) -> task_1712345678_0042; task_lock commits owner=backend",
|
||||
"annotation": "The ownership check and state transition are atomic."
|
||||
"content": "backend submit_plan -> plan_approval_request(request_id=req_000007, task_id=task_1712345678_0042)",
|
||||
"annotation": "The request records the task and work version that the plan is meant to authorize."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "review_plan",
|
||||
"content": "{\"request_id\":\"req_000007\",\"approve\":true,\"feedback\":\"Proceed with the scoped refactor.\"}",
|
||||
"annotation": "Approval is correlated by request ID and cannot carry into a different assignment."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "plan_approval_response(request_id=req_000007, approve=true) -> backend",
|
||||
"annotation": "The teammate receives the typed response before mutating tools are released."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
@@ -84,7 +101,7 @@
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "backend -> Lead: result(auth refactor complete) -> idle_notification",
|
||||
"annotation": "Result and idle state are separate events; the teammate remains available."
|
||||
"annotation": "The task directory stays selected through the completion turn, then IDLE releases the assignment."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
|
||||
@@ -62,9 +62,14 @@
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "bash",
|
||||
"content": "{\"command\":\"npm run lint && npm run test\",\"run_in_background\":true}",
|
||||
"content": "{\"command\":\"python -m unittest tests.test_agent_teams_runtime\",\"run_in_background\":true}",
|
||||
"annotation": "Long-running validation goes through the background task path."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "permission: user approved the exact test command",
|
||||
"annotation": "Team confirmation does not authorize shell execution; the foreground turn asks separately before dispatch."
|
||||
},
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "connect_mcp",
|
||||
@@ -85,7 +90,7 @@
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "recover: background task done, teammate replied, deploy status result appended",
|
||||
"content": "task_notification(status=completed): tests passed; teammate result and deploy status appended",
|
||||
"annotation": "The integrated runtime folds asynchronous results back into the loop."
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
{
|
||||
"type": "tool_call",
|
||||
"toolName": "Workflow",
|
||||
"content": "{\"name\":\"review-changes\",\"description\":\"Review changed files across dimensions and verify each finding\",\"phases\":[\"Review\",\"Verify\"]}",
|
||||
"annotation": "One tool call hands deterministic orchestration to the workflow runtime."
|
||||
"content": "{\"name\":\"review-changes\",\"args\":{\"budget\":null}}",
|
||||
"annotation": "The model selects a saved workflow and arguments; the host registry supplies its trusted metadata and script."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "async_launched(runId=wf_review-changes_6779) -> task_started",
|
||||
"content": "async_launched(runId=wf_review-changes_0000000000001a7b) -> task_started",
|
||||
"annotation": "The runtime emits launch lifecycle events before it executes the script; this is not a tool result."
|
||||
},
|
||||
{
|
||||
@@ -36,19 +36,19 @@
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "task_notification(status=completed, outputFile=.runtime/wf_review-changes_6779.output.json)",
|
||||
"content": "task_notification(status=completed, outputFile=.runtime/wf_review-changes_0000000000001a7b.output.json)",
|
||||
"annotation": "The task emits its final lifecycle event after output is written."
|
||||
},
|
||||
{
|
||||
"type": "tool_result",
|
||||
"toolName": "Workflow",
|
||||
"content": "{\"launched\":{\"status\":\"async_launched\",\"runId\":\"wf_review-changes_6779\"},\"result\":{\"confirmed\":[]},\"task\":{\"status\":\"completed\"}}",
|
||||
"annotation": "The completed call returns once, with launch metadata, the workflow result, and task state together."
|
||||
"content": "{\"launched\":{\"status\":\"async_launched\",\"taskId\":\"local_workflow_wf_review-changes_0000000000001a7b\",\"taskType\":\"local_workflow\",\"runId\":\"wf_review-changes_0000000000001a7b\",\"workflowName\":\"review-changes\"},\"result\":{\"confirmed\":[{\"dimension\":\"security\",\"title\":\"audit:security #1\",\"severity\":\"high\"},{\"dimension\":\"style\",\"title\":\"audit:style #1\",\"severity\":\"high\"},{\"dimension\":\"security\",\"title\":\"audit:security #2\",\"severity\":\"medium\"},{\"dimension\":\"performance\",\"title\":\"audit:performance #2\",\"severity\":\"medium\"},{\"dimension\":\"correctness\",\"title\":\"audit:correctness #1\",\"severity\":\"low\"},{\"dimension\":\"performance\",\"title\":\"audit:performance #1\",\"severity\":\"low\"}]},\"task\":{\"taskId\":\"local_workflow_wf_review-changes_0000000000001a7b\",\"taskType\":\"local_workflow\",\"runId\":\"wf_review-changes_0000000000001a7b\",\"workflowName\":\"review-changes\",\"status\":\"completed\",\"usage\":{\"agents\":11,\"tokens\":352},\"progress\":[{\"type\":\"workflow_phase\",\"title\":\"Review\"},{\"type\":\"workflow_agent\",\"label\":\"audit:correctness\",\"phase\":\"Review\",\"status\":\"done\"},{\"type\":\"workflow_phase\",\"title\":\"Verify\"},{\"type\":\"workflow_agent\",\"label\":\"audit:security\",\"phase\":\"Review\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"audit:performance\",\"phase\":\"Review\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"audit:style\",\"phase\":\"Review\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:correctness:audit:correctness #1\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:security:audit:security #1\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:security:audit:security #2\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:performance:audit:performance #1\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:performance:audit:performance #2\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:style:audit:style #1\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_agent\",\"label\":\"verify:style:audit:style #2\",\"phase\":\"Verify\",\"status\":\"done\"},{\"type\":\"workflow_log\",\"message\":\"confirmed 6 real finding(s)\"}]}}",
|
||||
"annotation": "The deterministic sample returns its six fixture findings and measured runner usage; these are not claims about the repository."
|
||||
},
|
||||
{
|
||||
"type": "system_event",
|
||||
"content": "append Workflow tool_result -> messages[]",
|
||||
"annotation": "The main loop receives that single result and continues with the updated conversation."
|
||||
"annotation": "A main-loop integration can append this JSON-safe result and continue with the updated conversation."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user