Each task includes: - Scope: what to build - Implementation: code sketches + details - Verification: concrete test criteria - Done criteria: acceptance checklist
2.1 KiB
2.1 KiB
T0.4: Pi & Error Classification
Scope
Implement action/skills.go with PrepareSkillsActivity and classifyPiErr for skill prep via homelab API.
Implementation
File: action/skills.go
type SkillRef struct {
Name string
URL string
}
type PrepareSkillsInput struct {
Skills []SkillRef
StreamTimeout time.Duration
}
func PrepareSkillsActivity(ctx context.Context, in PrepareSkillsInput) error
// For each skill, run: pi clone-or-fetch $skill.URL
// Pass --stream-timeout=$StreamTimeout to pi
// Each skill behind its own lock (not orchestrator.lock)
// On error, return classified error (see below)
func classifyPiErr(err error) error
// 4xx (400-499): NonRetryableApplicationError "PiClientError"
// 504: ApplicationError "PiStreamTimeout"
// 5xx (500-599, except 504): leave retryable
// Other network errors: leave retryable
Error Buckets
Bucket 1: 4xx (PiClientError)
- Status code 400-499
- Non-retryable: bad request, auth error, not found
- Temporal stops retrying immediately
- Activity fails
Bucket 2: 5xx except 504 (generic 5xx)
- Status code 500-503, 505-599
- Retryable: server error, likely transient
- Temporal backs off + retries until
ScheduleToCloseTimeout(5m)
Bucket 3: 504 (PiStreamTimeout)
- Status code 504
- Means pi's SSE stream-read timed out
- Retryable, BUT: Orchestrator doubles
config.Tuning.PiRetry.StreamTimeoutbefore retry - Next attempt uses wider timeout
Verification
cd /Users/rockliang/workplace/Poimen/workflows
go test -v ./tests -run TestPiErrors
# Test file: tests/pi_test.go
Test cases:
- Mock 400 response → NonRetryableApplicationError returned
- Mock 403 response → NonRetryableApplicationError returned
- Mock 500 response → retryable error returned
- Mock 503 response → retryable error returned
- Mock 504 response → ApplicationError type "PiStreamTimeout" returned
- Mock network timeout → retryable error returned
Done Criteria
go test ./tests -run TestPiErrorspasses all 6 test cases- All error buckets correctly classified
- No panics on nil pointers
- Error messages include HTTP status code