Skip to content

refactor: unify duplicated agent execution lifecycles into shared pipeline#509

Merged
zbigniewsobiecki merged 1 commit intodevfrom
refactor/unify-agent-execution-lifecycles
Feb 23, 2026
Merged

refactor: unify duplicated agent execution lifecycles into shared pipeline#509
zbigniewsobiecki merged 1 commit intodevfrom
refactor/unify-agent-execution-lifecycles

Conversation

@aaight
Copy link
Copy Markdown
Collaborator

@aaight aaight commented Feb 23, 2026

Summary

  • Extracts a shared executeAgentPipeline() function in src/agents/shared/executionPipeline.ts that unifies the ~250 lines of identical orchestration code duplicated between adapter.ts (Claude Code backend) and lifecycle.ts (LLMist backend)
  • Refactors both executeWithBackend (adapter.ts) and executeAgentLifecycle (lifecycle.ts) to delegate the outer scaffold to the shared pipeline
  • Extracts createLogWriter helper (previously duplicated in adapter.ts) into the shared module
  • Adds 25 new unit tests for executeAgentPipeline covering: CWD restoration, watchdog integration, cleanup behavior, error handling, run tracking via setRunId, and finalizeMetadata propagation
  • Updates the Sentry captureException test to reflect that the shared pipeline uses source: 'agent_execution' (previously backend_execution in adapter.ts)

What changed

New file: src/agents/shared/executionPipeline.ts

  • AgentPipelineOptions interface with an execute strategy callback
  • PipelineContext providing repoDir, fileLogger, logWriter, runId, setRunId
  • executeAgentPipeline() — the 16-step shared scaffold: FileLogger → Watchdog → Repo setup → Env snapshot → Squint DB → Run tracking → CWD change → Execute → Restore CWD → Finalize run → Cleanup
  • createLogWriter() — shared helper extracted from adapter.ts

Refactored: src/backends/adapter.ts

  • executeWithBackend now delegates outer scaffold to executeAgentPipeline
  • Run creation (needs model/maxIterations from buildBackendInput) moved inside execute callback using ctx.setRunId()

Refactored: src/agents/shared/lifecycle.ts

  • executeAgentLifecycle now delegates outer scaffold to executeAgentPipeline
  • LLMist-specific finalization (LLM call accumulation, llmIterations, gadgetCalls) handled via FinalizeRunOutcome.metadata

New file: tests/unit/agents/shared/executionPipeline.test.ts

  • 25 tests covering all pipeline behaviors

Test plan

  • All 2820 tests pass (npm test)
  • TypeScript type checking passes (npm run typecheck)
  • Lint passes (npm run lint)

Card: https://trello.com/c/BR9j1dGp/93-refactor-unify-duplicated-agent-execution-lifecycles-in-adapterts-and-lifecyclets

🤖 Generated with Claude Code

@aaight
Copy link
Copy Markdown
Collaborator Author

aaight commented Feb 23, 2026

🤔 Just a sec, looking into that PR refactor now

@aaight
Copy link
Copy Markdown
Collaborator Author

aaight commented Feb 23, 2026

👋 I'm monitoring this PR. Currently waiting for:

  1. ⏳ CI checks to complete (lint-and-test still running)
  2. 📝 Review feedback to be posted

Once the checks pass and reviews are submitted, I'll address any feedback. The refactoring looks clean - nice work extracting the shared execution pipeline! ✨

@aaight
Copy link
Copy Markdown
Collaborator Author

aaight commented Feb 23, 2026

🔍 Reviewing code — Examining the PR changes for quality and correctness...

Copy link
Copy Markdown
Collaborator

@nhopeatall nhopeatall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Clean refactoring that extracts ~250 lines of duplicated orchestration code into a shared executeAgentPipeline(). The change is behavior-preserving, well-tested, and correctly structured.

Verification Notes

Behavior-preserving: Traced all key execution paths (success, failure, watchdog timeout, cleanup) and confirmed semantic equivalence:

  • CWD save/restore ✓
  • Env snapshot load/unload ✓
  • Squint DB setup/teardown ✓
  • Run tracking creation ✓
  • Finalize run on all exit paths (success, failure, watchdog) ✓
  • Cleanup in finally block with skipRepoDeletion
  • Log buffer priority (effectively unchanged — both backends return undefined logBuffer, so fileLogger fallback is always used) ✓

Intentional behavioral changes (minor, improvements):

  • Sentry source tag unified from backend_execution/agent_lifecycleagent_execution (noted in PR, test updated)
  • Adapter watchdog now also reports to Sentry via captureException (previously only lifecycle did this) — an improvement
  • backend tag removed from adapter Sentry error reports (minor observability reduction, agent identifier still provides context)

Type duplication: LogWriter type now exists in 3 places (backends/types.ts, agents/utils/hooks.ts, agents/shared/executionPipeline.ts). The first two pre-date this PR. Consider consolidating to a single canonical export in a future pass.

Circular dependency chain: executionPipeline.tscleanup.tslifecycle.tsexecutionPipeline.ts. This is safe because cleanup.ts and runTracking.ts only import types from lifecycle.ts, which get erased at runtime. No circular runtime dependency exists. Consider having cleanup.ts and runTracking.ts import FileLogger directly from executionPipeline.ts to make the dependency graph cleaner.

All 53 tests pass. CI is green. The strategy callback pattern is a good fit for this problem.

@zbigniewsobiecki zbigniewsobiecki merged commit bba2156 into dev Feb 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants