feat(workflows): wire TaskUnit/Orchestrator activities, add k8s deploy manifests
ci / test (push) Failing after 5s

Implements real activity-calling logic in OrchestratorWorkflow and
TaskUnitWorkflow (previously stubs), adds GitDiffActivity, and expands
PlanningActivity's I/O to carry repo path and prior task results.

Adds k8s/ deployment manifests (worker Deployment, orchestrator Job,
Kustomize base) for the poimen-workflows Temporal worker, using a
dedicated Kubernetes namespace `poimen` and Temporal namespace
`poimen-harness` rather than sharing the Temporal server's own
`temporal`/`production` namespaces.
This commit is contained in:
Test
2026-08-21 21:57:01 -07:00
parent e0947c5ed3
commit 002fe98e17
17 changed files with 702 additions and 22 deletions
+26
View File
@@ -190,3 +190,29 @@ func GitSquashMergeActivity(ctx context.Context, in GitSquashMergeInput) error {
return nil
}
// GitDiffInput is input to GitDiffActivity.
type GitDiffInput struct {
WorktreePath string
}
// GitDiffOutput is output of GitDiffActivity.
type GitDiffOutput struct {
Diff string
}
// GitDiffActivity gets git diff for a worktree.
func GitDiffActivity(ctx context.Context, in GitDiffInput) (GitDiffOutput, error) {
out := GitDiffOutput{Diff: ""}
// Get diff from worktree against main branch
cmd := exec.CommandContext(ctx, "git", "-C", in.WorktreePath, "diff", "main")
output, err := cmd.CombinedOutput()
if err != nil {
// Diff can fail if branch doesn't exist, treat as no changes
return out, nil
}
out.Diff = string(output)
return out, nil
}
+10 -6
View File
@@ -11,9 +11,11 @@ import (
// PlanningInput is input to PlanningActivity.
type PlanningInput struct {
Config statemachine.OrchestratorConfig
BoardState string // JSON or markdown of task board
Milestone string
Config statemachine.OrchestratorConfig
BoardState string // JSON or markdown of task board
RepoPath string // Path to target repository
Milestone string // e.g., "T0"
TaskResults []statemachine.TaskUnitOutput // Results from completed tasks
}
// TaskDispatch represents a dispatched task.
@@ -25,8 +27,9 @@ type TaskDispatch struct {
// PlanningOutput is the output of PlanningActivity.
type PlanningOutput struct {
Tasks []TaskDispatch
SubmilestoneComplete bool
TasksToDispatch []string // Task IDs to dispatch in this cycle
CompletedBranches []string // Branches to squash merge (when milestone complete)
SubmilestoneComplete bool // Whether the milestone is complete
}
// PlanningActivity calls the Planner LLM to decide which tasks to dispatch.
@@ -81,7 +84,8 @@ func PlanningActivity(ctx context.Context, in PlanningInput) (PlanningOutput, er
// This is a stub that allows the test to verify the activity is called
_ = response
return PlanningOutput{
Tasks: []TaskDispatch{},
TasksToDispatch: []string{},
CompletedBranches: []string{},
SubmilestoneComplete: false,
}, nil
}
+7 -2
View File
@@ -17,15 +17,20 @@ import (
type PrepareSkillsInput struct {
Skills []statemachine.SkillRef
StreamTimeout time.Duration
Provider string // pi provider name (e.g. "homelab-reasoning"); required, pi has no usable default provider
}
// PrepareSkillsActivity prepares skills for use via pi command.
func PrepareSkillsActivity(ctx context.Context, in PrepareSkillsInput) error {
if in.Provider == "" {
return fmt.Errorf("PrepareSkillsInput.Provider must be set (pi has no usable default provider)")
}
for _, skill := range in.Skills {
activity.RecordHeartbeat(ctx, skill.Name)
// Run: pi clone-or-fetch <skill-url> --stream-timeout=<duration>
cmd := exec.CommandContext(ctx, "pi", "clone-or-fetch", skill.URL, fmt.Sprintf("--stream-timeout=%s", in.StreamTimeout.String()))
// Run: pi clone-or-fetch <skill-url> --provider=<provider> --stream-timeout=<duration>
cmd := exec.CommandContext(ctx, "pi", "clone-or-fetch", skill.URL, "--provider="+in.Provider, fmt.Sprintf("--stream-timeout=%s", in.StreamTimeout.String()))
if err := cmd.Run(); err != nil {
// Classify error
classifiedErr := ClassifyPiErr(err, skill.Name)