fix(task): improve task lifecycle UX with 6 targeted fixes#21
Merged
josephgoksu merged 2 commits intomainfrom Mar 8, 2026
Merged
fix(task): improve task lifecycle UX with 6 targeted fixes#21josephgoksu merged 2 commits intomainfrom
josephgoksu merged 2 commits intomainfrom
Conversation
- Auto-infer session_id from hook_session.json when MCP transport doesn't provide one, eliminating friction on every task transition - Add task skip action (pending/in_progress → skipped) with reason - Treat skipped tasks as resolved in dependency graph (GetNextTask) - Add StatusSkipped to task model - Hook continue-check: graceful degradation with /tw-next fallback - Plan generate: respect explicit tasks array, bypass LLM when provided - Anti-overlap instructions in planner/decompose/expand prompts
internal/app/plan.go
Outdated
Comment on lines
82
to
90
| // ExplicitTask is a caller-provided task definition that bypasses LLM generation. | ||
| type ExplicitTask struct { | ||
| Title string | ||
| Description string | ||
| AcceptanceCriteria []string | ||
| ValidationSteps []string | ||
| Priority int | ||
| Complexity string | ||
| } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Move TaskInput to task package, alias in mcp/types.go, and remove manual field-by-field mapping in handlers. Addresses Greptile review.
Owner
Author
|
Addressed Greptile review comment (DRY violation for |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Addresses 6 task lifecycle UX defects identified during real-world plan execution:
hook_session.jsonwhen MCP transport doesn't provide one — eliminates the friction of everytask action=nextfailing on first attemptskipaction (pending/in_progress → skipped) with reason tracking, plus skipped tasks treated as resolved in dependency graphcontinue-checkgracefully degrades with/tw-nextfallback instead of failing silently when repo can't be openedplan action=generatenow respects caller-providedtasksarray, bypassing LLM generation entirelyskippedstatus to task lifecycle state machineChanged files
cmd/mcp_server.gocmd/hook.go/tw-nextfallbackinternal/mcp/types.goTaskActionSkipenum valueinternal/mcp/handlers.gohandleTaskSkiphandler, explicit tasks passthroughinternal/memory/task_store.goSkipTask()method, dependency query fixinternal/memory/repository_tasks.goSkipTaskwrapperinternal/task/models.goStatusSkippedconstantinternal/app/plan.goExplicitTasktype, early return pathinternal/config/prompts.goTest plan
go build ./...passesgo test ./internal/memory/... ./internal/mcp/... ./internal/task/... ./internal/config/... ./internal/app/...— 19 tests passtask action=skipvia MCP with a pending tasktask action=nextworks without explicit session_idplan action=generatewith explicit tasks array bypasses LLM/tw-nextfallback on repo errorGreptile Summary
This PR delivers 6 targeted UX improvements to the task lifecycle: session ID auto-inference from
hook_session.json, a newskipaction with dependency-graph awareness, hook graceful degradation with/tw-nextfallback hints, explicit tasks passthrough forplan action=generate, anti-overlap prompt instructions across all three agent prompts, and theStatusSkippedmodel constant.The core mechanics are correct — the SQL dependency fix (
NOT IN (completed, skipped)), theSkipTasklifecycle implementation, and the session inference fallback all work as intended. However, there are several documentation gaps that create usability friction:TaskToolParamsstruct comment omits the newly addedskipaction, leaving callers without documentation of what it does or what fields it requires.PlanToolParams.Tasksfield is documented only forexpandbut is now silently also consumed bygeneratewith entirely different semantics (user edits vs. LLM-bypass), creating a trap for callers who won't know what behavior to expect.ExplicitTaskininternal/app/plan.gois structurally identical toTaskInputininternal/mcp/types.gowith a manual field-by-field mapping that creates maintenance burden — any future field additions must be made in three places.statuscolumn insqlite.gostill lists the old set of allowed values and doesn't includeskipped.Confidence Score: 4/5
TaskToolParamsstruct comment omitsskipaction,PlanToolParams.Tasksfield silently dual-purposed for two actions with different semantics but only one documented); (2) DRY violation in type design (ExplicitTaskduplicatesmcp.TaskInputstructure with manual field-by-field mapping). All logic changes are correct: SQL parameter count matches placeholders,SkipTaskrows-affected guard prevents silent no-ops, session inference is properly nil/empty-guarded, explicit tasks bypass is cleanly isolated.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A([pending]) -->|task action=start| B([in_progress]) A -->|task action=skip| E([skipped]) B -->|task action=complete| C([verifying]) B -->|task action=skip| E C -->|validation pass| D([completed]) C -->|validation fail| F([failed]) subgraph Dependency Resolution D -->|unblocks dependents| G{GetNextTask} E -->|treated as resolved| G G -->|NOT IN completed,skipped| H([next pending task]) end subgraph Session ID Inference I[MCP tool call] --> J{session.ID available?} J -->|yes| K[use transport session ID] J -->|no| L{hook_session.json exists?} L -->|yes, SessionID != empty| M[use hook session ID] L -->|no| N[empty session ID / caller must provide] endComments Outside Diff (3)
internal/mcp/types.go, line 141-152 (link)The
TaskToolParamsstruct comment still lists onlynext, current, start, completeand omits the newly addedskipaction. This leaves callers without documentation of whatskipdoes or what fields it requires.Prompt To Fix With AI
internal/mcp/types.go, line 335-337 (link)PlanToolParams.Tasksis now silently used by bothexpandandgenerateactions with completely different semantics, but the documentation only mentionsexpand. This undocumented dual-use creates a trap for callers: if they sendtaskstogenerateexpectingexpand-style feedback behavior, they'll instead trigger LLM-bypass behavior.Also update the
PlanToolParamsrequired-fields comment block to documenttasksas optional for both actions.Prompt To Fix With AI
internal/memory/sqlite.go, line 199 (link)The inline schema comment lists allowed status values but was not updated to include
skipped.Prompt To Fix With AI
Last reviewed commit: cb4e9db