Skip to content

feat: plan synthetic task#79

Closed
branchseer wants to merge 46 commits intomainfrom
feat_plan_synthetic
Closed

feat: plan synthetic task#79
branchseer wants to merge 46 commits intomainfrom
feat_plan_synthetic

Conversation

@branchseer
Copy link
Copy Markdown
Member

@branchseer branchseer commented Jan 4, 2026

Support directly planning synthetic tasks like pnpm install before the real task execution.

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@branchseer branchseer changed the title feat: tui feat: plan synthetic task Jan 4, 2026
branchseer and others added 18 commits January 7, 2026 18:29
…rter

Implements the full execution loop in the new session architecture, enabling actual task execution with intelligent caching and formatted output.

Core changes:
- Implement execute_spawn() with fspy tracking for file system access monitoring
- Create PostRunFingerprint for content-based cache invalidation
- Wire up LabeledReporter for formatted execution output with cache status
- Migrate cache to use SpawnFingerprint from vite_task_plan
- Add workspace_path() getter and make session module public

Test infrastructure:
- Add vite-task-smoke e2e test with replace-file-content utility
- Add duration redaction to snapshot tests
- Verify cache hit/miss detection with file modifications

The execution now properly tracks file reads, validates fingerprints, and displays execution progress with cache status indicators.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace ExecuteError enum with event-based error reporting through the Reporter trait. Errors are now emitted as events and stop execution immediately via internal ExecutionAborted error.

Key changes:
- Add Reporter trait with handle_event() and post_execution() methods
- Remove ExecuteError and PathError enums
- Make ExecutionItemDisplay optional in Start event (None for top-level, Some for nested)
- Convert all error returns to error events
- Add internal ExecutionAborted type for error propagation via ? operator
- Update Session::execute to accept Box<dyn Reporter> instead of closure
- Implement Reporter trait for LabeledReporter with error tracking
- Fix top-level leaf execution for built-in commands
- Add cycle dependency error test fixture

All tests pass with updated snapshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Set NO_COLOR=1 environment variable when running e2e tests to disable ANSI color codes in output. This makes snapshots more readable and less fragile.

Updated all affected snapshots to contain plain text without color codes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove direct stdout/stderr writing from collect_std_outputs since
we're now using event-based reporting through the Reporter trait.
Previously, output was written twice:
1. Directly to stdout/stderr in spawn.rs
2. Through events in the Reporter

Also remove the duplicate public handle_event method from
LabeledReporter - only the trait implementation is needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Modified spawn_with_tracking to accept an optional callback that is
invoked immediately when stdout/stderr data arrives, rather than
buffering all output and emitting events after the process completes.

This enables:
- Real-time output streaming to the user
- Better interactivity for long-running tasks
- Reduced memory usage for large outputs

The callback is wrapped in a Mutex to allow sharing between the
concurrent stdout and stderr collection tasks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Simplified the concurrent stdout/stderr handling by:
- Removed collect_std_outputs helper function
- Made on_output parameter non-optional (always required)
- Used tokio::select! to read from both streams concurrently
- Eliminated Mutex wrapper since callback can be called directly
- Cleaned up unused imports (Mutex, try_join3, AsyncRead)

This approach is simpler, more efficient, and avoids the overhead
of mutex locking on every output chunk.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extracted common output processing logic into a closure to eliminate
code duplication between stdout and stderr handling. The closure:
- Emits events immediately via on_output callback
- Merges consecutive outputs of the same kind for caching

This reduces the select! arms from ~20 lines each to just 4 lines,
making the code more maintainable without introducing Mutex overhead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tests verify that tasks with cache: false skip caching on subsequent runs,
while tasks with cache: true properly cache and hit on second execution.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This refactoring moves cache status information to the Start event so users
see cache status (hit/miss/disabled) immediately when execution begins, rather
than after completion. It also adds detailed cache miss reasons and separates
display formatting from coloring to properly respect NO_COLOR.

Key changes:
- Update CacheStatus::Miss to carry detailed CacheMiss information
- Add CacheDisabledReason variants (NoCacheMetadata, CycleDetected)
- Create reusable display module for cache status formatting (plain text)
- Move coloring logic to LabeledReporter to respect NO_COLOR
- Determine cache status BEFORE emitting Start event in execute_spawn
- Update reporter to display inline cache status during execution
- ALWAYS emit Start event, including for cache hits

Benefits:
- Immediate user feedback on cache status at execution start
- Detailed cache miss reasons (file changed, command changed, etc.)
- Proper NO_COLOR environment variable support via ColorizeExt
- Simplified reporter state (cache_status now non-optional)
- Consistent event emission for all execution paths

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add cache_disabled count to Statistics line for complete breakdown
- Hide "0 cache disabled" when count is zero to keep output clean
- Change "no cache metadata" to "Cache disabled in task configuration" for clarity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add silent_if_cache_hit option to suppress output for cache hits
- Add hide_summary option to skip printing execution summary
- Track cache hit executions to filter their output
- Both options default to false for backward compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
For single built-in commands (like `vite lint`), show just the cache status
instead of the full summary with Statistics and Task Details sections.

Before:
  Statistics:   1 tasks • 0 cache hits • 1 cache misses
  Performance:  0% cache hit rate

  Task Details:
  ────────────────────────────────────────────────
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

After:
  → Cache miss: no previous cache entry found

This provides a cleaner, less cluttered output for simple commands while
still showing important cache information.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Hide "no previous cache entry found" in simplified summary for clean
  first-run output (NotFound cache miss)
- Add comprehensive documentation to LabeledReporter explaining all
  output modes (Normal, Silent Cache Hit, Hidden Summary, Simplified)
- Add inline comments for reporter configuration fields

This keeps first-run output clean showing only stdout/stderr while
still displaying meaningful cache status for subsequent runs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Expose plan_synthetic_task as a public API method to allow external
callers to plan and execute synthetic tasks programmatically.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Removed 9 legacy modules (~3,113+ lines) that are not used by the Session
API or vite_task_bin:

- cache.rs (283 lines) - Old TaskCache, replaced by session/cache
- config/ directory - Old task configuration, not used by session API
- error.rs - Old Error enum, replaced with anyhow::Error
- execute.rs (1,080 lines) - Old execution, replaced by session/execute
- fingerprint.rs (759 lines) - Old fingerprinting
- fs.rs (321 lines) - Old FileSystem trait
- schedule.rs (249 lines) - Old ExecutionPlan, replaced by vite_task_plan
- types.rs (7 lines) - Only used by config module
- ui.rs (414 lines) - Old UI formatting, replaced by session/reporter

Updated lib.rs to export only what vite_task_bin needs:
- CLIArgs for CLI parsing
- Session API (Session, SessionCallbacks, TaskSynthesizer, Reporter, LabeledReporter)
- Re-exports from vite_task_graph (loader) and vite_task_plan (plan_request)

Updated session modules to use anyhow::Error instead of the deleted custom Error type.

Result: Ultra-lean public API focused entirely on the Session-based interface.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@branchseer branchseer closed this Jan 9, 2026
@branchseer branchseer deleted the feat_plan_synthetic branch January 9, 2026 15:09
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.

1 participant