Add testable task descriptions: T0.1 through T0.9
Each task includes: - Scope: what to build - Implementation: code sketches + details - Verification: concrete test criteria - Done criteria: acceptance checklist
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
# T0.6: TaskUnit Workflow
|
||||
|
||||
## Scope
|
||||
Implement `statemachine/taskunit.go` with retry loops, timeout escalation, and lessons injection.
|
||||
|
||||
## Implementation
|
||||
|
||||
### File: `statemachine/taskunit.go`
|
||||
```go
|
||||
func TaskUnitWorkflow(ctx workflow.Context, in TaskUnitInput) (TaskUnitOutput, error)
|
||||
// 1. Call GitWorktreeAddActivity(ctx, {RepoPath, TaskID}) → get worktree path
|
||||
// 2. Lessons file init: try ReadLessonsActivity, may be empty on first run
|
||||
// 3. Retry loop:
|
||||
// timeoutAttempt := 1
|
||||
// for judgeAttempt := 1; judgeAttempt <= in.MaxJudgeRetries; judgeAttempt++
|
||||
//
|
||||
// SetupActivity options:
|
||||
// StartToCloseTimeout: in.BaseTimeout * time.Duration(timeoutAttempt)
|
||||
// HeartbeatTimeout: (in.BaseTimeout * time.Duration(timeoutAttempt)) / 4
|
||||
// RetryPolicy: {MaximumAttempts: 1} // NO retries; we manage them in the loop
|
||||
//
|
||||
// Call ImplementerActivity(ctx, {Lessons: lessons, ...})
|
||||
// If isStartToCloseTimeout(err):
|
||||
// timeoutAttempt++
|
||||
// judgeAttempt-- // don't consume a judge retry on timeout
|
||||
// continue // next loop iteration has longer timeout
|
||||
// If err != nil:
|
||||
// return TaskUnitOutput{Verdict: "fail", Critique: err.Error()}, nil
|
||||
//
|
||||
// Call RunIntegrationTestActivity(ctx, {WorktreePath, TestCmd})
|
||||
// If integration test fails:
|
||||
// // Some tasks don't have tests; pass if no test defined
|
||||
//
|
||||
// Call JudgeActivity(ctx, {Diff, IntegrationTestResult})
|
||||
// If judge.Verdict == "pass":
|
||||
// Call GitCommitActivity(ctx, {WorktreePath, "T0.x: implementation"})
|
||||
// return TaskUnitOutput{Verdict: "pass", Branch: "task/T0.x"}
|
||||
// Else:
|
||||
// Call UpdateLessonsActivity(ctx, {Critique})
|
||||
// lessons = ReadLessonsActivity() // updated lessons for next attempt
|
||||
// continue // next judgeAttempt with lessons injected
|
||||
// End retries
|
||||
//
|
||||
// 4. If we exit loop without pass: return fail verdict
|
||||
```
|
||||
|
||||
## Retry Logic Detail
|
||||
|
||||
**TimeoutAttempt vs JudgeAttempt:**
|
||||
- TimeoutAttempt: activity ran out of time, next attempt has longer StartToCloseTimeout
|
||||
- JudgeAttempt: activity finished but output wrong, lessons injected, duration doesn't change
|
||||
- They're independent counters so timeout escalation doesn't consume judge retries
|
||||
|
||||
**Lessons injection:**
|
||||
- Before each ImplementerActivity, render prompt with Lessons appended: "Known errors from prior attempts:\n{lessons}"
|
||||
- On judge failure, append new lesson to lessons file
|
||||
- Lessons persist within TaskUnitWorkflow (shared memory)
|
||||
- Lessons also written to disk (tasks/.orchestrator/lessons/<TaskID>.jsonl) for Planner's review
|
||||
|
||||
## Verification
|
||||
```bash
|
||||
cd /Users/rockliang/workplace/Poimen/workflows
|
||||
go test -v ./tests -run TestTaskUnit
|
||||
|
||||
# Test file: tests/taskunit_workflow_test.go
|
||||
```
|
||||
|
||||
Test cases (mocked activities):
|
||||
1. **Pass on first try:** Implementer→TestPass→JudgePass → return pass
|
||||
2. **Fail then pass after lesson:** Implementer→TestPass→JudgeFail (append lesson) → Implementer (lessons injected)→TestPass→JudgePass → return pass
|
||||
3. **Retries exhausted:** Implementer→JudgeFail 3 times → return fail
|
||||
4. **Timeout escalation:** Implementer timeout 1st → BaseTimeout*1 fails, Implementer timeout 2nd → BaseTimeout*2 succeeds → continue
|
||||
|
||||
## Done Criteria
|
||||
- `go test ./tests -run TestTaskUnit` passes all 4 cases
|
||||
- Split timeout/judge-fail counters work correctly
|
||||
- Lessons inject into prompt without error
|
||||
- No infinite loops on mocked failures
|
||||
Reference in New Issue
Block a user