Files
poimen-workflows/tasks/T0.4.md
T
Test 11a1c1196a 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
2026-08-20 22:41:54 -07:00

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.StreamTimeout before 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 TestPiErrors passes all 6 test cases
  • All error buckets correctly classified
  • No panics on nil pointers
  • Error messages include HTTP status code