Repository navigation
Record agents spawned by Claude Code's Workflow tool - #2687
peyton-alt wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit af049a2. Configure here.
| _, err := os.Stat(path) | ||
| return err == nil | ||
| } | ||
|
|
There was a problem hiding this comment.
Workflow files missed at turn end
Medium Severity
ExtractAllModifiedFiles still discovers children only via ExtractSpawnedAgentIDs and the direct agent-<id>.jsonl layout. CalculateTotalTokenUsage in the same file now uses subagentTranscriptPaths so workflow runs named by Run ID: are included, but turn-end file extraction never opens subagents/workflows/<runId>/. Workflow edits that appear only in those transcripts are omitted from the parent turn's transcript-derived file list.
Reviewed by Cursor Bugbot for commit af049a2. Configure here.
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Token discovery can misattribute usage, a fixture fails on Windows, and transcript lookup repeats full directory scans.
Review effort: Balanced
Findings: 2
Open (3)
What changed in this PR
Adds Claude Code Workflow-agent capture to Entire’s checkpoint pipeline, addressing missing task records, transcripts, and session token totals in #2685.
Changes:
- Registers Workflow-specific launch hooks and idempotent task records.
- Shares transcript resolution and includes launched Workflow runs in token accounting.
- Adds regression coverage and updates lifecycle documentation.
| File | Description |
|---|---|
| docs/development/filesystem-safety.md | Documents Workflow directory reads. |
| docs/architecture/sessions-and-checkpoints.md | Explains Workflow task lifecycle. |
| docs/architecture/agent-integration-checklist.md | Adds Workflow launch guidance. |
| docs/architecture/agent-guide.md | Updates event contracts. |
| cmd/entire/cli/validation/validators.go | Validates Workflow run IDs. |
| cmd/entire/cli/validation/validators_test.go | Tests run-ID validation. |
| cmd/entire/cli/transcript.go | Uses shared transcript resolver. |
| cmd/entire/cli/transcript_test.go | Tests Workflow transcript lookup. |
| cmd/entire/cli/strategy/manual_commit_condensation.go | Shares condensation transcript lookup. |
| cmd/entire/cli/strategy/manual_commit_condensation_test.go | Tests Workflow fallback resolution. |
| cmd/entire/cli/session/state.go | Documents agent-keyed task records. |
| cmd/entire/cli/paths/subagent_transcript.go | Adds shared transcript discovery. |
| cmd/entire/cli/paths/subagent_transcript_test.go | Tests layouts and discovery restrictions. |
| cmd/entire/cli/lifecycle.go | Preserves repeated launches and improves diagnostics. |
| cmd/entire/cli/lifecycle_test.go | Tests repeated-launch preservation. |
| cmd/entire/cli/integration_test/subagent_workflow_test.go | Covers Workflow capture and mid-run commits. |
| cmd/entire/cli/integration_test/hooks.go | Adds Workflow hook simulation. |
| cmd/entire/cli/integration_test/agent_test.go | Updates installed-hook expectations. |
| cmd/entire/cli/hook_registry.go | Classifies the new subagent hook. |
| cmd/entire/cli/agentimport/claude_test.go | Tests launching-turn token attribution. |
| cmd/entire/cli/agent/event.go | Adds idempotent-launch flag. |
| cmd/entire/cli/agent/claudecode/types.go | Adds Workflow hook payload types. |
| cmd/entire/cli/agent/claudecode/transcript.go | Discovers Workflow runs and aggregates tokens. |
| cmd/entire/cli/agent/claudecode/transcript_test.go | Tests token discovery and deduplication. |
| cmd/entire/cli/agent/claudecode/lifecycle.go | Parses Workflow launch events. |
| cmd/entire/cli/agent/claudecode/lifecycle_test.go | Tests launch parsing and filtering. |
| cmd/entire/cli/agent/claudecode/hooks.go | Installs, removes, and checks the hook. |
| cmd/entire/cli/agent/claudecode/hooks_test.go | Tests hook configuration lifecycle. |
| .claude/settings.json | Enables the Workflow launch hook. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| func ExtractWorkflowRunIDs(transcript []TranscriptLine) []string { | ||
| var runIDs []string | ||
| forEachToolResultText(transcript, func(_, text string) { | ||
| if runID := extractIDAfter(text, "Run ID: ", true); runID != "" && | ||
| validation.ValidateWorkflowRunID(runID) == nil && !slices.Contains(runIDs, runID) { | ||
| runIDs = append(runIDs, runID) | ||
| } | ||
| }) | ||
| return runIDs | ||
| } |
| writeWorkflowFixture(t, filepath.Join(SubagentsDir(dir, sessionID), SubagentWorkflowsDirName, "wf_1", "agent-*.jsonl")) | ||
| assert.Empty(t, ResolveSubagentTranscriptPath(dir, sessionID, "")) | ||
| assert.Empty(t, ResolveSubagentTranscriptPath(dir, sessionID, "*")) | ||
| assert.Empty(t, ResolveSubagentTranscriptPath(dir, sessionID, "../x")) |
| if legacy := filepath.Join(transcriptDir, name); pathExists(legacy) { | ||
| return legacy | ||
| } | ||
| return WorkflowAgentTranscripts(subagentsDir)[agentID] |
Agents a Workflow tool call launches never reached Entire's launch hooks, which match only the Agent tool, so each SubagentStop found no in-flight record and was skipped: no task record, no transcript, no subagent tokens. Claude Code fires SubagentStart for each workflow agent with its agent_id and agent_type "workflow-subagent". Entire now installs that hook (matcher "workflow-subagent") and records a live task record keyed by the agent id; a repeated start does not reset it. SubagentStop then completes it from the agent's transcript under subagents/workflows/<run>/. Transcript fallbacks (commit while an agent runs, the SessionEnd sweep) also look in the run directory, and the session's subagent token total counts the agents of workflow runs the parent transcript launched. Existing installs need `entire enable` to add the hook; `entire status` and `entire doctor` report the hook config as outdated until then. Part of #2685 (per-task token usage is fixed separately). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Entire-Checkpoint: 01M49HRP4R4KHH7S665NYK4Y7W
af049a2 to
9d505c2
Compare
Session subagent tokens found Workflow runs only from the result text's "Run ID:" wording, and only the first one per result. They now also read the launch's structured toolUseResult.runId (taskType local_workflow), so a change in Claude Code's prose cannot silently drop workflow agents' tokens, and every "Run ID:" in a result counts. Also documents why turn-end file extraction does not look up workflow agents (they run after the parent's turn ends; their files reach the session through their task records) and that a Workflow launched from inside a subagent is not counted in the parent's subagent_tokens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Entire-Checkpoint: 01M4A5R5RF266YDVKTBWHTXY7V
…ranscript An agent ID found in two runs (a resumed run can carry an agent) took whichever run was read last, in both the by-ID transcript lookup and the session subagent token count. Both now keep the most recently modified transcript, so the result does not depend on read order and the agent is counted once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Entire-Checkpoint: 01M4A6HQTHQV74Y0TW000AHCJ4




https://entire.io/gh/entireio/cli/trails/1505
Summary
Agents that Claude Code's
Workflowtool launches left no trace in the checkpoint: notasks/entry, no stored transcript, no subagent tokens. Entire's launch hooks (PreToolUse/PostToolUse) match only theAgenttool, so a workflow agent never got an in-flight record, and each of itsSubagentStopevents was skipped as "no live in-flight marker".Claude Code fires
SubagentStartfor every workflow agent withagent_idandagent_type: "workflow-subagent". This PR:SubagentStarthook with matcherworkflow-subagent, so directAgentlaunches never invoke it (the parser also ignores any other agent type);agent_id(a Workflow call'stool_use_idis shared by all its agents); a repeated start cannot reset a record still in session state;SubagentStopcorrelation byagent_idcomplete it fromagent_transcript_pathundersubagents/workflows/<run>/;pathsthat replaces two duplicates;subagent_tokens, for the runs the parent transcript launched (the launch's structuredtoolUseResult.runId, with the result'sRun ID: wf_…text as a fallback), soentire importputs their tokens on the launching turn; an agent found in more than one run counts once, from its newest transcript;agent_id/agent_typewhen aSubagentStopis skipped.Existing installs get the new hook with
entire enable; until thenentire statusandentire doctorreport the Claude hook config as outdated.Part of #2685: this PR gives each workflow agent a task record and counts them in the session's subagent tokens. Each record's own
token_usageis still undercounted (see below), which is being fixed in a separate PR; #2685 should close once both are in.Verified
tasks/<agent_id>/×3 withtask.json, the agent transcript and the right file;checkpoint explain --jsonlists 3 tasks. Sessionsubagent_tokensequals the summedmessage.usageof the three agent transcripts before and after the commit, with no double counting in a later checkpoint. A directAgentsubagent in the same session still gets exactly onetoolu_…-keyed record, and Entire'ssubagent-startdid not run for it. No warnings inentire.log.main: notasks/,"tasks": [], nosubagent_tokens, three skippedSubagentStops.mise run checkpasses. New tests (hook install/upgrade/uninstall/health, parse filter, repeated start, resolver layout, token discovery and dedup, import turn split, two integration tests including a commit while the agent is still running) fail onmain.Not in this PR
token_usageundercounts: it is computed atSubagentStop, before Claude Code has written the agent's final message to its transcript, so a task record misses its last API call(s) while the stored transcript has them (live:task.json1 call, stored transcript 2). The same race exists onmainfor directAgentsubagents. Sessionsubagent_tokensis computed later and is correct. Fix in a separate PR offmain(recompute each task's tokens from the transcript stored at checkpoint time).filescome from the agent's transcript, so files an agent changes through Bash (echo >>) are not listed on its record; they still appear in the session'sfiles_touched. Same as directAgentsubagents.SubagentStopfor three agents; two live runs here produced exactly three. The skip log now includesagent_idandagent_type, so a repeat can be identified.session adoptdoes not yet accept a workflow agent's transcript path.tool_use_ids.🤖 Generated with Claude Code